Source Code Cross Referenced for CompileStack.java in  » Scripting » groovy-1.0 » org » codehaus » groovy » classgen » 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 » Scripting » groovy 1.0 » org.codehaus.groovy.classgen 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         $Id: CompileStack.java 4352 2006-12-13 15:58:48Z blackdrag $
003:
004:         Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005:
006:         Redistribution and use of this software and associated documentation
007:         ("Software"), with or without modification, are permitted provided
008:         that the following conditions are met:
009:
010:         1. Redistributions of source code must retain copyright
011:            statements and notices.  Redistributions must also contain a
012:            copy of this document.
013:
014:         2. Redistributions in binary form must reproduce the
015:            above copyright notice, this list of conditions and the
016:            following disclaimer in the documentation and/or other
017:            materials provided with the distribution.
018:
019:         3. The name "groovy" must not be used to endorse or promote
020:            products derived from this Software without prior written
021:            permission of The Codehaus.  For written permission,
022:            please contact info@codehaus.org.
023:
024:         4. Products derived from this Software may not be called "groovy"
025:            nor may "groovy" appear in their names without prior written
026:            permission of The Codehaus. "groovy" is a registered
027:            trademark of The Codehaus.
028:
029:         5. Due credit should be given to The Codehaus -
030:            http://groovy.codehaus.org/
031:
032:         THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033:         ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034:         NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035:         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
036:         THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037:         INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038:         (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039:         SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040:         HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041:         STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042:         ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043:         OF THE POSSIBILITY OF SUCH DAMAGE.
044:
045:         */
046:
047:        package org.codehaus.groovy.classgen;
048:
049:        import java.util.ArrayList;
050:        import java.util.Collections;
051:        import java.util.HashMap;
052:        import java.util.Iterator;
053:        import java.util.LinkedList;
054:        import java.util.List;
055:        import java.util.ListIterator;
056:
057:        import org.codehaus.groovy.GroovyBugError;
058:        import org.codehaus.groovy.ast.ClassHelper;
059:        import org.codehaus.groovy.ast.ClassNode;
060:        import org.codehaus.groovy.ast.Parameter;
061:        import org.codehaus.groovy.ast.VariableScope;
062:        import org.objectweb.asm.Label;
063:        import org.objectweb.asm.MethodVisitor;
064:        import org.objectweb.asm.Opcodes;
065:
066:        /**
067:         * This class is a helper for AsmClassGenerator. It manages
068:         * different aspects of the code of a code block like 
069:         * handling labels, defining variables, and scopes. 
070:         * After a MethodNode is visited clear should be called, for 
071:         * initialization the method init should be used.
072:         * <p> 
073:         * Some Notes:
074:         * <ul>
075:         * <li> every push method will require a later pop call
076:         * <li> method parameters may define a category 2 variable, so
077:         *      don't ignore the type stored in the variable object
078:         * <li> the index of the variable may not be as assumed when
079:         *      the variable is a parameter of a method because the 
080:         *      parameter may be used in a closure, so don't ignore
081:         *      the stored variable index
082:         * <li> the names of temporary variables can be ignored. The names
083:         *      are only used for debugging and do not conflict with each 
084:         *      other or normal variables. For accessing the index of the
085:         *      variable must be used.
086:         * </ul>
087:         * 
088:         * 
089:         * @see org.codehaus.groovy.classgen.AsmClassGenerator
090:         * @author Jochen Theodorou
091:         */
092:        public class CompileStack implements  Opcodes {
093:            /**
094:             * @TODO remove optimization of this.foo -> this.@foo
095:             * 
096:             */
097:
098:            // state flag
099:            private boolean clear = true;
100:            // current scope
101:            private VariableScope scope;
102:            // current label for continue
103:            private Label continueLabel;
104:            // current label for break
105:            private Label breakLabel;
106:            // available variables on stack
107:            private HashMap stackVariables = new HashMap();
108:            // index of the last variable on stack
109:            private int currentVariableIndex = 1;
110:            // index for the next variable on stack
111:            private int nextVariableIndex = 1;
112:            // currently temporary variables in use
113:            private LinkedList temporaryVariables = new LinkedList();
114:            // overall used variables for a method/constructor
115:            private LinkedList usedVariables = new LinkedList();
116:            // map containing named labels of parenting blocks
117:            private HashMap super BlockNamedLabels = new HashMap();
118:            // map containing named labels of current block
119:            private HashMap currentBlockNamedLabels = new HashMap();
120:            // list containing runnables representing a finally block
121:            // such a block is created by synchronized or finally and
122:            // must be called for break/continue/return
123:            private LinkedList finallyBlocks = new LinkedList();
124:            // a list of blocks already visiting. 
125:            private List visitedBlocks = new LinkedList();
126:
127:            private Label this StartLabel, this EndLabel;
128:
129:            // current class index
130:            private int currentClassIndex, currentMetaClassIndex;
131:
132:            private MethodVisitor mv;
133:            private BytecodeHelper helper;
134:
135:            // helper to handle different stack based variables    
136:            private LinkedList stateStack = new LinkedList();
137:
138:            // defines the first variable index useable after
139:            // all parameters of a method 
140:            private int localVariableOffset;
141:            // this is used to store the goals for a "break foo" call
142:            // in a loop where foo is a label.
143:            private HashMap namedLoopBreakLabel = new HashMap();
144:            //this is used to store the goals for a "continue foo" call
145:            // in a loop where foo is a label.
146:            private HashMap namedLoopContinueLabel = new HashMap();
147:            private String className;
148:
149:            private class StateStackElement {
150:                VariableScope _scope;
151:                Label _continueLabel;
152:                Label _breakLabel;
153:                Label _finallyLabel;
154:                int _lastVariableIndex;
155:                int _nextVariableIndex;
156:                HashMap _stackVariables;
157:                LinkedList _temporaryVariables = new LinkedList();
158:                LinkedList _usedVariables = new LinkedList();
159:                HashMap _super BlockNamedLabels;
160:                HashMap _currentBlockNamedLabels;
161:                LinkedList _finallyBlocks;
162:
163:                StateStackElement() {
164:                    _scope = CompileStack.this .scope;
165:                    _continueLabel = CompileStack.this .continueLabel;
166:                    _breakLabel = CompileStack.this .breakLabel;
167:                    _lastVariableIndex = CompileStack.this .currentVariableIndex;
168:                    _stackVariables = CompileStack.this .stackVariables;
169:                    _temporaryVariables = CompileStack.this .temporaryVariables;
170:                    _nextVariableIndex = nextVariableIndex;
171:                    _super BlockNamedLabels = super BlockNamedLabels;
172:                    _currentBlockNamedLabels = currentBlockNamedLabels;
173:                    _finallyBlocks = finallyBlocks;
174:                }
175:            }
176:
177:            private void pushState() {
178:                stateStack.add(new StateStackElement());
179:                stackVariables = new HashMap(stackVariables);
180:                finallyBlocks = new LinkedList(finallyBlocks);
181:            }
182:
183:            private void popState() {
184:                if (stateStack.size() == 0) {
185:                    throw new GroovyBugError(
186:                            "Tried to do a pop on the compile stack without push.");
187:                }
188:                StateStackElement element = (StateStackElement) stateStack
189:                        .removeLast();
190:                scope = element._scope;
191:                continueLabel = element._continueLabel;
192:                breakLabel = element._breakLabel;
193:                currentVariableIndex = element._lastVariableIndex;
194:                stackVariables = element._stackVariables;
195:                nextVariableIndex = element._nextVariableIndex;
196:                finallyBlocks = element._finallyBlocks;
197:            }
198:
199:            public Label getContinueLabel() {
200:                return continueLabel;
201:            }
202:
203:            public Label getBreakLabel() {
204:                return breakLabel;
205:            }
206:
207:            public void removeVar(int tempIndex) {
208:                for (Iterator iter = temporaryVariables.iterator(); iter
209:                        .hasNext();) {
210:                    Variable element = (Variable) iter.next();
211:                    if (element.getIndex() == tempIndex) {
212:                        iter.remove();
213:                        return;
214:                    }
215:                }
216:                throw new GroovyBugError(
217:                        "CompileStack#removeVar: tried to remove a temporary variable with a non existent index");
218:            }
219:
220:            private void setEndLabels() {
221:                Label endLabel = new Label();
222:                mv.visitLabel(endLabel);
223:                for (Iterator iter = stackVariables.values().iterator(); iter
224:                        .hasNext();) {
225:                    Variable var = (Variable) iter.next();
226:                    var.setEndLabel(endLabel);
227:                }
228:                this EndLabel = endLabel;
229:            }
230:
231:            public void pop() {
232:                setEndLabels();
233:                popState();
234:            }
235:
236:            public VariableScope getScope() {
237:                return scope;
238:            }
239:
240:            /**
241:             * creates a temporary variable. 
242:             * 
243:             * @param var defines type and name
244:             * @param store defines if the toplevel argument of the stack should be stored
245:             * @return the index used for this temporary variable
246:             */
247:            public int defineTemporaryVariable(
248:                    org.codehaus.groovy.ast.Variable var, boolean store) {
249:                return defineTemporaryVariable(var.getName(), var.getType(),
250:                        store);
251:            }
252:
253:            public Variable getVariable(String variableName) {
254:                return getVariable(variableName, true);
255:            }
256:
257:            public Variable getVariable(String variableName, boolean mustExist) {
258:                if (variableName.equals("this"))
259:                    return Variable.THIS_VARIABLE;
260:                if (variableName.equals("super"))
261:                    return Variable.SUPER_VARIABLE;
262:                Variable v = (Variable) stackVariables.get(variableName);
263:                if (v == null && mustExist)
264:                    throw new GroovyBugError(
265:                            "tried to get a variable with the name "
266:                                    + variableName
267:                                    + " as stack variable, but a variable with this name was not created");
268:                return v;
269:            }
270:
271:            /**
272:             * creates a temporary variable. 
273:             * 
274:             * @param name defines type and name
275:             * @param store defines if the toplevel argument of the stack should be stored
276:             * @return the index used for this temporary variable
277:             */
278:            public int defineTemporaryVariable(String name, boolean store) {
279:                return defineTemporaryVariable(name, ClassHelper.DYNAMIC_TYPE,
280:                        store);
281:            }
282:
283:            /**
284:             * creates a temporary variable. 
285:             * 
286:             * @param name defines the name
287:             * @param node defines the node
288:             * @param store defines if the toplevel argument of the stack should be stored 
289:             * @return the index used for this temporary variable
290:             */
291:            public int defineTemporaryVariable(String name, ClassNode node,
292:                    boolean store) {
293:                Variable answer = defineVar(name, node, false);
294:                temporaryVariables.add(answer);
295:                usedVariables.removeLast();
296:
297:                if (store)
298:                    mv.visitVarInsn(ASTORE, currentVariableIndex);
299:
300:                return answer.getIndex();
301:            }
302:
303:            private void resetVariableIndex(boolean isStatic) {
304:                if (!isStatic) {
305:                    currentVariableIndex = 1;
306:                    nextVariableIndex = 1;
307:                } else {
308:                    currentVariableIndex = 0;
309:                    nextVariableIndex = 0;
310:                }
311:            }
312:
313:            /**
314:             * Clears the state of the class. This method should be called 
315:             * after a MethodNode is visited. Note that a call to init will
316:             * fail if clear is not called before
317:             */
318:            public void clear() {
319:                if (stateStack.size() > 1) {
320:                    int size = stateStack.size() - 1;
321:                    throw new GroovyBugError("the compile stack contains "
322:                            + size + " more push instruction"
323:                            + (size == 1 ? "" : "s") + " than pops.");
324:                }
325:                clear = true;
326:                // br experiment with local var table so debuggers can retrieve variable names
327:                if (true) {//AsmClassGenerator.CREATE_DEBUG_INFO) {
328:                    if (this EndLabel == null)
329:                        setEndLabels();
330:
331:                    if (!scope.isInStaticContext()) {
332:                        // write "this"
333:                        mv.visitLocalVariable("this", className, null,
334:                                this StartLabel, this EndLabel, 0);
335:                    }
336:
337:                    for (Iterator iterator = usedVariables.iterator(); iterator
338:                            .hasNext();) {
339:                        Variable v = (Variable) iterator.next();
340:                        String type = BytecodeHelper.getTypeDescription(v
341:                                .getType());
342:                        Label start = v.getStartLabel();
343:                        Label end = v.getEndLabel();
344:                        mv.visitLocalVariable(v.getName(), type, null, start,
345:                                end, v.getIndex());
346:                    }
347:                }
348:                pop();
349:                stackVariables.clear();
350:                usedVariables.clear();
351:                scope = null;
352:                mv = null;
353:                resetVariableIndex(false);
354:                super BlockNamedLabels.clear();
355:                currentBlockNamedLabels.clear();
356:                namedLoopBreakLabel.clear();
357:                namedLoopContinueLabel.clear();
358:                continueLabel = null;
359:                breakLabel = null;
360:                helper = null;
361:                this StartLabel = null;
362:                this EndLabel = null;
363:            }
364:
365:            /**
366:             * initializes this class for a MethodNode. This method will
367:             * automatically define varibales for the method parameters
368:             * and will create references if needed. the created variables
369:             * can be get by getVariable
370:             * 
371:             */
372:            protected void init(VariableScope el, Parameter[] parameters,
373:                    MethodVisitor mv, ClassNode cn) {
374:                if (!clear)
375:                    throw new GroovyBugError(
376:                            "CompileStack#init called without calling clear before");
377:                clear = false;
378:                pushVariableScope(el);
379:                this .mv = mv;
380:                this .helper = new BytecodeHelper(mv);
381:                defineMethodVariables(parameters, el.isInStaticContext());
382:                this .className = BytecodeHelper.getTypeDescription(cn);
383:                currentClassIndex = -1;
384:                currentMetaClassIndex = -1;
385:            }
386:
387:            /**
388:             * Causes the statestack to add an element and sets
389:             * the given scope as new current variable scope. Creates 
390:             * a element for the state stack so pop has to be called later
391:             */
392:            protected void pushVariableScope(VariableScope el) {
393:                pushState();
394:                scope = el;
395:                super BlockNamedLabels = new HashMap(super BlockNamedLabels);
396:                super BlockNamedLabels.putAll(currentBlockNamedLabels);
397:                currentBlockNamedLabels = new HashMap();
398:            }
399:
400:            /**
401:             * Should be called when decending into a loop that defines
402:             * also a scope. Calls pushVariableScope and prepares labels 
403:             * for a loop structure. Creates a element for the state stack
404:             * so pop has to be called later 
405:             */
406:            protected void pushLoop(VariableScope el, String labelName) {
407:                pushVariableScope(el);
408:                initLoopLabels(labelName);
409:            }
410:
411:            private void initLoopLabels(String labelName) {
412:                continueLabel = new Label();
413:                breakLabel = new Label();
414:                if (labelName != null) {
415:                    namedLoopBreakLabel.put(labelName, breakLabel);
416:                    namedLoopContinueLabel.put(labelName, continueLabel);
417:                }
418:            }
419:
420:            /**
421:             * Should be called when decending into a loop that does 
422:             * not define a scope. Creates a element for the state stack
423:             * so pop has to be called later
424:             */
425:            protected void pushLoop(String labelName) {
426:                pushState();
427:                initLoopLabels(labelName);
428:            }
429:
430:            /**
431:             * Used for <code>break foo</code> inside a loop to end the
432:             * execution of the marked loop. This method will return the
433:             * break label of the loop if there is one found for the name.
434:             * If not, the current break label is returned.
435:             */
436:            protected Label getNamedBreakLabel(String name) {
437:                Label label = getBreakLabel();
438:                Label endLabel = null;
439:                if (name != null)
440:                    endLabel = (Label) namedLoopBreakLabel.get(name);
441:                if (endLabel != null)
442:                    label = endLabel;
443:                return label;
444:            }
445:
446:            /**
447:             * Used for <code>continue foo</code> inside a loop to continue
448:             * the execution of the marked loop. This method will return 
449:             * the break label of the loop if there is one found for the 
450:             * name. If not, getLabel is used.
451:             */
452:            protected Label getNamedContinueLabel(String name) {
453:                Label label = getLabel(name);
454:                Label endLabel = null;
455:                if (name != null)
456:                    endLabel = (Label) namedLoopContinueLabel.get(name);
457:                if (endLabel != null)
458:                    label = endLabel;
459:                return label;
460:            }
461:
462:            /**
463:             * Creates a new break label and a element for the state stack
464:             * so pop has to be called later
465:             */
466:            protected Label pushSwitch() {
467:                pushState();
468:                breakLabel = new Label();
469:                return breakLabel;
470:            }
471:
472:            /**
473:             * because a boolean Expression may not be evaluated completly
474:             * it is important to keep the registers clean
475:             */
476:            protected void pushBooleanExpression() {
477:                pushState();
478:            }
479:
480:            private Variable defineVar(String name, ClassNode type,
481:                    boolean methodParameterUsedInClosure) {
482:                makeNextVariableID(type);
483:                int index = currentVariableIndex;
484:                if (methodParameterUsedInClosure) {
485:                    index = localVariableOffset++;
486:                }
487:                Variable answer = new Variable(index, type, name);
488:                usedVariables.add(answer);
489:                answer.setHolder(methodParameterUsedInClosure);
490:                return answer;
491:            }
492:
493:            private void makeLocalVariablesOffset(Parameter[] paras,
494:                    boolean isInStaticContext) {
495:                resetVariableIndex(isInStaticContext);
496:
497:                for (int i = 0; i < paras.length; i++) {
498:                    makeNextVariableID(paras[i].getType());
499:                }
500:                localVariableOffset = nextVariableIndex;
501:
502:                resetVariableIndex(isInStaticContext);
503:            }
504:
505:            private void defineMethodVariables(Parameter[] paras,
506:                    boolean isInStaticContext) {
507:                Label startLabel = new Label();
508:                this StartLabel = startLabel;
509:                mv.visitLabel(startLabel);
510:
511:                makeLocalVariablesOffset(paras, isInStaticContext);
512:
513:                boolean hasHolder = false;
514:                for (int i = 0; i < paras.length; i++) {
515:                    String name = paras[i].getName();
516:                    Variable answer;
517:                    if (paras[i].isClosureSharedVariable()) {
518:                        answer = defineVar(name, ClassHelper
519:                                .getWrapper(paras[i].getType()), true);
520:                        ClassNode type = paras[i].getType();
521:                        helper.load(type, currentVariableIndex);
522:                        helper.box(type);
523:                        createReference(answer);
524:                        hasHolder = true;
525:                    } else {
526:                        answer = defineVar(name, paras[i].getType(), false);
527:                    }
528:                    answer.setStartLabel(startLabel);
529:                    stackVariables.put(name, answer);
530:                }
531:
532:                if (hasHolder) {
533:                    nextVariableIndex = localVariableOffset;
534:                }
535:            }
536:
537:            private void createReference(Variable reference) {
538:                mv.visitTypeInsn(NEW, "groovy/lang/Reference");
539:                mv.visitInsn(DUP_X1);
540:                mv.visitInsn(SWAP);
541:                mv.visitMethodInsn(INVOKESPECIAL, "groovy/lang/Reference",
542:                        "<init>", "(Ljava/lang/Object;)V");
543:                mv.visitVarInsn(ASTORE, reference.getIndex());
544:            }
545:
546:            /**
547:             * Defines a new Variable using an AST variable.
548:             * @param initFromStack if true the last element of the 
549:             *                      stack will be used to initilize
550:             *                      the new variable. If false null
551:             *                      will be used.
552:             */
553:            public Variable defineVariable(org.codehaus.groovy.ast.Variable v,
554:                    boolean initFromStack) {
555:                String name = v.getName();
556:                Variable answer = defineVar(name, v.getType(), false);
557:                if (v.isClosureSharedVariable())
558:                    answer.setHolder(true);
559:                stackVariables.put(name, answer);
560:
561:                Label startLabel = new Label();
562:                answer.setStartLabel(startLabel);
563:                if (answer.isHolder()) {
564:                    if (!initFromStack)
565:                        mv.visitInsn(ACONST_NULL);
566:                    createReference(answer);
567:                } else {
568:                    if (!initFromStack)
569:                        mv.visitInsn(ACONST_NULL);
570:                    mv.visitVarInsn(ASTORE, currentVariableIndex);
571:                }
572:                mv.visitLabel(startLabel);
573:                return answer;
574:            }
575:
576:            /**
577:             * Returns true if a varibale is already defined
578:             */
579:            public boolean containsVariable(String name) {
580:                return stackVariables.containsKey(name);
581:            }
582:
583:            /**
584:             * Calculates the index of the next free register stores ir
585:             * and sets the current variable index to the old value
586:             */
587:            private void makeNextVariableID(ClassNode type) {
588:                currentVariableIndex = nextVariableIndex;
589:                if (type == ClassHelper.long_TYPE
590:                        || type == ClassHelper.double_TYPE) {
591:                    nextVariableIndex++;
592:                }
593:                nextVariableIndex++;
594:            }
595:
596:            /**
597:             * Returns the label for the given name 
598:             */
599:            public Label getLabel(String name) {
600:                if (name == null)
601:                    return null;
602:                Label l = (Label) super BlockNamedLabels.get(name);
603:                if (l == null)
604:                    l = createLocalLabel(name);
605:                return l;
606:            }
607:
608:            /**
609:             * creates a new named label
610:             */
611:            public Label createLocalLabel(String name) {
612:                Label l = (Label) currentBlockNamedLabels.get(name);
613:                if (l == null) {
614:                    l = new Label();
615:                    currentBlockNamedLabels.put(name, l);
616:                }
617:                return l;
618:            }
619:
620:            public int getCurrentClassIndex() {
621:                return currentClassIndex;
622:            }
623:
624:            public void setCurrentClassIndex(int index) {
625:                currentClassIndex = index;
626:            }
627:
628:            public int getCurrentMetaClassIndex() {
629:                return currentMetaClassIndex;
630:            }
631:
632:            public void setCurrentMetaClassIndex(int index) {
633:                currentMetaClassIndex = index;
634:            }
635:
636:            public void applyFinallyBlocks(Label label, boolean isBreakLabel) {
637:                // first find the state defining the label. That is the state
638:                // directly after the state not knowing this label. If no state
639:                // in the list knows that label, then the defining state is the
640:                // current state.
641:                StateStackElement result = null;
642:                for (ListIterator iter = stateStack.listIterator(stateStack
643:                        .size()); iter.hasPrevious();) {
644:                    StateStackElement element = (StateStackElement) iter
645:                            .previous();
646:                    if (!element._currentBlockNamedLabels.values().contains(
647:                            label)) {
648:                        if (isBreakLabel && element._breakLabel != label) {
649:                            result = element;
650:                            break;
651:                        }
652:                        if (!isBreakLabel && element._continueLabel != label) {
653:                            result = element;
654:                            break;
655:                        }
656:                    }
657:                }
658:
659:                List blocksToRemove;
660:                if (result == null) {
661:                    // all Blocks do know the label, so use all finally blocks
662:                    blocksToRemove = Collections.EMPTY_LIST;
663:                } else {
664:                    blocksToRemove = result._finallyBlocks;
665:                }
666:
667:                ArrayList blocks = new ArrayList(finallyBlocks);
668:                blocks.removeAll(blocksToRemove);
669:                applyFinallyBlocks(blocks);
670:            }
671:
672:            private void applyFinallyBlocks(List blocks) {
673:                for (Iterator iter = blocks.iterator(); iter.hasNext();) {
674:                    Runnable block = (Runnable) iter.next();
675:                    if (visitedBlocks.contains(block))
676:                        continue;
677:                    visitedBlocks.add(block);
678:                    block.run();
679:                }
680:            }
681:
682:            public void applyFinallyBlocks() {
683:                applyFinallyBlocks(finallyBlocks);
684:            }
685:
686:            public boolean hasFinallyBlocks() {
687:                return !finallyBlocks.isEmpty();
688:            }
689:
690:            public void pushFinallyBlock(Runnable block) {
691:                finallyBlocks.addFirst(block);
692:                pushState();
693:            }
694:
695:            public void popFinallyBlock() {
696:                popState();
697:                finallyBlocks.removeFirst();
698:            }
699:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.