Source Code Cross Referenced for ContinuationClassLoader.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » components » flow » java » 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 » Content Management System » apache lenya 2.0 » org.apache.cocoon.components.flow.java 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.cocoon.components.flow.java;
018:
019:        import java.util.ArrayList;
020:        import java.util.Vector;
021:
022:        import org.apache.bcel.Constants;
023:        import org.apache.bcel.Repository;
024:        import org.apache.bcel.classfile.ConstantCP;
025:        import org.apache.bcel.classfile.ConstantNameAndType;
026:        import org.apache.bcel.classfile.ConstantPool;
027:        import org.apache.bcel.classfile.ConstantUtf8;
028:        import org.apache.bcel.classfile.JavaClass;
029:        import org.apache.bcel.classfile.Method;
030:        import org.apache.bcel.generic.ACONST_NULL;
031:        import org.apache.bcel.generic.BasicType;
032:        import org.apache.bcel.generic.ClassGen;
033:        import org.apache.bcel.generic.ConstantPoolGen;
034:        import org.apache.bcel.generic.GOTO;
035:        import org.apache.bcel.generic.IFEQ;
036:        import org.apache.bcel.generic.IFNONNULL;
037:        import org.apache.bcel.generic.IFNULL;
038:        import org.apache.bcel.generic.INVOKESTATIC;
039:        import org.apache.bcel.generic.InstructionConstants;
040:        import org.apache.bcel.generic.InstructionFactory;
041:        import org.apache.bcel.generic.InstructionHandle;
042:        import org.apache.bcel.generic.InstructionList;
043:        import org.apache.bcel.generic.InstructionTargeter;
044:        import org.apache.bcel.generic.InvokeInstruction;
045:        import org.apache.bcel.generic.MethodGen;
046:        import org.apache.bcel.generic.ObjectType;
047:        import org.apache.bcel.generic.PUSH;
048:        import org.apache.bcel.generic.RET;
049:        import org.apache.bcel.generic.ReferenceType;
050:        import org.apache.bcel.generic.ReturnaddressType;
051:        import org.apache.bcel.generic.SWAP;
052:        import org.apache.bcel.generic.TABLESWITCH;
053:        import org.apache.bcel.generic.TargetLostException;
054:        import org.apache.bcel.generic.Type;
055:        import org.apache.bcel.util.ClassLoaderRepository;
056:        import org.apache.bcel.verifier.exc.AssertionViolatedException;
057:        import org.apache.bcel.verifier.structurals.ControlFlowGraph;
058:        import org.apache.bcel.verifier.structurals.ExceptionHandler;
059:        import org.apache.bcel.verifier.structurals.ExecutionVisitor;
060:        import org.apache.bcel.verifier.structurals.Frame;
061:        import org.apache.bcel.verifier.structurals.InstConstraintVisitor;
062:        import org.apache.bcel.verifier.structurals.InstructionContext;
063:        import org.apache.bcel.verifier.structurals.LocalVariables;
064:        import org.apache.bcel.verifier.structurals.OperandStack;
065:        import org.apache.bcel.verifier.structurals.UninitializedObjectType;
066:
067:        /**
068:         * The classloader breakes the methods of the classes into pieces and
069:         * add intercepting code to suspend the execution of the method.
070:         * 
071:         * This code is based on the original idea of the BRAKES project.
072:         * (http://www.cs.kuleuven.ac.be/~eddy/BRAKES/brakes.html).
073:         *
074:         * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
075:         * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
076:         * @version CVS $Id: ContinuationClassLoader.java 433543 2006-08-22 06:22:54Z crossley $
077:         */
078:        public class ContinuationClassLoader extends ClassLoader {
079:
080:            private static final String CONTINUATION_CLASS = Continuation.class
081:                    .getName();
082:            private static final ObjectType CONTINUATION_TYPE = new ObjectType(
083:                    CONTINUATION_CLASS);
084:
085:            private static final String STACK_CLASS = ContinuationStack.class
086:                    .getName();
087:            private static final ObjectType STACK_TYPE = new ObjectType(
088:                    STACK_CLASS);
089:
090:            private static final String CONTINUABLE_CLASS = Continuable.class
091:                    .getName();
092:
093:            private static final String CONTINUATIONCAPABLE_CLASS = ContinuationCapable.class
094:                    .getName();
095:
096:            private static final String CONTINUATION_METHOD = "currentContinuation";
097:            private static final String STACK_METHOD = "getStack";
098:            private static final String POP_METHOD = "pop";
099:            private static final String PUSH_METHOD = "push";
100:            private static final String RESTORING_METHOD = "isRestoring";
101:            private static final String CAPURING_METHOD = "isCapturing";
102:
103:            private static boolean currentMethodStatic;
104:
105:            public ContinuationClassLoader(ClassLoader parent) {
106:                super (parent);
107:                Repository.setRepository(new ClassLoaderRepository(parent));
108:            }
109:
110:            protected synchronized Class loadClass(String name, boolean resolve)
111:                    throws ClassNotFoundException {
112:                // this finds also classes, which are already transformed, via findLoadedClass
113:                Class c = super .loadClass(name, resolve);
114:
115:                // transform class if class is continuable and not continuation capable
116:                if ((Continuable.class.isAssignableFrom(c))
117:                        && (!ContinuationCapable.class.isAssignableFrom(c))
118:                        && (!c.isInterface())) {
119:                    JavaClass clazz = Repository.lookupClass(c);
120:
121:                    byte data[] = transform(clazz);
122:                    c = defineClass(name, data, 0, data.length);
123:                }
124:                if (c == null) {
125:                    throw new ClassNotFoundException(name);
126:                }
127:                if (resolve) {
128:                    resolveClass(c);
129:                }
130:                return c;
131:            }
132:
133:            private byte[] transform(JavaClass javaclazz)
134:                    throws ClassNotFoundException {
135:                // make all methods of java class continuable
136:                ClassGen clazz = new ClassGen(javaclazz);
137:                ConstantPoolGen cp = clazz.getConstantPool();
138:                // obsolete, but neccesary to execute the InvokeContext
139:                InstConstraintVisitor icv = new InstConstraintVisitor();
140:                icv.setConstantPoolGen(cp);
141:                // vistor to build the frame information
142:                ExecutionVisitor ev = new ExecutionVisitor();
143:                ev.setConstantPoolGen(cp);
144:
145:                Method[] methods = clazz.getMethods();
146:                for (int i = 0; i < methods.length; i++) {
147:                    MethodGen method = new MethodGen(methods[i], clazz
148:                            .getClassName(), cp);
149:
150:                    currentMethodStatic = methods[i].isStatic();
151:                    if (isValid(method)) {
152:                        // analyse the code of the method to create the frame
153:                        // information about every instruction
154:                        ControlFlowGraph cfg = new ControlFlowGraph(method);
155:                        analyse(clazz, method, cfg, icv, ev);
156:                        // add intercepting code 
157:                        rewrite(method, cfg);
158:                        // make last optional check for consistency
159:                        clazz.replaceMethod(methods[i], method.getMethod());
160:                    }
161:                }
162:                clazz.addInterface(CONTINUATIONCAPABLE_CLASS);
163:                return clazz.getJavaClass().getBytes();
164:            }
165:
166:            private boolean isValid(MethodGen m) {
167:                if (m.getName().equals(Constants.CONSTRUCTOR_NAME)
168:                        || m.getName()
169:                                .equals(Constants.STATIC_INITIALIZER_NAME)
170:                        || m.isNative() || m.isAbstract()) {
171:                    return false;
172:                } else {
173:                    return true;
174:                }
175:            }
176:
177:            private void analyse(ClassGen clazz, MethodGen method,
178:                    ControlFlowGraph cfg, InstConstraintVisitor icv,
179:                    ExecutionVisitor ev) {
180:                // build the initial frame situation for this method.
181:                Frame vanillaFrame = new Frame(method.getMaxLocals(), method
182:                        .getMaxStack());
183:                if (!method.isStatic()) {
184:                    if (method.getName().equals(Constants.CONSTRUCTOR_NAME)) {
185:                        Frame._this  = new UninitializedObjectType(
186:                                new ObjectType(clazz.getClassName()));
187:                        vanillaFrame.getLocals().set(
188:                                0,
189:                                new UninitializedObjectType(new ObjectType(
190:                                        clazz.getClassName())));
191:                    } else {
192:                        Frame._this  = null;
193:                        vanillaFrame.getLocals().set(0,
194:                                new ObjectType(clazz.getClassName()));
195:                    }
196:                }
197:                // fill local variables with parameter types
198:                Type[] argtypes = method.getArgumentTypes();
199:                int twoslotoffset = 0;
200:                for (int j = 0; j < argtypes.length; j++) {
201:                    if ((argtypes[j] == Type.SHORT)
202:                            || (argtypes[j] == Type.BYTE)
203:                            || (argtypes[j] == Type.CHAR)
204:                            || (argtypes[j] == Type.BOOLEAN)) {
205:                        argtypes[j] = Type.INT;
206:                    }
207:                    vanillaFrame.getLocals().set(
208:                            twoslotoffset + j + (method.isStatic() ? 0 : 1),
209:                            argtypes[j]);
210:                    if (argtypes[j].getSize() == 2) {
211:                        twoslotoffset++;
212:                        vanillaFrame.getLocals()
213:                                .set(
214:                                        twoslotoffset + j
215:                                                + (method.isStatic() ? 0 : 1),
216:                                        Type.UNKNOWN);
217:                    }
218:                }
219:                icv.setMethodGen(method);
220:
221:                Vector ics = new Vector(); // Type: InstructionContext
222:                Vector ecs = new Vector(); // Type: ArrayList (of InstructionContext)
223:
224:                InstructionContext start = cfg.contextOf(method
225:                        .getInstructionList().getStart());
226:
227:                start.execute(vanillaFrame, new ArrayList(), icv, ev);
228:                // new ArrayList() <=>  no Instruction was executed before
229:                //                  => Top-Level routine (no jsr call before)
230:                ics.add(start);
231:                ecs.add(new ArrayList());
232:
233:                while (!ics.isEmpty()) {
234:                    InstructionContext u = (InstructionContext) ics.remove(0);
235:                    ArrayList ec = (ArrayList) ecs.remove(0);
236:
237:                    ArrayList oldchain = (ArrayList) (ec.clone());
238:                    ArrayList newchain = (ArrayList) (ec.clone());
239:                    newchain.add(u);
240:
241:                    if ((u.getInstruction().getInstruction()) instanceof  RET) {
242:                        // We can only follow _one_ successor, the one after the
243:                        // JSR that was recently executed.
244:                        RET ret = (RET) u.getInstruction().getInstruction();
245:                        ReturnaddressType t = (ReturnaddressType) u
246:                                .getOutFrame(oldchain).getLocals().get(
247:                                        ret.getIndex());
248:                        InstructionContext theSuccessor = cfg.contextOf(t
249:                                .getTarget());
250:
251:                        if (theSuccessor.execute(u.getOutFrame(oldchain),
252:                                newchain, icv, ev)) {
253:                            ics.add(theSuccessor);
254:                            ecs.add(newchain.clone());
255:                        }
256:                    } else { // "not a ret"
257:                        // Normal successors. Add them to the queue of successors.
258:                        InstructionContext[] succs = u.getSuccessors();
259:                        for (int s = 0; s < succs.length; s++) {
260:                            InstructionContext v = succs[s];
261:                            if (v.execute(u.getOutFrame(oldchain), newchain,
262:                                    icv, ev)) {
263:                                ics.add(v);
264:                                ecs.add(newchain.clone());
265:                            }
266:                        }
267:                    }
268:                    // Exception Handlers. Add them to the queue of successors.
269:                    ExceptionHandler[] exc_hds = u.getExceptionHandlers();
270:                    for (int s = 0; s < exc_hds.length; s++) {
271:                        InstructionContext v = cfg.contextOf(exc_hds[s]
272:                                .getHandlerStart());
273:                        // TODO: the "oldchain" and "newchain" is used to determine the subroutine
274:                        // we're in (by searching for the last JSR) by the InstructionContext
275:                        // implementation. Therefore, we should not use this chain mechanism
276:                        // when dealing with exception handlers.
277:
278:                        LocalVariables newLocals = u.getOutFrame(oldchain)
279:                                .getLocals();
280:                        OperandStack newStack = new OperandStack(u.getOutFrame(
281:                                oldchain).getStack().maxStack(), (exc_hds[s]
282:                                .getExceptionType() == null ? Type.THROWABLE
283:                                : exc_hds[s].getExceptionType()));
284:                        Frame newFrame = new Frame(newLocals, newStack);
285:
286:                        if (v.execute(newFrame, new ArrayList(), icv, ev)) {
287:                            ics.add(v);
288:                            ecs.add(new ArrayList());
289:                        }
290:                    }
291:                }
292:            }
293:
294:            private void rewrite(MethodGen method, ControlFlowGraph cfg)
295:                    throws ClassNotFoundException {
296:                InstructionFactory insFactory = new InstructionFactory(method
297:                        .getConstantPool());
298:                Vector invokeIns = new Vector();
299:                int count = 0;
300:                InstructionList insList = method.getInstructionList();
301:                InstructionHandle ins = insList.getStart();
302:                InstructionList restorer = new InstructionList();
303:                while (ins != null) {
304:                    InstructionHandle next = ins.getNext();
305:
306:                    // if not traversed by the analyser, then don't rewrite
307:                    InstructionContext context = null;
308:                    Frame frame = null;
309:                    try {
310:                        context = cfg.contextOf(ins);
311:                        frame = context.getOutFrame(new ArrayList());
312:                    } catch (AssertionViolatedException ave) {
313:                        // empty
314:                    }
315:                    if (frame != null) {
316:                        if (rewriteable(method, ins)) {
317:                            // Add frame saver and restorer for the current breakpoint
318:
319:                            // determine type of object for the method invocation
320:                            InvokeInstruction invoke = (InvokeInstruction) ins
321:                                    .getInstruction();
322:                            Type[] arguments = invoke.getArgumentTypes(method
323:                                    .getConstantPool());
324:                            ObjectType objecttype = null;
325:                            if (!(invoke instanceof  INVOKESTATIC)) {
326:                                objecttype = (ObjectType) context.getInFrame()
327:                                        .getStack().peek(arguments.length);
328:                            }
329:                            InstructionList rList = restoreFrame(method, ins,
330:                                    insFactory, frame, objecttype);
331:                            insList.append(ins, saveFrame(method, ins, count++,
332:                                    insFactory, frame));
333:                            invokeIns.addElement(rList.getStart());
334:                            restorer.append(rList);
335:                        }
336:                        // remove all new's                
337:                        if (ins.getInstruction().getOpcode() == Constants.NEW) {
338:                            try {
339:                                // remove additional dup's
340:                                while (next != null
341:                                        && next.getInstruction().getOpcode() == Constants.DUP) {
342:                                    context = cfg.contextOf(next);
343:                                    frame = context
344:                                            .getOutFrame(new ArrayList());
345:                                    InstructionHandle newnext = next.getNext();
346:                                    insList.delete(next);
347:                                    next = newnext;
348:                                }
349:                                InstructionTargeter[] targeter = ins
350:                                        .getTargeters();
351:                                if (targeter != null) {
352:                                    InstructionHandle newnext = ins.getNext();
353:                                    for (int i = 0; i < targeter.length; i++) {
354:                                        targeter[i].updateTarget(ins, newnext);
355:                                    }
356:                                }
357:                                insList.delete(ins);
358:                            } catch (TargetLostException tle) {
359:                                throw new ClassNotFoundException(tle
360:                                        .getMessage(), tle);
361:                            }
362:                        } else if (ins.getInstruction().getOpcode() == Constants.INVOKESPECIAL) {
363:                            // duplicate stack before invokespecial to insert uninitialized object
364:                            frame = context.getInFrame();
365:                            InvokeInstruction invoke = (InvokeInstruction) ins
366:                                    .getInstruction();
367:                            Type[] arguments = invoke.getArgumentTypes(method
368:                                    .getConstantPool());
369:
370:                            OperandStack os = frame.getStack();
371:                            Type type = os.peek(arguments.length);
372:                            if (type instanceof  UninitializedObjectType) {
373:                                ObjectType objecttype = ((UninitializedObjectType) type)
374:                                        .getInitialized();
375:                                InstructionList duplicator = duplicateStack(
376:                                        method, invoke, objecttype);
377:                                InstructionTargeter[] targeter = ins
378:                                        .getTargeters();
379:
380:                                if (targeter != null) {
381:                                    InstructionHandle newnext = duplicator
382:                                            .getStart();
383:                                    for (int i = 0; i < targeter.length; i++) {
384:                                        targeter[i].updateTarget(ins, newnext);
385:                                    }
386:                                }
387:                                insList.insert(ins, duplicator);
388:                            }
389:                        }
390:                    }
391:                    ins = next;
392:                }
393:                InstructionHandle firstIns = insList.getStart();
394:                if (count > 0) {
395:                    InstructionHandle[] tableTargets = new InstructionHandle[count];
396:                    int[] match = new int[count];
397:                    for (int i = 0; i < count; i++) {
398:                        match[i] = i;
399:                    }
400:                    invokeIns.copyInto(tableTargets);
401:                    insList.insert(restorer);
402:
403:                    // select frame restorer
404:                    insList.insert(new TABLESWITCH(match, tableTargets,
405:                            firstIns));
406:                    insList.insert(insFactory.createInvoke(STACK_CLASS,
407:                            getPopMethod(Type.INT), Type.INT, Type.NO_ARGS,
408:                            Constants.INVOKEVIRTUAL));
409:                    insList.insert(InstructionFactory.createLoad(STACK_TYPE,
410:                            method.getMaxLocals() + 1));
411:
412:                    // test if the continuation should be restored
413:                    insList.insert(new IFEQ(firstIns));
414:                    insList.insert(insFactory.createInvoke(CONTINUATION_CLASS,
415:                            RESTORING_METHOD, Type.BOOLEAN, Type.NO_ARGS,
416:                            Constants.INVOKEVIRTUAL));
417:                    insList.insert(InstructionFactory.createLoad(
418:                            CONTINUATION_TYPE, method.getMaxLocals()));
419:                }
420:
421:                // get stack from current continuation and store in the last local variable
422:                insList.insert(InstructionFactory.createStore(STACK_TYPE,
423:                        method.getMaxLocals() + 1));
424:                insList.insert(insFactory.createInvoke(CONTINUATION_CLASS,
425:                        STACK_METHOD, STACK_TYPE, Type.NO_ARGS,
426:                        Constants.INVOKEVIRTUAL));
427:                InstructionHandle restore_handle = insList
428:                        .insert(InstructionFactory.createLoad(
429:                                CONTINUATION_TYPE, method.getMaxLocals()));
430:
431:                // if not continuation exists, create empty stack
432:                insList.insert(new GOTO(firstIns));
433:                insList.insert(InstructionFactory.createStore(STACK_TYPE,
434:                        method.getMaxLocals() + 1));
435:                insList.insert(insFactory.createInvoke(STACK_CLASS,
436:                        Constants.CONSTRUCTOR_NAME, Type.VOID, Type.NO_ARGS,
437:                        Constants.INVOKESPECIAL));
438:                insList.insert(InstructionFactory.createDup(STACK_TYPE
439:                        .getSize()));
440:                insList.insert(insFactory.createNew(STACK_TYPE));
441:
442:                // test if no current continuation exists
443:                insList.insert(new IFNONNULL(restore_handle));
444:                insList.insert(InstructionFactory.createLoad(CONTINUATION_TYPE,
445:                        method.getMaxLocals()));
446:
447:                // get current continuation and store in the next to last local variable
448:                insList.insert(InstructionFactory.createStore(
449:                        CONTINUATION_TYPE, method.getMaxLocals()));
450:                insList.insert(insFactory.createInvoke(CONTINUATION_CLASS,
451:                        CONTINUATION_METHOD, CONTINUATION_TYPE, Type.NO_ARGS,
452:                        Constants.INVOKESTATIC));
453:
454:                // make room for additional objects
455:                method.setMaxLocals(method.getMaxLocals() + 2);
456:                method.setMaxStack(method.getMaxStack() + 2);
457:            }
458:
459:            private InstructionList duplicateStack(MethodGen method,
460:                    InvokeInstruction invoke, ObjectType objecttype)
461:                    throws ClassNotFoundException {
462:                // reconstruction of an uninitialed object to call the constructor.
463:                InstructionFactory insFactory = new InstructionFactory(method
464:                        .getConstantPool());
465:                InstructionList insList = new InstructionList();
466:
467:                Type[] arguments = invoke.getArgumentTypes(method
468:                        .getConstantPool());
469:                // pop all arguments for the constructor from the stack
470:                for (int i = arguments.length - 1; i >= 0; i--) {
471:                    Type type = arguments[i];
472:                    insList.append(InstructionFactory.createLoad(STACK_TYPE,
473:                            method.getMaxLocals() + 1));
474:                    insList.append(new SWAP());
475:                    if (type instanceof  BasicType) {
476:                        if (type.getSize() < 2 && !type.equals(Type.FLOAT)) {
477:                            type = Type.INT;
478:                        }
479:                        insList.append(insFactory.createInvoke(STACK_CLASS,
480:                                getPushMethod(type), Type.VOID,
481:                                new Type[] { type }, Constants.INVOKEVIRTUAL));
482:                    } else if (type instanceof  ReferenceType) {
483:                        insList.append(insFactory.createInvoke(STACK_CLASS,
484:                                getPushMethod(Type.OBJECT), Type.VOID,
485:                                new Type[] { Type.OBJECT },
486:                                Constants.INVOKEVIRTUAL));
487:                    }
488:                }
489:                // create uninitialzed object
490:                insList.append(insFactory.createNew(objecttype));
491:                insList.append(InstructionFactory.createDup(objecttype
492:                        .getSize()));
493:                // return the arguments into the stack
494:                for (int i = 0; i < arguments.length; i++) {
495:                    Type type = arguments[i];
496:                    insList.append(InstructionFactory.createLoad(STACK_TYPE,
497:                            method.getMaxLocals() + 1));
498:                    if (type instanceof  BasicType) {
499:                        if (type.getSize() < 2 && !type.equals(Type.FLOAT)) {
500:                            type = Type.INT;
501:                        }
502:                        insList.append(insFactory.createInvoke(STACK_CLASS,
503:                                getPopMethod(type), type, Type.NO_ARGS,
504:                                Constants.INVOKEVIRTUAL));
505:                    } else if (type instanceof  ReferenceType) {
506:                        insList.append(insFactory.createInvoke(STACK_CLASS,
507:                                getPopMethod(Type.OBJECT), Type.OBJECT,
508:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
509:                        if (!type.equals(Type.OBJECT)) {
510:                            insList.append(insFactory.createCast(Type.OBJECT,
511:                                    type));
512:                        }
513:                    }
514:                }
515:                return insList;
516:            }
517:
518:            private boolean rewriteable(MethodGen method,
519:                    InstructionHandle handle) throws ClassNotFoundException {
520:                // check in the invocation can be a breakpoint.
521:                int opcode = handle.getInstruction().getOpcode();
522:                boolean invokeSpecialSuper = false;
523:                if (opcode == Constants.INVOKESPECIAL) {
524:                    InvokeInstruction ivs = (InvokeInstruction) handle
525:                            .getInstruction();
526:                    String mName = ivs.getMethodName(method.getConstantPool());
527:                    invokeSpecialSuper = !mName
528:                            .equals(Constants.CONSTRUCTOR_NAME);
529:                }
530:
531:                if (opcode == Constants.INVOKEVIRTUAL
532:                        || opcode == Constants.INVOKESTATIC
533:                        || opcode == Constants.INVOKEINTERFACE
534:                        || invokeSpecialSuper) {
535:
536:                    int index = ((InvokeInstruction) handle.getInstruction())
537:                            .getIndex();
538:                    String classname = getObjectType(
539:                            method.getConstantPool().getConstantPool(), index)
540:                            .getClassName();
541:
542:                    // rewrite invocation if object is continuable or a continuation object
543:                    return Repository.implementationOf(classname,
544:                            CONTINUABLE_CLASS)
545:                            || Repository.instanceOf(classname,
546:                                    CONTINUATION_CLASS);
547:                }
548:                return false;
549:            }
550:
551:            private InstructionList saveFrame(MethodGen method,
552:                    InstructionHandle handle, int pc,
553:                    InstructionFactory insFactory, Frame frame) {
554:                InstructionList insList = new InstructionList();
555:
556:                // Remove needless return type from stack
557:                InvokeInstruction inv = (InvokeInstruction) handle
558:                        .getInstruction();
559:                Type returnType = getReturnType(method.getConstantPool()
560:                        .getConstantPool(), inv.getIndex());
561:                if (returnType.getSize() > 0) {
562:                    insList.insert(InstructionFactory.createPop(returnType
563:                            .getSize()));
564:                }
565:                boolean skipFirst = returnType.getSize() > 0;
566:
567:                // save stack
568:                OperandStack os = frame.getStack();
569:                for (int i = skipFirst ? 1 : 0; i < os.size(); i++) {
570:                    Type type = os.peek(i);
571:                    if (type instanceof  BasicType) {
572:                        if (type.getSize() < 2 && !type.equals(Type.FLOAT)) {
573:                            type = Type.INT;
574:                        }
575:                        insList.append(InstructionFactory.createLoad(
576:                                STACK_TYPE, method.getMaxLocals() + 1));
577:                        insList.append(new SWAP()); // TODO: check for types with two words on stack
578:                        insList.append(insFactory.createInvoke(STACK_CLASS,
579:                                getPushMethod(type), Type.VOID,
580:                                new Type[] { type }, Constants.INVOKEVIRTUAL));
581:                    } else if (type == null) {
582:                        insList.append(InstructionConstants.POP);
583:                    } else if (type instanceof  UninitializedObjectType) {
584:                        // After the remove of new, there shouldn't be a
585:                        // uninitialized object on the stack
586:                    } else if (type instanceof  ReferenceType) {
587:                        insList.append(InstructionFactory.createLoad(
588:                                STACK_TYPE, method.getMaxLocals() + 1));
589:                        insList.append(new SWAP());
590:                        insList.append(insFactory.createInvoke(STACK_CLASS,
591:                                getPushMethod(Type.OBJECT), Type.VOID,
592:                                new Type[] { Type.OBJECT },
593:                                Constants.INVOKEVIRTUAL));
594:                    }
595:                }
596:                // add isCapturing test
597:                insList.insert(new IFEQ(handle.getNext()));
598:                // test if the continuation should be captured after the invocation
599:                insList.insert(insFactory.createInvoke(CONTINUATION_CLASS,
600:                        CAPURING_METHOD, Type.BOOLEAN, Type.NO_ARGS,
601:                        Constants.INVOKEVIRTUAL));
602:                insList.insert(InstructionFactory.createLoad(CONTINUATION_TYPE,
603:                        method.getMaxLocals()));
604:                // test if continuation exists
605:                insList.insert(new IFNULL(handle.getNext()));
606:                insList.insert(InstructionFactory.createLoad(CONTINUATION_TYPE,
607:                        method.getMaxLocals()));
608:                // save local variables
609:                LocalVariables lvs = frame.getLocals();
610:                for (int i = 0; i < lvs.maxLocals(); i++) {
611:                    Type type = lvs.get(i);
612:                    if (type instanceof  BasicType) {
613:                        insList.append(InstructionFactory.createLoad(
614:                                STACK_TYPE, method.getMaxLocals() + 1));
615:                        insList.append(InstructionFactory.createLoad(type, i));
616:                        if (type.getSize() < 2 && !type.equals(Type.FLOAT))
617:                            type = Type.INT;
618:                        insList.append(insFactory.createInvoke(STACK_CLASS,
619:                                getPushMethod(type), Type.VOID,
620:                                new Type[] { type }, Constants.INVOKEVIRTUAL));
621:                    } else if (type == null) {
622:                        // no need to save null
623:                    } else if (type instanceof  UninitializedObjectType) {
624:                        // no need to save uninitialized objects
625:                    } else if (type instanceof  ReferenceType) {
626:                        if (i == 0 && !currentMethodStatic) {
627:                            // remember current object
628:                            insList.append(InstructionFactory.createLoad(
629:                                    STACK_TYPE, method.getMaxLocals() + 1));
630:                            insList.append(InstructionFactory.createLoad(type,
631:                                    i));
632:                            insList.append(insFactory.createInvoke(STACK_CLASS,
633:                                    PUSH_METHOD + "Reference", Type.VOID,
634:                                    new Type[] { Type.OBJECT },
635:                                    Constants.INVOKEVIRTUAL));
636:                        }
637:                        insList.append(InstructionFactory.createLoad(
638:                                STACK_TYPE, method.getMaxLocals() + 1));
639:                        insList.append(InstructionFactory.createLoad(type, i));
640:                        insList.append(insFactory.createInvoke(STACK_CLASS,
641:                                getPushMethod(Type.OBJECT), Type.VOID,
642:                                new Type[] { Type.OBJECT },
643:                                Constants.INVOKEVIRTUAL));
644:                    }
645:                }
646:                // save programcounter
647:                insList.append(InstructionFactory.createLoad(STACK_TYPE, method
648:                        .getMaxLocals() + 1));
649:                insList.append(new PUSH(method.getConstantPool(), pc));
650:                insList.append(insFactory.createInvoke(STACK_CLASS,
651:                        getPushMethod(Type.INT), Type.VOID,
652:                        new Type[] { Type.INT }, Constants.INVOKEVIRTUAL));
653:                // return NULL result
654:                insList.append(InstructionFactory.createNull(method
655:                        .getReturnType()));
656:                insList.append(InstructionFactory.createReturn(method
657:                        .getReturnType()));
658:                return insList;
659:            }
660:
661:            private InstructionList restoreFrame(MethodGen method,
662:                    InstructionHandle handle, InstructionFactory insFactory,
663:                    Frame frame, ObjectType objecttype) {
664:                InstructionList insList = new InstructionList();
665:                // restore local variables
666:                LocalVariables lvs = frame.getLocals();
667:                for (int i = lvs.maxLocals() - 1; i >= 0; i--) {
668:                    Type type = lvs.get(i);
669:                    if (type instanceof  BasicType) {
670:                        insList.append(InstructionFactory.createLoad(
671:                                STACK_TYPE, method.getMaxLocals() + 1));
672:                        if (type.getSize() < 2 && !type.equals(Type.FLOAT)) {
673:                            type = Type.INT;
674:                        }
675:                        insList.append(insFactory.createInvoke(STACK_CLASS,
676:                                getPopMethod(type), type, Type.NO_ARGS,
677:                                Constants.INVOKEVIRTUAL));
678:                        insList.append(InstructionFactory.createStore(type, i));
679:                    } else if (type == null) {
680:                        insList.append(new ACONST_NULL());
681:                        insList.append(InstructionFactory.createStore(
682:                                new ObjectType("<null object>"), i));
683:                    } else if (type instanceof  UninitializedObjectType) {
684:                        // No uninitilaized objects should be found
685:                        // in the local variables.
686:                    } else if (type instanceof  ReferenceType) {
687:                        insList.append(InstructionFactory.createLoad(
688:                                STACK_TYPE, method.getMaxLocals() + 1));
689:                        insList.append(insFactory.createInvoke(STACK_CLASS,
690:                                getPopMethod(Type.OBJECT), Type.OBJECT,
691:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
692:                        if (!type.equals(Type.OBJECT)
693:                                && (!type.equals(Type.NULL))) {
694:                            insList.append(insFactory.createCast(Type.OBJECT,
695:                                    type));
696:                        }
697:                        insList.append(InstructionFactory.createStore(type, i));
698:                    }
699:                }
700:
701:                InvokeInstruction inv = (InvokeInstruction) handle
702:                        .getInstruction();
703:                Type returnType = getReturnType(method.getConstantPool()
704:                        .getConstantPool(), inv.getIndex());
705:                boolean skipFirst = returnType.getSize() > 0;
706:
707:                // restore stack
708:                OperandStack os = frame.getStack();
709:                for (int i = os.size() - 1; i >= (skipFirst ? 1 : 0); i--) {
710:                    Type type = os.peek(i);
711:                    if (type instanceof  BasicType) {
712:                        if (type.getSize() < 2 && !type.equals(Type.FLOAT)) {
713:                            type = Type.INT;
714:                        }
715:                        insList.append(InstructionFactory.createLoad(
716:                                STACK_TYPE, method.getMaxLocals() + 1));
717:                        insList.append(insFactory.createInvoke(STACK_CLASS,
718:                                getPopMethod(type), type, Type.NO_ARGS,
719:                                Constants.INVOKEVIRTUAL));
720:                    } else if (type == null) {
721:                        insList.append(new ACONST_NULL());
722:                    } else if (type instanceof  UninitializedObjectType) {
723:                        // After the remove of new, there shouldn't be a
724:                        // uninitialized object on the stack
725:                    } else if (type instanceof  ReferenceType) {
726:                        insList.append(InstructionFactory.createLoad(
727:                                STACK_TYPE, method.getMaxLocals() + 1));
728:                        insList.append(insFactory.createInvoke(STACK_CLASS,
729:                                getPopMethod(Type.OBJECT), Type.OBJECT,
730:                                Type.NO_ARGS, Constants.INVOKEVIRTUAL));
731:                        if (!type.equals(Type.OBJECT))
732:                            insList.append(insFactory.createCast(Type.OBJECT,
733:                                    type));
734:                    }
735:                }
736:                // retrieve current object
737:                if (!(inv instanceof  INVOKESTATIC)) {
738:                    insList.append(InstructionFactory.createLoad(STACK_TYPE,
739:                            method.getMaxLocals() + 1));
740:                    insList.append(insFactory.createInvoke(STACK_CLASS,
741:                            POP_METHOD + "Reference", Type.OBJECT,
742:                            Type.NO_ARGS, Constants.INVOKEVIRTUAL));
743:                    insList.append(insFactory.createCast(Type.OBJECT,
744:                            objecttype));
745:                }
746:                // Create null types for the parameters of the method invocation
747:                Type[] paramTypes = getParamTypes(method.getConstantPool()
748:                        .getConstantPool(), inv.getIndex());
749:                for (int j = 0; j < paramTypes.length; j++) {
750:                    insList
751:                            .append(InstructionFactory
752:                                    .createNull(paramTypes[j]));
753:                }
754:                // go to last invocation
755:                insList.append(new GOTO(handle));
756:                return insList;
757:            }
758:
759:            private ObjectType getObjectType(ConstantPool cp, int index) {
760:                ConstantCP cmr = (ConstantCP) cp.getConstant(index);
761:                String sig = cp.getConstantString(cmr.getClassIndex(),
762:                        Constants.CONSTANT_Class);
763:                return new ObjectType(sig.replace('/', '.'));
764:            }
765:
766:            private Type[] getParamTypes(ConstantPool cp, int index) {
767:                ConstantCP cmr = (ConstantCP) cp.getConstant(index);
768:                ConstantNameAndType cnat = (ConstantNameAndType) cp
769:                        .getConstant(cmr.getNameAndTypeIndex());
770:                String sig = ((ConstantUtf8) cp.getConstant(cnat
771:                        .getSignatureIndex())).getBytes();
772:                return Type.getArgumentTypes(sig);
773:            }
774:
775:            private Type getReturnType(ConstantPool cp, int index) {
776:                ConstantCP cmr = (ConstantCP) cp.getConstant(index);
777:                ConstantNameAndType cnat = (ConstantNameAndType) cp
778:                        .getConstant(cmr.getNameAndTypeIndex());
779:                String sig = ((ConstantUtf8) cp.getConstant(cnat
780:                        .getSignatureIndex())).getBytes();
781:                return Type.getReturnType(sig);
782:            }
783:
784:            private String getPopMethod(Type type) {
785:                return POP_METHOD + getTypeSuffix(type);
786:            }
787:
788:            private String getPushMethod(Type type) {
789:                return PUSH_METHOD + getTypeSuffix(type);
790:            }
791:
792:            private String getTypeSuffix(Type type) {
793:                if (type.equals(Type.BOOLEAN))
794:                    return "Int";
795:                else if (type.equals(Type.CHAR))
796:                    return "Int";
797:                else if (type.equals(Type.FLOAT))
798:                    return "Float";
799:                else if (type.equals(Type.DOUBLE))
800:                    return "Double";
801:                else if (type.equals(Type.BYTE))
802:                    return "Int";
803:                else if (type.equals(Type.SHORT))
804:                    return "Int";
805:                else if (type.equals(Type.INT))
806:                    return "Int";
807:                else if (type.equals(Type.LONG))
808:                    return "Long";
809:                // VOID and OBJECT are "Object"
810:                return "Object";
811:            }
812:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.