KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > impl > MethodAnnotater


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24
25 package com.sun.jdo.api.persistence.enhancer.impl;
26
27 import java.util.Map JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Vector JavaDoc;
30 import java.util.Stack JavaDoc;
31 import java.util.Enumeration JavaDoc;
32
33 import com.sun.jdo.api.persistence.enhancer.classfile.*;
34
35 import com.sun.jdo.api.persistence.enhancer.util.Support;
36 import com.sun.jdo.api.persistence.enhancer.util.InternalError;
37 import com.sun.jdo.api.persistence.enhancer.util.ClassFileSource;
38
39 //@olsen: added import
40
import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaData;
41
42
43 //@olsen: cosmetics
44
//@olsen: moved: this class -> package impl
45
//@olsen: subst: (object)state -> flags
46
//@olsen: subst: JDOFlags -> jdoFlags
47
//@olsen: subst: JDO[gs]etFlags -> jdo[GS]etFlags
48
//@olsen: subst: (object)reference -> stateManager
49
//@olsen: subst: [Nn]eedsJDORefMethods -> [Nn]eedsJDOStateManagerMethods
50
//@olsen: subst: JDORef -> jdoStateManager
51
//@olsen: subst: JDO[gs]etRef -> jdo[GS]etStateManager
52
//@olsen: subst: [iI]Persistent -> [pP]ersistenceCapable
53
//@olsen: subst: PersistentAux -> StateManager
54
//@olsen: subst: jdo/ -> com/sun/forte4j/persistence/internal/
55
//@olsen: subst: /* ... */ -> // ...
56
//@olsen: subst: FilterEnv -> Environment
57
//@olsen: dropped parameter 'Environment env', use association instead
58
//@olsen: subst: Hashtable -> Map, HashMap
59
//@olsen: subst: absolut jdo types and names -> constants from JDOMetaData
60
//@olsen: subst: .classControl(). -> .
61
//@olsen: subst: noteList -> note
62
//@olsen: added: support for I18N
63
//@olsen: subst: FilterError -> UserException, affirm()
64
//@olsen: removed: proprietary support for HashCode
65
//@olsen: removed: support for [No]AnnotateField
66
//@olsen: removed: old, disabled ODI code
67

68
69 /*
70  * The current code annotation strategy
71  * 1) getfield instructions operating on persistent types cause a fetch
72  * 2) putfield instructions operating on persistent types cause a dirty
73  * 3) fetches which can be identified to be a fetch of "this" are moved
74  * to the start of the method.
75  * 3) dirties which can be identified to be a dirty of "this" are moved
76  * to the start of the method only if the code path to the dirty is
77  * unconditional.
78  * 4) Array loads cause array fetches
79  * 5) Array stores cause array dirtys
80  * 6) Each array fetch/dirty call which occurs in a loop construct
81  * is allocated a dedicated local variable which is used to cache
82  * the last array dirtied or fetched by the instruction in order to
83  * minimize the overhead in array manipulation within a loop.
84  * 7) In calls to methods in non-persistence-aware classes which are
85  * declared to take array parameters, the array parameter is fetched.
86  * If the called code stores to the array, the user must manually
87  * annotate.
88  * 8) Certain method invocations trigger fetches or dirties of arguments.
89  * These special cases are listed in InvokeAnnotation.java.
90  *
91  * Possible Alternative Code Annotation strategy
92  * 1) non-static non-private methods always fetch/dirty "this"
93  * 2) non-static private methods never fetch but may dirty "this"
94  * 3) invocations of private methods from static methods fetch the target
95  * 4) invocations of private methods from non-static methods fetch the
96  * target if it can't be identified as "this"
97  * 5) putfields always cause dirtying of the target but if the
98  * target is known to be this, promote to a dirty of this.
99  * 6) getfields only cause fetching of the target if the
100  * target is not known to be this
101  * 7) Array loads cause array fetches
102  * 8) Array stores cause array dirtys
103  */

104
105
106 /**
107  * MethodAnnotater controls the code annotation for a single method
108  * within a class.
109  */

110 //^olsen: move code -> MethodAction
111
class MethodAnnotater
112     extends Support
113     implements AnnotationConstants {
114
115     //@olsen: made final
116
private final ClassAction ca;
117
118     //@olsen: made final
119
private final ClassMethod method;
120
121     //@olsen: made final
122
private final ConstantPool pool;
123
124     /* Central repository for the options and classes */
125     //@olsen: added association
126
//@olsen: made final
127
private final Environment env;
128
129     /* What types of annotation will be done on the method? */
130     private int annotate;
131
132     /* List of single element register values (Integer) for temporaries */
133     private Vector JavaDoc tmpRegisters;
134
135     /* List of double element register values (Integer) for temporaries */
136     private Vector JavaDoc tmpDoubleRegisters;
137
138     /* List of single word register values which cache fetches/stores
139      * Each of these registers must be initialized to null at the start of
140      * the method */

141 //@olsen: disabled feature
142
/*
143     private Vector caches;
144 */

145
146     /* The maximum amount of stack needed by any specific annotation sequence,
147      * less the amount of stack which the annotated instruction is known to
148      * need, if any */

149     private short annotationStack = 0;
150
151     /* If true, the method will contain an unconditional fetch(this) */
152 //@olsen: disabled feature
153
/*
154     private boolean fetchThis = false;
155 */

156
157     /* If true, the method will contain an unconditional dirty(this) */
158 //@olsen: disabled feature
159
/*
160     private boolean dirtyThis = false;
161 */

162
163     /* Table mapping Insn to InsnNote - allows annotation computations to
164      * be attached to instructions non-intrusively */

165     private Map JavaDoc insnNotes = new HashMap JavaDoc(11);
166
167     /* The largest loop contained within the method, or null. */
168 //@olsen: disabled feature
169
/*
170     private Loop largestLoop;
171 */

172
173     // package accessors
174

175     /**
176      * Is any annotation needed for this method? The result of this
177      * method isn't valid until after checkMethod has been run.
178      */

179     boolean needsAnnotation() {
180         return annotate != 0;
181     }
182
183     /**
184      * Constructor
185      */

186     //@olsen: added parameter 'env' for association
187
MethodAnnotater(ClassAction ca,
188                     ClassMethod method,
189                     Environment env) {
190         this.ca = ca;
191         this.method = method;
192         this.env = env;
193         this.pool = ca.classFile().pool();
194     }
195
196 // ---------------------------------------------------------------------------
197

198     /**
199      * Examine the method to determine what sort of annotations are needed
200      */

201     void checkMethod() {
202         //@olsen: added printing output
203
env.message(
204             "checking method " + ca.userClassName()//NOI18N
205
+ "." + method.name().asString()//NOI18N
206
+ Descriptor.userMethodArgs(method.signature().asString()));
207
208         //@olsen: cosmetics
209
annotate = 0;
210         final CodeAttribute codeAttr = method.codeAttribute();
211         if (codeAttr == null) {
212             return;
213         }
214
215 //^olsen: make robust
216
/*
217         if (isAnnotated(codeAttr)) {
218             env.message("Method " + ca.userClassName() +
219                         "." + method.name().asString() +
220                         Descriptor.userMethodArgs(method.signature().asString()) +
221                         " is already annotated.");
222             return;
223         }
224 */

225
226         // look for certain special cases to avoid
227
//@olsen: cosmetics
228
if (avoidAnnotation()) {
229             return;
230         }
231         checkCode(codeAttr);
232
233 //@olsen: disabled feature
234
/*
235         if (!avoidAnnotation()) {
236             largestLoop = Loop.checkLoops(codeAttr.theCode());
237             checkCode(codeAttr);
238         } else if (methodIsPersistentFinalize()) {
239             annotate = MakeThisTransient;
240         }
241 */

242     }
243
244     /**
245      * Check to see if the code attribute contains any calls to
246      * Implementaiton.fetch, or Implementation.dirty
247      */

248 //^olsen: make robust
249
/*
250     private boolean isAnnotated(CodeAttribute codeAttr) {
251         for (Insn insn = codeAttr.theCode();
252              insn != null;
253              insn = insn.next()) {
254
255             // All non-interface method invocations are InsnConstOp
256
257             if (insn instanceof InsnConstOp) {
258                 InsnConstOp coInsn = (InsnConstOp) insn;
259                 ConstBasic operand = coInsn.value();
260                 if (operand instanceof ConstMethodRef) {
261
262                     // A method invocation of some sort
263
264                     ConstMethodRef methRef = (ConstMethodRef) operand;
265                     if (methRef.className().asString().equals("com/sun/forte4j/persistence/internal/Implementation")) {
266
267                         // A method invocation against class Persistent
268
269                         ConstNameAndType nt = methRef.nameAndType();
270                         String ntName = nt.name().asString();
271                         if (ntName.equals("fetch") || ntName.equals("dirty"))
272                             // A fetch or a dirty call
273                             return true;
274                     }
275                 }
276             }
277         }
278         return false;
279     }
280 */

281
282     /**
283      * Check to see if this method is an initializer.
284      */

285 //@olsen: disabled feature
286
/*
287     private boolean methodIsInitializer() {
288         String methName = method.name().asString();
289         //^olsen: check for serialization
290         return (methName.equals("<init>") ||
291                 (methName.equals("readObject") &&
292                  method.signature().asString().equals(
293                      "(Ljava/io/ObjectInputStream;)V")));
294     }
295 */

296
297
298     /**
299      * Check to see if this method is a finalize method.
300      */

301 //@olsen: disabled feature
302
/*
303     private boolean methodIsFinalize() {
304         return (method.name().asString().equals("finalize") &&
305                 method.signature().asString().equals("()V") &&
306                 !method.isStatic());
307     }
308 */

309
310     /**
311      * Check to see if this method is an persistent finalize.
312      */

313 //@olsen: disabled feature
314
/*
315     private boolean methodIsPersistentFinalize() {
316         return (methodIsFinalize() &&
317                 ca.persistCapable());
318     }
319 */

320
321     /**
322      * Check to see if this is a special case that should not be
323      * annotated.
324      */

325     private boolean avoidAnnotation() {
326         //@olsen: cosmetics
327

328 //@olsen: allow for annotating initializers+finalizers
329
/*
330         final String methodName = method.name().asString();
331         final String methodSig = method.signature().asString();
332
333         if (methodName.equals("<clinit>") || methodIsFinalize())
334             // Never annotate class initializers or finalizers
335             return true;
336 */

337
338 //^olsen: enable feature, rather use HashMap for lookup
339
//@olsen: disabled feature
340
/*
341         if (ca.persistCapable()) {
342             if ((methodName.equals("initializeContents") &&
343                  methodSig.equals("(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V")) ||
344                 (methodName.equals("flushContents") &&
345                  methodSig.equals("(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V")) ||
346                 (methodName.equals("clearContents") &&
347                  methodSig.equals("()V")) ||
348                 (methodName.equals("postInitializeContents") &&
349                  methodSig.equals("()V")) ||
350                 (methodName.equals("preFlushContents") &&
351                  methodSig.equals("()V")) ||
352                 (methodName.equals("preClearContents") &&
353                  methodSig.equals("()V")) ||
354                 (methodName.equals("jdoGetStateManager") &&
355                  methodSig.equals("()Lcom/sun/forte4j/persistence/internal/StateManager;")) ||
356                 (methodName.equals("jdoSetStateManager") &&
357                  methodSig.equals("(Lcom/sun/forte4j/persistence/internal/StateManager;)V")) ||
358                 (methodName.equals("jdoGetFlags") &&
359                  methodSig.equals("()B")) ||
360                 (methodName.equals("jdoSetFlags") &&
361                  methodSig.equals("(B)V")))
362                 // This is one of the special persistence actions.
363                 // Don't annotate it
364                 return true;
365         }
366 */

367
368         return false;
369     }
370
371 // ---------------------------------------------------------------------------
372

373     /**
374      * Check the code attribute for possible annotations
375      */

376     //^olsen: move code to inner class ?!
377
void checkCode(CodeAttribute codeAttr) {
378         //@olsen: cosmetics
379
Insn firstInsn = codeAttr.theCode();
380
381         // mark branch targets so we can distinguish them from
382
// targets which exist for the benefit of line numbers,
383
// local variables, etc.
384
for (Insn markInsn = firstInsn;
385              markInsn != null;
386              markInsn = markInsn.next()) {
387             markInsn.markTargets();
388         }
389
390         int allFlags = 0;
391 //@olsen: disabled feature
392
/*
393         boolean branchesSeen = false;
394 */

395
396         for (Insn insn = firstInsn; insn != null; insn = insn.next() ) {
397             InsnNote note = null;
398
399             switch(insn.opcode()) {
400 //@olsen: disabled feature
401
/*
402             case opc_invokestatic:
403             case opc_invokespecial:
404             case opc_invokevirtual:
405             case opc_invokeinterface:
406                 note = noteInvokeAnnotation(insn);
407                 break;
408 */

409             case opc_getfield:
410                 note = noteGetFieldAnnotation(insn);
411                 break;
412             case opc_putfield:
413                 note = notePutFieldAnnotation(insn);
414                 break;
415 //@olsen: disabled feature
416
/*
417             case opc_aaload:
418             case opc_baload:
419             case opc_caload:
420             case opc_saload:
421             case opc_iaload:
422             case opc_laload:
423             case opc_faload:
424             case opc_daload:
425                 note = noteArrayLoadAnnotation(insn);
426                 break;
427             case opc_aastore:
428             case opc_bastore:
429             case opc_castore:
430             case opc_sastore:
431             case opc_iastore:
432             case opc_lastore:
433             case opc_fastore:
434             case opc_dastore:
435                 note = noteArrayStoreAnnotation(insn);
436                 break;
437 */

438             default:
439                 break;
440             }
441
442             if (note != null) {
443                 addNoteList(note);
444
445                 //@olsen: ensured to use single note only (as instantiated)
446
affirm((note.next() == null),
447                        "Number of annotation notes for instruction > 1.");//NOI18N
448
allFlags |= note.insnFlags;
449
450 //@olsen: ensured to use single note only (as instantiated)
451
/*
452                 for (InsnNote aNote = note;
453                      aNote != null;
454                      aNote = aNote.next()) {
455 //@olsen: disabled feature
456 ///
457                     if (branchesSeen == false)
458                         aNote.insnFlags |= Unconditional;
459 ///
460
461 //@olsen: disabled feature
462 ///
463                     if (largestLoop != null && largestLoop.contains(insn))
464                         aNote.insnFlags |= InLoop;
465 ///
466
467 //@olsen: disabled feature
468 ///
469                     // annotating based on thisOptimization will be done later
470                     if (aNote.dirtyThis() && aNote.unconditional())
471                         dirtyThis = true;
472                     else if (aNote.dirtyThis() || aNote.fetchThis())
473                         fetchThis = true;
474 ///
475
476                     allFlags |= aNote.insnFlags;
477                 }
478 */

479             }
480
481 //@olsen: disabled feature
482
/*
483             if (insn.branches())
484                 branchesSeen = true;
485 */

486         }
487
488 //@olsen: disabled feature
489
/*
490         if (methodIsInitializer()) {
491             // An inititalizer - either force the fetchThis, dirtyThis flags
492             // on or off.
493             if (env.doInitializerOptimization()) {
494                 // turn on the fetchThis, dirtyThis flags to inhibit fetches
495                 // and stores of this if enabled. We won't really insert the
496                 // fetch/dirty, since it isn't needed.
497                 fetchThis = true;
498                 dirtyThis = true;
499             } else {
500                 // Make sure that the fetchThis, dirtyThis flags are turned off
501                 fetchThis = false;
502                 dirtyThis = false;
503             }
504         }
505 */

506
507         //^olsen: prepare for inheritance on PC classes
508
//@olsen: check for annotating of clone()
509
final String JavaDoc methodName = method.name().asString();
510         final String JavaDoc methodSig = method.signature().asString();
511         //^olsen: annotate persistence-capable root classes only
512
// until the JDO spec precisely defines how to treat
513
// user-defined clone methods in transient classes
514
final boolean implementsPersistence = ca.getImplementsPersistence();
515         if (false) {
516             System.out.println(" check for annotating clone()");//NOI18N
517
System.out.println(" methodName = " + methodName);//NOI18N
518
System.out.println(" methodSig = " + methodSig);//NOI18N
519
System.out.println(" implementsPersistence = "//NOI18N
520
+ implementsPersistence);
521         }
522         if (methodName.equals("clone")//NOI18N
523
&& methodSig.equals("()Ljava/lang/Object;")//NOI18N
524
&& implementsPersistence) {
525             //^olsen: rather scan for 'invokespecial clone()Ljava/lang/Object;'
526
// in instruction loop above
527
allFlags |= SuperClone;
528         }
529
530 //@olsen: disabled feature
531
/*
532         if (methodName.equals("clone") &&
533             methodSig.equals("()Ljava/lang/Object;") &&
534             ca.persistCapable()) {
535             allFlags |= FetchThis;
536             fetchThis = true;
537         }
538 */

539         annotate = allFlags;
540     }
541
542
543     /**
544      * Make note of annotations if needed for a method invocation instruction.
545      */

546 //@olsen: disabled feature
547
/*
548     private InsnNote noteInvokeAnnotation(Insn insn) {
549         int flags = 0;
550
551         ConstBasicMemberRef methRef = (ConstBasicMemberRef)
552             ((InsnConstOp)insn).value();
553
554         InsnArgNote note = null;
555
556         for (InvokeAnnotation invAnn
557                  = InvokeAnnotation.checkInvoke(methRef, env);
558              invAnn != null;
559              invAnn = invAnn.next()) {
560             int thisFlags = 0;
561             Insn dep = findArgDepositer(insn, invAnn.whichArg());
562             if (dep != null && dep.opcode() == opc_aload_0 && !method.isStatic()) {
563                 if ((invAnn.annotateHow() & DirtyAny) != 0)
564                     thisFlags = DirtyThis;
565                 else
566                     thisFlags = FetchThis;
567             } else
568                 thisFlags = invAnn.annotateHow();
569
570             InsnArgNote newNote =
571                 new InsnArgNote(insn, thisFlags, invAnn.whichArg(),
572                                 Descriptor.extractArgSig(
573                                     methRef.nameAndType().signature().asString()));
574
575             // sort in order of decreasing stack depth
576             if (note == null || note.arg() < newNote.arg()) {
577                 newNote.nextNote = note;
578                 note = newNote;
579             } else {
580                 InsnArgNote aNote = note;
581                 while (aNote.nextNote != null && aNote.nextNote.arg() > newNote.arg())
582                     aNote = aNote.nextNote;
583                 newNote.nextNote = aNote.nextNote;
584                 aNote.nextNote = newNote;
585             }
586         }
587
588         return note;
589     }
590 */

591
592     /**
593      * make note of annotations if needed for the getField instruction.
594      */

595     //^olsen: merge code with notePutFieldAnnotation() ?!
596
private InsnNote noteGetFieldAnnotation(Insn insn) {
597         //@olsen: cosmetics
598
final InsnConstOp getFieldInsn = (InsnConstOp)insn;
599         final ConstFieldRef fieldRef = (ConstFieldRef)getFieldInsn.value();
600         final String JavaDoc fieldOf = fieldRef.className().asString();
601
602         //@olsen: changed to use JDOMetaData
603
final String JavaDoc fieldName
604             = fieldRef.nameAndType().name().asString();
605         final JDOMetaData meta = env.getJDOMetaData();
606         if (!meta.isPersistentField(fieldOf, fieldName))
607             return null;
608
609 //@olsen: disabled feature
610
/*
611         final ClassControl cc = env.findClass(fieldOf);
612
613         if (cc == null || !cc.persistCapable())
614             return null;
615 */

616
617         //@olsen: added checks
618
final boolean dfgField
619             = meta.isDefaultFetchGroupField(fieldOf, fieldName);
620         final boolean pkField
621             = meta.isPrimaryKeyField(fieldOf, fieldName);
622         final int fieldIndex
623             = meta.getFieldNo(fieldOf, fieldName);
624         final String JavaDoc targetPCRootClass
625             = meta.getPersistenceCapableRootClass(fieldOf);
626
627         int flags = 0;
628         //@olsen: added variables
629
final String JavaDoc fieldSig = fieldRef.nameAndType().signature().asString();
630         // there's no field value on the stack yet
631
final int stackArgSize = 0;
632
633         //@olsen: added println() for debugging
634
if (false) {
635             System.out.println(" get field "//NOI18N
636
+ fieldOf + "." + fieldName//NOI18N
637
+ "[" + fieldIndex + "]"//NOI18N
638
+ "<" + fieldSig + ">"//NOI18N
639
+ " : p"//NOI18N
640
+ (dfgField ? ",dfg" : ",!dfg")//NOI18N
641
+ (pkField ? ",pk" : ",!pk")//NOI18N
642
+ ";");//NOI18N
643
}
644
645         Insn dep = findArgDepositer(insn, stackArgSize);
646         if (dep != null
647             && dep.opcode() == opc_aload_0
648             && !method.isStatic())
649             // This represents a fetch of "this"
650
flags |= FetchThis;
651         else
652             flags |= FetchPersistent;
653
654         //@olsen: added test
655
if (dfgField)
656             flags |= DFGField;
657
658         //@olsen: added test
659
if (pkField)
660             flags |= PKField;
661
662         //@olsen: changed to use JDOMetaData
663
return new InsnNote(insn, flags,
664                             stackArgSize,
665                             fieldSig, fieldOf, fieldName, fieldIndex,
666                             targetPCRootClass);
667 //@olsen: disabled feature
668
/*
669         return new InsnNote(insn, flags, 0, "", cc.action());
670 */

671     }
672
673     /**
674      * Generate annotations if needed for the putField instruction.
675      */

676     //^olsen: merge code with noteGetFieldAnnotation() ?!
677
private InsnNote notePutFieldAnnotation(Insn insn) {
678         //@olsen: cosmetics
679
final InsnConstOp putFieldInsn = (InsnConstOp)insn;
680         final ConstFieldRef fieldRef = (ConstFieldRef)putFieldInsn.value();
681         final String JavaDoc fieldOf = fieldRef.className().asString();
682
683         //@olsen: changed to use JDOMetaData
684
final String JavaDoc fieldName
685             = fieldRef.nameAndType().name().asString();
686         final JDOMetaData meta = env.getJDOMetaData();
687         if (!meta.isPersistentField(fieldOf, fieldName))
688             return null;
689
690 //@olsen: disabled feature
691
/*
692         final ClassControl cc = env.findClass(fieldOf);
693
694         if (cc == null || !cc.persistCapable())
695             return null;
696 */

697
698         //@olsen: added checks
699
final boolean dfgField
700             = meta.isDefaultFetchGroupField(fieldOf, fieldName);
701         final boolean pkField
702             = meta.isPrimaryKeyField(fieldOf, fieldName);
703         final int fieldIndex
704             = meta.getFieldNo(fieldOf, fieldName);
705         final String JavaDoc targetPCRootClass
706             = meta.getPersistenceCapableRootClass(fieldOf);
707
708         int flags = 0;
709         //@olsen: added variables
710
final String JavaDoc fieldSig = fieldRef.nameAndType().signature().asString();
711         // size of field value on the stack
712
final int stackArgSize
713             = (fieldSig.equals("J") || fieldSig.equals("D")) ? 2 : 1;//NOI18N
714

715         //@olsen: added println() for debugging
716
if (false) {
717             System.out.println(" put field "//NOI18N
718
+ fieldOf + "." + fieldName//NOI18N
719
+ "[" + fieldIndex + "]"//NOI18N
720
+ "<" + fieldSig + ">"//NOI18N
721
+ " : p"//NOI18N
722
+ (dfgField ? ",dfg" : ",!dfg")//NOI18N
723
+ (pkField ? ",pk" : ",!pk")//NOI18N
724
+ ";");//NOI18N
725
}
726
727         Insn dep = findArgDepositer(insn, stackArgSize);
728         if (dep != null
729             && dep.opcode() == opc_aload_0
730             && !method.isStatic())
731             // This represents a dirtyfication of "this"
732
flags |= DirtyThis;
733         else
734             flags |= DirtyPersistent;
735
736         //@olsen: added test
737
if (dfgField)
738             flags |= DFGField;
739
740         //@olsen: added test
741
if (pkField)
742             flags |= PKField;
743
744         //@olsen: changed to use JDOMetaData
745
return new InsnNote(insn, flags,
746                             stackArgSize,
747                             fieldSig, fieldOf, fieldName, fieldIndex,
748                             targetPCRootClass);
749 //@olsen: disabled feature
750
/*
751         return new InsnNote(insn, flags, stackArgSize, fieldSig, cc.action());
752 */

753     }
754
755     /**
756      * Generate annotations if needed for the arrayLoad instruction.
757      */

758 //@olsen: disabled feature
759
/*
760     private InsnNote noteArrayLoadAnnotation(Insn insn) {
761         int arrayFetchType = 0;
762         switch(insn.opcode()) {
763         case opc_aaload:
764             arrayFetchType = ArrayTypeObject;
765             break;
766         case opc_caload:
767             arrayFetchType = ArrayTypeChar;
768             break;
769         case opc_saload:
770             arrayFetchType = ArrayTypeShort;
771             break;
772         case opc_iaload:
773             arrayFetchType = ArrayTypeInt;
774             break;
775         case opc_laload:
776             arrayFetchType = ArrayTypeLong;
777             break;
778         case opc_faload:
779             arrayFetchType = ArrayTypeFloat;
780             break;
781         case opc_daload:
782             arrayFetchType = ArrayTypeDouble;
783             break;
784         case opc_baload:
785             // Unfortunately, both byte arrays and boolean arrays are accessed
786             // using the same instruction so don't attempt to infer the array
787             // element type for these.
788             break;
789         }
790         return new InsnNote(insn, FetchArray | arrayFetchType, 1, "I", null);
791     }
792 */

793
794 //@olsen: disabled feature
795
/*
796     private InsnNote noteArrayStoreAnnotation(Insn insn) {
797         int valueType = Insn.loadStoreDataType(insn.opcode());
798         int valueSize = Descriptor.elementSize(valueType);
799         String stackSig = "I" + Descriptor.elementSig(valueType);
800
801         // Compute the array store type for completeness. The generated
802         // annotation currently doesn't use this information because there
803         // are no array element type-specific overloads of dirty() but
804         // perhaps we'll add them at some point.
805         int arrayStoreType = 0;
806         switch(insn.opcode()) {
807         case opc_aastore:
808             arrayStoreType = ArrayTypeObject;
809             break;
810         case opc_castore:
811             arrayStoreType = ArrayTypeChar;
812             break;
813         case opc_sastore:
814             arrayStoreType = ArrayTypeShort;
815             break;
816         case opc_iastore:
817             arrayStoreType = ArrayTypeInt;
818             break;
819         case opc_lastore:
820             arrayStoreType = ArrayTypeLong;
821             break;
822         case opc_fastore:
823             arrayStoreType = ArrayTypeFloat;
824             break;
825         case opc_dastore:
826             arrayStoreType = ArrayTypeDouble;
827             break;
828         case opc_bastore:
829             // Unfortunately, both byte arrays and boolean arrays are accessed
830             // using the same instruction so don't attempt to infer the array
831             // element type for these.
832             break;
833         }
834
835         return new InsnNote(insn, DirtyArray | arrayStoreType,
836                             valueSize+1, stackSig, null);
837     }
838 */

839
840 // ---------------------------------------------------------------------------
841

842     /**
843      * Annotate the class method. For now, brute force rules.
844      */

845     void annotateMethod() {
846         //@olsen: cosmetics
847
final CodeAttribute codeAttr = method.codeAttribute();
848         if (codeAttr == null || !needsAnnotation())
849             return;
850
851 //@olsen: disabled feature
852
/*
853         if ((annotate & MakeThisTransient) != 0) {
854             makeThisTransient(codeAttr);
855             if (annotate == MakeThisTransient)
856                 return;
857         }
858 */

859
860         //@olsen: added printing output
861
env.message(
862             "annotating method " + ca.userClassName()//NOI18N
863
+ "." + method.name().asString()//NOI18N
864
+ Descriptor.userMethodArgs(method.signature().asString()));
865
866 //@olsen: disabled feature
867
/*
868         clearThisAnnotation();
869         removeRedundantThisAnnotation();
870 */

871
872         Insn firstInsn = codeAttr.theCode();
873
874         // First instruction is a target
875
Insn insn = firstInsn.next();
876
877         while (insn != null) {
878             switch(insn.opcode()) {
879 //@olsen: disabled feature
880
/*
881             case opc_invokestatic:
882             case opc_invokespecial:
883             case opc_invokevirtual:
884             case opc_invokeinterface:
885 */

886             case opc_getfield:
887             case opc_putfield:
888 //@olsen: disabled feature
889
/*
890             case opc_aaload:
891             case opc_baload:
892             case opc_caload:
893             case opc_saload:
894             case opc_iaload:
895             case opc_laload:
896             case opc_faload:
897             case opc_daload:
898             case opc_aastore:
899             case opc_bastore:
900             case opc_castore:
901             case opc_sastore:
902             case opc_iastore:
903             case opc_lastore:
904             case opc_fastore:
905             case opc_dastore:
906 */

907                 insn = insnAnnotation(insn);
908                 break;
909             default:
910                 break;
911             }
912
913             insn = insn.next();
914         }
915
916         //@olsen: do special annotation if detected super.clone()
917
if ((annotate & SuperClone) != 0) {
918             final String JavaDoc superName = ca.classFile().superName().asString();
919             annotateClone(codeAttr, superName);
920         }
921
922 //@olsen: disabled feature
923
/*
924         if (methodIsInitializer()) {
925         } else {
926             // Pre- fetch/dirty this if needed
927             if (fetchThis || dirtyThis) {
928                 // Optimize a fetch(this) or dirty(this) to the start of
929                 // the method.
930                 // For fetch calls this is:
931                 // if (jdoFlags < 0)
932                 // Implementation.fetch(this);
933                 //
934                 // For dirty calls this is:
935                 // if ((jdoFlags&PersistenceCapable.writeBarrierSet) != 0)
936                 // Implementation.dirty(this);
937
938                 Insn newInsn = Insn.create(opc_aload_0);
939                 Insn annotationStart = newInsn;
940                 InsnTarget afterCondition = null;
941
942 //@olsen: disabled feature
943 ///
944                 if (ca.getFlagsMemberValid() &&
945                     ca.getFlagsMember() != null) {
946 ///
947
948                     //@olsen: changed to use JDOMetaData
949                     final String className = ca.className();
950                     final String pcRootClass
951                         = env.getJDOMetaData().getPersistenceCapableRootClass(className);
952                     newInsn = newInsn.append(
953                         Insn.create(opc_getfield,
954                                     pool.addFieldRef(
955                                         pcRootClass,
956                                         JDOMetaData.JDOFlagsFieldName,
957                                         JDOMetaData.JDOFlagsFieldSig)));
958 //@olsen: disabled feature
959 ///
960                     ClassControl flagsCC
961                         = ca.getFlagsMemberClassControl();
962                     newInsn = newInsn.append(
963                         Insn.create(opc_getfield,
964                                     pool.addFieldRef(
965                                         flagsCC.className(),
966                                         ca.getFlagsMember(),
967                                         "B")));
968 ///
969
970                     afterCondition = new InsnTarget();
971                     if (dirtyThis) {
972                         newInsn = newInsn.append(Insn.create(opc_iconst_2));
973                         newInsn = newInsn.append(Insn.create(opc_iand));
974                         newInsn = newInsn.append(Insn.create(opc_ifeq, afterCondition));
975                         newInsn = newInsn.append(Insn.create(opc_aload_0));
976                     } else {
977                         newInsn = newInsn.append(Insn.create(opc_ifge, afterCondition));
978                         newInsn = newInsn.append(Insn.create(opc_aload_0));
979                     }
980 //@olsen: disabled feature
981 ///
982                 }
983 ///
984
985                 newInsn = newInsn.append(
986                     Insn.create(
987                         opc_invokestatic,
988                         pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation",
989                                           (dirtyThis ? "dirty" : "fetch"),
990                                           "(" + JDOMetaData.JDOPersistenceCapableSig + ")V")));
991
992                 if (afterCondition != null)
993                     newInsn = newInsn.append(afterCondition);
994                 firstInsn.insert(annotationStart);
995                 noteStack(2);
996             }
997
998 //@olsen: disabled feature
999 ///
1000            if (methodName.equals("clone") &&
1001                methodSig.equals("()Ljava/lang/Object;") &&
1002                !ca.getNeedsClone()) {
1003                annotateClone(codeAttr, superName);
1004            }
1005///
1006//@olsen: disabled feature
1007        }
1008*/

1009
1010//@olsen: disabled feature
1011
/*
1012        //^olsen: caches -> int[] ?
1013        if (caches != null && caches.size() > 0) {
1014            // Generate fetch/dirty cache initializers
1015            Insn initInsn = null;
1016            //^olsen: optimize traversal ?
1017            for (int i = 0; i < caches.size(); i++) {
1018                int slot = ((Integer) caches.elementAt(i)).intValue();
1019                Insn nullInsn = Insn.create(opc_aconst_null);
1020                if (initInsn == null)
1021                    initInsn = nullInsn;
1022                else
1023                    initInsn.append(nullInsn);
1024                initInsn.append(InsnUtils.aStore(slot, pool));
1025            }
1026
1027            // These initializations must not occur in an
1028            // exception handler or the code may fail to verify. If an
1029            // exception handler starts at offset 0, our initializations
1030            // will fall into the exception handler block. For
1031            // simplicity, just add a new target as the initial
1032            // instruction - it doesn't cost anything in the
1033            // generated code.
1034            InsnTarget newFirstInsn = new InsnTarget();
1035            initInsn.append(firstInsn);
1036            newFirstInsn.append(initInsn);
1037            firstInsn = newFirstInsn;
1038            codeAttr.setTheCode(firstInsn);
1039        }
1040*/

1041
1042        if (annotationStack > 0)
1043            codeAttr.setStackUsed(codeAttr.stackUsed() + annotationStack);
1044    }
1045
1046// ---------------------------------------------------------------------------
1047

1048    /**
1049     * If dirtyThis or fetchThis is set, remove flags indicating the need to
1050     * fetch or dirth "this" on individual instructions.
1051     */

1052//@olsen: disabled feature
1053
/*
1054    private void clearThisAnnotation() {
1055        // If the user has disabled "this" optimization, simply turn the
1056        // dirtyThis and fetchThis flags off unless this is an initializer
1057        // method, in which case we defer reseting the flags until the end
1058        // of this method.
1059        if (!env.doThisOptimization() && !methodIsInitializer()) {
1060            dirtyThis = false;
1061            fetchThis = false;
1062        }
1063
1064        if (!dirtyThis && !fetchThis)
1065            return;
1066
1067        final CodeAttribute codeAttr = method.codeAttribute();
1068        if (codeAttr != null) {
1069            for (Insn insn = codeAttr.theCode();
1070                 insn != null;
1071                 insn = insn.next()) {
1072                for (InsnNote note = getNoteList(insn);
1073                     note != null;
1074                     note = note.next()) {
1075
1076                    if (dirtyThis && note.dirtyThis())
1077                        note.dontDirtyThis();
1078                    if ((dirtyThis || fetchThis) && note.fetchThis())
1079                        note.dontFetchThis();
1080                }
1081            }
1082        }
1083
1084        if (methodIsInitializer()) {
1085            dirtyThis = false;
1086            fetchThis = false;
1087        }
1088    }
1089*/

1090
1091    /**
1092     * Optimize out obviously redundant fetch(this) and dirty(this)
1093     * annotations. These are repeated fetches and dirties which occur
1094     * in straight-line code with no intervening branch targets or
1095     * method calls.
1096     */

1097//@olsen: disabled feature
1098
/*
1099    private void removeRedundantThisAnnotation() {
1100        // This optimization doesn't apply to static methods or initializers.
1101        // Static methods are ignored because they don't have a "this" and
1102        // initializers may be excluded if we expect that there are no
1103        // fetch/dirty of "this".
1104        if (method.isStatic() ||
1105            (methodIsInitializer() && env.doInitializerOptimization()))
1106            return;
1107
1108        CodeAttribute codeAttr = method.codeAttribute();
1109        if (codeAttr != null && needsAnnotation()) {
1110            Insn firstInsn = codeAttr.theCode();
1111
1112            // First instruction is a target
1113            Insn insn = firstInsn.next();
1114
1115            boolean thisFetched = false;
1116            boolean thisDirtied = false;
1117
1118            while (insn != null) {
1119
1120                for (InsnNote note = getNoteList(insn);
1121                     note != null;
1122                     note = note.next()) {
1123
1124                    if (note.fetchThis()) {
1125                        if (thisFetched)
1126                            note.dontFetchThis();
1127                        else
1128                            thisFetched = true;
1129                    }
1130                    if (note.dirtyThis()) {
1131                        if (thisDirtied)
1132                            note.dontDirtyThis();
1133                        else {
1134                            thisDirtied = true;
1135                            thisFetched = true;
1136                        }
1137                    }
1138                }
1139
1140                boolean invalidate = false;
1141                switch(insn.opcode()) {
1142                case opc_jsr:
1143                case opc_invokestatic:
1144                case opc_invokespecial:
1145                case opc_invokevirtual:
1146                case opc_invokeinterface:
1147                    invalidate = true;
1148                    break;
1149
1150                case opc_monitorenter:
1151                    // If the code is explicitly synchronizing then the user
1152                    // might have some reason to expect instructions to
1153                    // interleave against another thread execution in a
1154                    // particular order, so invalidate any assumption about
1155                    // the fetch/dirty flags
1156                    invalidate = true;
1157                    break;
1158
1159                case Insn.opc_target:
1160                    // targets which result from line-number info, etc. do not
1161                    // invalidate the optimization
1162                    if (((InsnTarget)insn).isBranchTarget())
1163                        invalidate = true;
1164                    break;
1165
1166                default:
1167                    break;
1168                }
1169
1170                if (invalidate) {
1171                    thisFetched = false;
1172                    thisDirtied = false;
1173                }
1174
1175                insn = insn.next();
1176            }
1177        }
1178    }
1179*/

1180
1181// ---------------------------------------------------------------------------
1182

1183    //^olsen: extend for full support of inheritance on PC classes
1184
//@olsen: reimplemented this method
1185
private void annotateClone(CodeAttribute codeAttr,
1186                               String JavaDoc superName) {
1187        if (false) {
1188            final String JavaDoc methodName = method.name().asString();
1189            final String JavaDoc methodSig = method.signature().asString();
1190            System.out.println("annotateClone()");//NOI18N
1191
System.out.println(" methodName = " + methodName);//NOI18N
1192
System.out.println(" methodSig = " + methodSig);//NOI18N
1193
System.out.println(" superName = " + superName);//NOI18N
1194
}
1195
1196        Insn insn;
1197        for (insn = codeAttr.theCode();
1198             insn != null;
1199             insn = insn.next()) {
1200
1201            // Found the clone method. See if it is the flavor of clone()
1202
// which does a super.clone() call, and if it is, add
1203
// field initializations for the jdoStateManager and jdoFlags
1204
// fields.
1205
if (insn.opcode() != opc_invokespecial)
1206                continue;
1207
1208            final InsnConstOp invoke = (InsnConstOp)insn;
1209            final ConstMethodRef methodRef = (ConstMethodRef)invoke.value();
1210            final ConstNameAndType methodNT = methodRef.nameAndType();
1211            final String JavaDoc methodName = methodNT.name().asString();
1212            final String JavaDoc methodSig = methodNT.signature().asString();
1213
1214            if (!(methodName.equals("clone")//NOI18N
1215
&& methodSig.equals("()Ljava/lang/Object;")))//NOI18N
1216
continue;
1217
1218            if (false) {
1219                final ConstClass methodClass = methodRef.className();
1220                final String JavaDoc methodClassName = methodClass.asString();
1221                System.out.println(" found invocation of: "//NOI18N
1222
+ methodClassName
1223                                   + "." + methodName + methodSig);//NOI18N
1224
}
1225
1226            // check whether next instruction already is a downcast to a
1227
// class implementing PersistenceCapable
1228
final String JavaDoc thisClass = ca.className();
1229            final Insn checkCastInsn = insn.next();
1230            final boolean needCheckcast;
1231            if (checkCastInsn.opcode() != opc_checkcast) {
1232                needCheckcast = true;
1233            } else {
1234                ConstClass target =
1235                    (ConstClass) ((InsnConstOp) checkCastInsn).value();
1236                if (target.asString().equals(thisClass)) {
1237                    insn = checkCastInsn;
1238                    needCheckcast = false;
1239                } else {
1240                    needCheckcast = true;
1241                }
1242            }
1243
1244            // clear jdo fields of clone
1245
{
1246                // duplicate downcastet reference
1247
final Insn newInsn = Insn.create(opc_dup);
1248                if (needCheckcast) {
1249                    newInsn.append(Insn.create(opc_checkcast,
1250                                               pool.addClass(thisClass)));
1251                }
1252                newInsn.append(Insn.create(opc_dup));
1253
1254                // clear jdo fields
1255
newInsn.append(Insn.create(opc_aconst_null));
1256                newInsn.append(Insn.create(
1257                    opc_putfield,
1258                    pool.addFieldRef(thisClass,
1259                                     JDOMetaData.JDOStateManagerFieldName,
1260                                     JDOMetaData.JDOStateManagerFieldSig)));
1261                newInsn.append(Insn.create(opc_iconst_0));
1262                newInsn.append(Insn.create(
1263                    opc_putfield,
1264                    pool.addFieldRef(thisClass,
1265                                     JDOMetaData.JDOFlagsFieldName,
1266                                     JDOMetaData.JDOFlagsFieldSig)));
1267
1268                // insert code
1269
insn.insert(newInsn);
1270                noteStack(3);
1271            }
1272        }
1273    }
1274
1275//@olsen: disabled feature
1276
/*
1277    private void annotateClone(CodeAttribute codeAttr,
1278                               String superName) {
1279        Insn insn;
1280        for (insn = codeAttr.theCode();
1281             insn != null;
1282             insn = insn.next()) {
1283
1284            // Found the clone method. See if it is the flavor of clone()
1285            // which does a super.clone() call, and if it is, add
1286            // field initializations for the jdoStateManager and jdoFlags
1287            // fields.
1288            if (insn.opcode() == opc_invokespecial) {
1289                InsnConstOp invoke = (InsnConstOp) insn;
1290                ConstMethodRef methRef = (ConstMethodRef) invoke.value();
1291                String methName = methRef.nameAndType().name().asString();
1292                if (methName.equals("clone")) {
1293                    String thisClass = ca.className();
1294
1295//@olsen: disabled feature
1296///
1297                    // The following change to the method ref is a
1298                    // workaround for the Sun JIT. If there is a
1299                    // derived class whose clone() method calls
1300                    // super.clone() where the super class's clone()
1301                    // was constructed by osjcfp,
1302                    // the compiler will generate code which
1303                    // calls java.lang.Object.clone() instead of the
1304                    // base class's clone (since that's all it can
1305                    // see at compile time). It also sets
1306                    // (correctly) the ACC_SUPER bit. Unfortunately,
1307                    // the JDK JIT will not call the inserted clone
1308                    // method, but instead calls the
1309                    // java.lang.Object.clone() method. The hackery
1310                    // below modifies the invokespecial super.clone()
1311                    // call to instead use the osjcfp supplied clone().
1312                    // It should be removed if/when the JIT
1313                    // is fixed. -cwl 6/27/97
1314
1315                    ClassControl cc =
1316                        env.findClass(superName).findMethodClass(
1317                            "clone", "()Ljava/lang/Object;");
1318                    if (cc != null &&
1319                        !cc.className().equals(methRef.className().asString())) {
1320                        env.message("Changing " + thisClass + ".clone() to call " +
1321                                    cc.className() + ".clone() instead of " +
1322                                    methRef.className().asString() + ".clone()");
1323                        ConstMethodRef newMethRef =
1324                            pool.addMethodRef(cc.className(),
1325                                              "clone",
1326                                              "()Ljava/lang/Object;");
1327                        invoke.setValue(newMethRef);
1328                    }
1329///
1330
1331//@olsen: disabled feature
1332///
1333                    boolean needCheckcast = false;
1334                    Insn checkCastInsn = insn.next();
1335                    if (checkCastInsn.opcode() != opc_checkcast)
1336                        needCheckcast = true;
1337                    else {
1338                        ConstClass target =
1339                            (ConstClass) ((InsnConstOp) checkCastInsn).value();
1340                        ClassControl targetCC = env.findClass(target.asString());
1341                        if (targetCC != null && !targetCC.inherits(thisClass))
1342                            needCheckcast = true;
1343                        else
1344                            insn = checkCastInsn;
1345                    }
1346
1347                    boolean checkStack = false;
1348                    if (ca.getNeedsJDOStateManagerMethods()) {
1349                        Insn newInsn = Insn.create(opc_dup);
1350                        if (needCheckcast)
1351                            newInsn.append(Insn.create(opc_checkcast,
1352                                                       pool.addClass(thisClass)));
1353                        newInsn.append(Insn.create(opc_aconst_null));
1354                        newInsn.append(Insn.create(
1355                            opc_putfield,
1356                            pool.addFieldRef(thisClass,
1357                                             ca.getRefMember(),
1358                                             JDOStateManagerSig)));
1359                        insn.insert(newInsn);
1360                        checkStack = true;
1361                    }
1362
1363                    if (ca.getNeedsJDOFlagsMethods()) {
1364                        Insn newInsn = Insn.create(opc_dup);
1365                        if (needCheckcast)
1366                            newInsn.append(Insn.create(opc_checkcast,
1367                                                       pool.addClass(thisClass)));
1368                        newInsn.append(Insn.create(opc_iconst_0));
1369                        newInsn.append(Insn.create(opc_putfield,
1370                                                   pool.addFieldRef(thisClass,
1371                                                                    ca.getFlagsMember(),
1372                                                                    "B")));
1373
1374                        insn.insert(newInsn);
1375                        checkStack = true;
1376                    }
1377
1378                    if (checkStack)
1379                        noteStack(2);
1380///
1381                }
1382            }
1383        }
1384    }
1385*/

1386
1387// ---------------------------------------------------------------------------
1388

1389    /**
1390     * For a non-static method of a class which implements PersistenceCapable,
1391     * convert the object to a transient object by setting the stateManager
1392     * to null and the object flags to 0. It is assumed that
1393     * the ObjectTable will have already been cleaned up by the
1394     * garbage collector.
1395     */

1396//@olsen: disabled feature
1397
/*
1398    private void makeThisTransient(CodeAttribute codeAttr) {
1399
1400        Insn insn = codeAttr.theCode();
1401        while (insn.opcode() == Insn.opc_target)
1402            insn = insn.next();
1403
1404        // Set the statemanager to null
1405        Insn annotation = Insn.create(opc_aload_0);
1406        annotation.append(Insn.create(opc_aconst_null));
1407        ConstInterfaceMethodRef methRef =
1408            pool.addInterfaceMethodRef(JDOPersistenceCapablePath,
1409                                       "jdoSetStateManager",
1410                                       "(Lcom/sun/forte4j/persistence/internal/StateManager;)V");
1411        annotation.append(new InsnInterfaceInvoke(methRef, 2));
1412
1413        // Set the object flags to null
1414        annotation.append(Insn.create(opc_aload_0));
1415        annotation.append(Insn.create(opc_iconst_0));
1416        methRef = pool.addInterfaceMethodRef(
1417            JDOPersistenceCapablePath,
1418            "jdoSetFlags",
1419            "(B)V");
1420        annotation.append(new InsnInterfaceInvoke(methRef, 2));
1421
1422        insn.prev().insert(annotation);
1423
1424        if (codeAttr.stackUsed() < 2)
1425            codeAttr.setStackUsed(2);
1426    }
1427*/

1428
1429// ---------------------------------------------------------------------------
1430

1431    /**
1432     * Generate annotations if needed for the instruction.
1433     */

1434    private Insn insnAnnotation(final Insn insn) {
1435        // The note list should be sorted in order of decreasing arg depth
1436

1437        int initialSingleRegs = 0;
1438
1439//@olsen: ensured to use single note only (as instantiated)
1440
/*
1441        for (InsnNote note = getNoteList(insn);
1442             note != null;
1443             note = note.next()) { ... }
1444*/

1445        InsnNote note = getNoteList(insn);
1446        if (note == null)
1447            return insn;
1448
1449        //@olsen: ensured to use single note only (as instantiated)
1450
affirm(insn == note.insn);
1451        affirm((note.next() == null),
1452               "Number of annotation notes for instruction > 1.");//NOI18N
1453

1454        //@olsen: not needed to ensure: note.dirtyThis() && !method.isStatic()
1455
final boolean fetch = (note.fetchPersistent() || note.fetchThis());
1456        final boolean dirty = (note.dirtyPersistent() || note.dirtyThis());
1457        //@olsen: added consistency check
1458
affirm((fetch ^ dirty),
1459               "Inconsistent fetch/dirty flags.");//NOI18N
1460

1461        //@olsen: added checks
1462
final boolean dfgField = note.dfgFieldAccess();
1463        final boolean pkField = note.pkFieldAccess();
1464
1465        //@olsen: added println() for debugging
1466
if (false) {
1467            final String JavaDoc targetClassName = note.targetClassName;
1468            final String JavaDoc targetFieldName = note.targetFieldName;
1469            //final String targetPCRootClass = note.targetPCRootClass;
1470

1471            System.out.println(" build annotation: "//NOI18N
1472
+ targetClassName
1473                               + "." + targetFieldName + " : "//NOI18N
1474
+ (pkField ? "pk," : "!pk,")//NOI18N
1475
+ (dfgField ? "dfg," : "!dfg,")//NOI18N
1476
+ (fetch ? "fetch " : "dirty ")//NOI18N
1477
+ (note.fetchPersistent()
1478                                  ? "persistent" : "this")//NOI18N
1479
+ ";");//NOI18N
1480
}
1481
1482        //@olsen: improved control flow
1483
//@olsen: 4385427: do not enhance PK read access at all
1484
if (pkField && fetch) {
1485            return insn;
1486        }
1487
1488        //@olsen: enhance for mediated access
1489
//@olsen: enhance PK write as mediated access
1490
//@olsen: added: mediated getfield/putfield insn annotation
1491
if (pkField || !dfgField) {
1492            //insn.prev().insert(Insn.create(opc_nop));
1493
//@olsen: 4429769: drop putfield instruction on mediated write
1494
// access; isolate the get/putfield instruction to allow
1495
// to now be inserted by buildAccessAnnotation() itself
1496
final Insn prev = insn.prev();
1497            insn.remove();
1498
1499            //@olsen: changed not to return null
1500
final AnnotationFragment frag1 = buildAccessAnnotation(note);
1501            affirm(frag1, "Illegal annotation of PK or non-dfg field.");//NOI18N
1502

1503            //@olsen: 4429769, replace current instruction with fragment
1504
//insn.prev().insert(frag1.annotation);
1505
//noteStack(frag1.stackRequired - note.arg());
1506
//return insn;
1507
final Insn last = prev.insert(frag1.annotation);
1508            noteStack(frag1.stackRequired - note.arg());
1509            return last;
1510        }
1511
1512        // do basic annotation
1513
//@olsen: enhance for non-mediated access
1514
final AnnotationFragment frag0 = buildBasicAnnotation(note);
1515        //@olsen: changed not to return null
1516
affirm(frag0, "Illegal annotation of dfg field.");//NOI18N
1517
//if (frag0 != null) {
1518
{
1519            // Attempt to find an instruction where the argument is known
1520
// to be on the top of stack
1521
StackState state
1522                = new StackState(note.arg(), note.sig(), insn.prev());
1523            minimizeStack(state);
1524
1525            if (false) {
1526                System.out.println(" state.argDepth = "//NOI18N
1527
+ state.argDepth);
1528                System.out.print(" state.insn = ");//NOI18N
1529
state.insn.printInsn(System.out);
1530                System.out.print(" insn = ");//NOI18N
1531
insn.printInsn(System.out);
1532            }
1533
1534            // generate the necessary instructions
1535
Insn annotation = null;
1536            if (state.argDepth == 0) {
1537                // The value is on top of the stack - the dup in the basic
1538
// annotation fragment will suffice
1539
annotation = frag0.annotation;
1540                noteStack(frag0.stackRequired);
1541            } else if (state.argDepth == 1) {
1542                // The value on top of the stack is one deep. Because the
1543
// operand of interest is also a single word value we can
1544
// simply execute a swap operation to get access to the
1545
// operand on top of the stack
1546
annotation = Insn.create(opc_swap);
1547                annotation.append(frag0.annotation);
1548                annotation.append(Insn.create(opc_swap));
1549
1550                // reduce the code fragment's stack requirements by
1551
// the amount that minimizeStack reduced the stack depth,
1552
// since that is the context in which the code fragment
1553
// will run.
1554
noteStack(frag0.stackRequired - (note.arg()-1));
1555            } else {
1556                // The value is hidden by 2 or more stack operands. Move
1557
// the obscuring values into temporaries to get access to
1558
// the value - put them back when done
1559
Stack JavaDoc stackTypes = state.stackTypes;
1560                int depth = state.argDepth;
1561                int elem = stackTypes.size()-1;
1562
1563                int singleRegs = initialSingleRegs;
1564                int doubleRegs = 0;
1565                int regnums[] = new int[depth];
1566                int regtotal = 0;
1567
1568                // Now, move values into temp registers
1569
while (depth > 0) {
1570                    int elemType =
1571                        ((Integer JavaDoc)stackTypes.elementAt(elem--)).intValue();
1572                    int elemSize = Descriptor.elementSize(elemType);
1573                    depth -= elemSize;
1574                    int reg = ((elemSize == 1)
1575                               ? tmpReg(singleRegs++)
1576                               : tmpReg2(doubleRegs++));
1577                    regnums[regtotal++] = reg;
1578
1579                    Insn store = InsnUtils.store(elemType, reg, pool);
1580                    if (annotation == null)
1581                        annotation = store;
1582                    else
1583                        annotation.append(store);
1584                }
1585                affirm((depth >= 0),
1586                       "Stack underflow while computing save registers");//NOI18N
1587

1588                annotation.append(frag0.annotation);
1589
1590                while (regtotal > 0)
1591                    annotation.append(InsnUtils.load(
1592                        ((Integer JavaDoc)stackTypes.elementAt(++elem)).intValue(),
1593                        regnums[--regtotal], pool));
1594
1595                noteStack(frag0.stackRequired - note.arg());
1596            }
1597
1598            state.insn.insert(annotation);
1599        }
1600
1601        return insn;
1602    }
1603
1604    //@olsen: added method for direct annotation of put/getfield
1605
//@olsen: must not return null
1606
private AnnotationFragment buildAccessAnnotation(final InsnNote note) {
1607        final int requiredStack;
1608        final Insn annotation;
1609
1610        final String JavaDoc targetClassName = note.targetClassName;
1611        final String JavaDoc targetFieldName = note.targetFieldName;
1612        final String JavaDoc targetPCRootClass = note.targetPCRootClass;
1613
1614        //@olsen: not needed to ensure: note.dirtyThis() && !method.isStatic()
1615
final boolean fetch = (note.fetchPersistent() || note.fetchThis());
1616        final boolean dirty = (note.dirtyPersistent() || note.dirtyThis());
1617        //@olsen: added consistency check
1618
affirm((fetch ^ dirty),
1619               "Inconsistent fetch/dirty flags.");//NOI18N
1620

1621        //@olsen: added println() for debugging
1622
if (false) {
1623            final boolean dfgField = note.dfgFieldAccess();
1624            final boolean pkField = note.pkFieldAccess();
1625
1626            System.out.println(" build access annotation: "//NOI18N
1627
+ targetClassName
1628                               + "." + targetFieldName + " : "//NOI18N
1629
+ (pkField ? "pk," : "!pk,")//NOI18N
1630
+ (dfgField ? "dfg," : "!dfg,")//NOI18N
1631
+ (fetch ? "fetch " : "dirty ")//NOI18N
1632
+ (note.fetchPersistent()
1633                                  ? "persistent" : "this")//NOI18N
1634
+ ";");//NOI18N
1635
}
1636
1637        final int argSize = note.arg();
1638        final String JavaDoc fieldSig = note.sig();
1639        final int fieldType = Descriptor.elementType(fieldSig);
1640        final int fieldIndex = note.targetFieldIndex;
1641        if (false) {
1642            System.out.println(" argSize = " + argSize);//NOI18N
1643
System.out.println(" fieldSig = " + fieldSig);//NOI18N
1644
System.out.println(" fieldType = " + fieldType);//NOI18N
1645
System.out.println(" fieldIndex = " + fieldIndex);//NOI18N
1646
}
1647
1648        if (fetch) {
1649            // get jdoStateManager
1650
Insn insn = annotation = Insn.create(opc_dup);
1651            insn = insn.append(
1652                Insn.create(opc_getfield,
1653                            pool.addFieldRef(
1654                                targetPCRootClass,
1655                                JDOMetaData.JDOStateManagerFieldName,
1656                                JDOMetaData.JDOStateManagerFieldSig)));
1657
1658            // test jdoStateManager
1659
// load/dirty field if nonnull
1660
InsnTarget fetchDirty = new InsnTarget();
1661            InsnTarget afterFetchDirty = new InsnTarget();
1662            insn = insn.append(Insn.create(opc_dup));
1663            insn = insn.append(
1664                Insn.create(opc_ifnonnull, fetchDirty));
1665
1666            // pop jdoStateManager and skip loading/dirtying
1667
insn = insn.append(Insn.create(opc_pop));
1668            insn = insn.append(
1669                Insn.create(opc_goto, afterFetchDirty));
1670
1671            // invoke StateManager's fetch method
1672
insn = insn.append(fetchDirty);
1673
1674            // push field's unique index onto stack (1st arg)
1675
insn = insn.append(InsnUtils.integerConstant(fieldIndex, pool));
1676
1677            // call stateManager's void prepareGetField(int fieldID) method
1678
requiredStack = 2;
1679            insn = insn.append(
1680                new InsnInterfaceInvoke(
1681                    pool.addInterfaceMethodRef(
1682                        JDOMetaData.JDOStateManagerPath,
1683                        "prepareGetField",//NOI18N
1684
"(I)V"),//NOI18N
1685
requiredStack));
1686
1687            insn = insn.append(afterFetchDirty);
1688            insn = insn.append(note.insn);
1689        } else {
1690            //affirm(dirty);
1691
int singleRegs = 0;
1692            int doubleRegs = 0;
1693
1694            // move current value into temp registers
1695
affirm(argSize > 0);
1696            final int reg = ((argSize == 1)
1697                             ? tmpReg(singleRegs++)
1698                             : tmpReg2(doubleRegs++));
1699            Insn insn = annotation = InsnUtils.store(fieldType, reg, pool);
1700
1701            // get jdoStateManager
1702
insn = insn.append(Insn.create(opc_dup));
1703            insn = insn.append(
1704                Insn.create(opc_getfield,
1705                            pool.addFieldRef(
1706                                targetPCRootClass,
1707                                JDOMetaData.JDOStateManagerFieldName,
1708                                JDOMetaData.JDOStateManagerFieldSig)));
1709
1710            // test jdoStateManager
1711
// load/dirty field if nonnull
1712
InsnTarget fetchDirty = new InsnTarget();
1713            InsnTarget afterFetchDirty = new InsnTarget();
1714            insn = insn.append(Insn.create(opc_dup));
1715            insn = insn.append(
1716                Insn.create(opc_ifnonnull, fetchDirty));
1717
1718            // pop jdoStateManager and skip loading/dirtying
1719
insn = insn.append(Insn.create(opc_pop));
1720            // restore value from registers
1721
affirm(argSize > 0);
1722            insn = insn.append(InsnUtils.load(fieldType, reg, pool));
1723            //@olsen: 4429769, insert the original putfield instruction here
1724
insn = insn.append(note.insn);
1725            insn = insn.append(
1726                Insn.create(opc_goto, afterFetchDirty));
1727
1728            // invoke StateManager's load method
1729
insn = insn.append(fetchDirty);
1730
1731            // push field's unique index onto stack (1st arg)
1732
insn = insn.append(InsnUtils.integerConstant(fieldIndex, pool));
1733
1734            // restore value from registers (2nd arg)
1735
affirm(argSize > 0);
1736            insn = insn.append(InsnUtils.load(fieldType, reg, pool));
1737
1738            // call stateManager's set<Type>Field(index, value) method
1739
switch(fieldType) {
1740            case T_BOOLEAN:
1741                //boolean setBooleanField(int fieldNumber, boolean value);
1742
requiredStack = 3;
1743                insn = insn.append(
1744                    new InsnInterfaceInvoke(
1745                        pool.addInterfaceMethodRef(
1746                            JDOMetaData.JDOStateManagerPath,
1747                            "setBooleanField",//NOI18N
1748
"(IB)B"),//NOI18N
1749
requiredStack));
1750                //@olsen: 4429769, disregard object and setField's return value
1751
insn = insn.append(Insn.create(opc_pop2));
1752                break;
1753            case T_CHAR:
1754                //char setCharField(int fieldNumber, char 3);
1755
requiredStack = 3;
1756                insn = insn.append(
1757                    new InsnInterfaceInvoke(
1758                        pool.addInterfaceMethodRef(
1759                            JDOMetaData.JDOStateManagerPath,
1760                            "setCharField",//NOI18N
1761
"(IC)C"),//NOI18N
1762
requiredStack));
1763                //@olsen: 4429769, disregard object and setField's return value
1764
insn = insn.append(Insn.create(opc_pop2));
1765                break;
1766            case T_BYTE:
1767                //byte setByteField(int fieldNumber, byte value);
1768
requiredStack = 3;
1769                insn = insn.append(
1770                    new InsnInterfaceInvoke(
1771                        pool.addInterfaceMethodRef(
1772                            JDOMetaData.JDOStateManagerPath,
1773                            "setByteField",//NOI18N
1774
"(IZ)Z"),//NOI18N
1775
requiredStack));
1776                //@olsen: 4429769, disregard object and setField's return value
1777
insn = insn.append(Insn.create(opc_pop2));
1778                break;
1779            case T_SHORT:
1780                //short setShortField(int fieldNumber, short value);
1781
requiredStack = 3;
1782                insn = insn.append(
1783                    new InsnInterfaceInvoke(
1784                        pool.addInterfaceMethodRef(
1785                            JDOMetaData.JDOStateManagerPath,
1786                            "setShortField",//NOI18N
1787
"(IS)S"),//NOI18N
1788
requiredStack));
1789                //@olsen: 4429769, disregard object and setField's return value
1790
insn = insn.append(Insn.create(opc_pop2));
1791                break;
1792            case T_INT:
1793                //int setIntField(int fieldNumber, int value);
1794
requiredStack = 3;
1795                insn = insn.append(
1796                    new InsnInterfaceInvoke(
1797                        pool.addInterfaceMethodRef(
1798                            JDOMetaData.JDOStateManagerPath,
1799                            "setIntField",//NOI18N
1800
"(II)I"),//NOI18N
1801
requiredStack));
1802                //@olsen: 4429769, disregard object and setField's return value
1803
insn = insn.append(Insn.create(opc_pop2));
1804                break;
1805            case T_LONG:
1806                //long setLongField(int fieldNumber, long value);
1807
requiredStack = 4;
1808                insn = insn.append(
1809                    new InsnInterfaceInvoke(
1810                        pool.addInterfaceMethodRef(
1811                            JDOMetaData.JDOStateManagerPath,
1812                            "setLongField",//NOI18N
1813
"(IJ)J"),//NOI18N
1814
requiredStack));
1815                //@olsen: 4429769, disregard object and setField's return value
1816
insn = insn.append(Insn.create(opc_pop2));
1817                insn = insn.append(Insn.create(opc_pop));
1818                break;
1819            case T_FLOAT:
1820                //float setFloatField(int fieldNumber, float value);
1821
requiredStack = 3;
1822                insn = insn.append(
1823                    new InsnInterfaceInvoke(
1824                        pool.addInterfaceMethodRef(
1825                            JDOMetaData.JDOStateManagerPath,
1826                            "setFloatField",//NOI18N
1827
"(IF)F"),//NOI18N
1828
requiredStack));
1829                //@olsen: 4429769, disregard object and setField's return value
1830
insn = insn.append(Insn.create(opc_pop2));
1831                break;
1832            case T_DOUBLE:
1833                //double setDoubleField(int fieldNumber, double value);
1834
requiredStack = 4;
1835                insn = insn.append(
1836                    new InsnInterfaceInvoke(
1837                        pool.addInterfaceMethodRef(
1838                            JDOMetaData.JDOStateManagerPath,
1839                            "setDoubleField",//NOI18N
1840
"(ID)D"),//NOI18N
1841
requiredStack));
1842                //@olsen: 4429769, disregard object and setField's return value
1843
insn = insn.append(Insn.create(opc_pop2));
1844                insn = insn.append(Insn.create(opc_pop));
1845                break;
1846            case TC_OBJECT:
1847            case TC_INTERFACE:
1848                //Object setObjectField(int fieldNumber, Object value);
1849
requiredStack = 3;
1850                insn = insn.append(
1851                    new InsnInterfaceInvoke(
1852                        pool.addInterfaceMethodRef(
1853                            JDOMetaData.JDOStateManagerPath,
1854                            "setObjectField",//NOI18N
1855
"(ILjava/lang/Object;)Ljava/lang/Object;"),//NOI18N
1856
requiredStack));
1857
1858                //@olsen: 4429769, no need to downcast anymore
1859
/*
1860                // add a down-cast to the field's type
1861                affirm((fieldSig.charAt(0) == 'L'
1862                        && fieldSig.charAt(fieldSig.length() - 1) == ';'),
1863                       "Inconsistent field signature");//NOI18N
1864                final String fieldTypeClassName
1865                    = fieldSig.substring(1, fieldSig.length() - 1);
1866                final ConstClass fieldTypeConstClass
1867                    = pool.addClass(fieldTypeClassName);
1868                insn = insn.append(
1869                    Insn.create(opc_checkcast, fieldTypeConstClass));
1870*/

1871                //@olsen: 4429769, disregard object and setField's return value
1872
insn = insn.append(Insn.create(opc_pop2));
1873                break;
1874            default:
1875                throw new InternalError JavaDoc("Unexpected field type");//NOI18N
1876
}
1877
1878            insn = insn.append(afterFetchDirty);
1879        }
1880
1881        //@olsen: added println() for debugging
1882
if (false) {
1883            System.out.println(" built annotation, "//NOI18N
1884
+ "required stack = "//NOI18N
1885
+ requiredStack);
1886        }
1887
1888        return new AnnotationFragment(annotation, requiredStack);
1889    }
1890
1891    /**
1892     * Assuming that an object reference is on the top of stack,
1893     * generate an instruction sequence to perform the annotation
1894     * indicated by the note.
1895     */

1896    //@olsen: must not return null
1897
private AnnotationFragment buildBasicAnnotation(InsnNote note) {
1898        int requiredStack = 2;
1899        Insn basicAnnotation = null;
1900
1901        //@olsen: changed to use JDOMetaData
1902
final String JavaDoc targetClassName = note.targetClassName;
1903        final String JavaDoc targetFieldName = note.targetFieldName;
1904        final String JavaDoc targetPCRootClass = note.targetPCRootClass;
1905
1906        //@olsen: not needed to ensure: note.dirtyThis() && !method.isStatic()
1907
final boolean fetch = (note.fetchPersistent() || note.fetchThis());
1908        final boolean dirty = (note.dirtyPersistent() || note.dirtyThis());
1909        //@olsen: added consistency check
1910
affirm((fetch ^ dirty),
1911               "Inconsistent fetch/dirty flags.");//NOI18N
1912

1913        //@olsen: added println() for debugging
1914
if (false) {
1915            final boolean dfgField = note.dfgFieldAccess();
1916            final boolean pkField = note.pkFieldAccess();
1917
1918            System.out.println(" build basic annotation: "//NOI18N
1919
+ targetClassName
1920                               + "." + targetFieldName + " : "//NOI18N
1921
+ (pkField ? "pk," : "!pk,")//NOI18N
1922
+ (dfgField ? "dfg," : "!dfg,")//NOI18N
1923
+ (fetch ? "fetch " : "dirty ")//NOI18N
1924
+ (note.fetchPersistent()
1925                                  ? "persistent" : "this")//NOI18N
1926
+ ";");//NOI18N
1927
}
1928
1929        //@olsen: changed code for annotation
1930
{
1931            Insn insn = null;
1932
1933            //requiredStack = 2;
1934

1935            // get jdoFlags
1936
basicAnnotation = insn = Insn.create(opc_dup);
1937            insn = insn.append(
1938                Insn.create(opc_getfield,
1939                            pool.addFieldRef(
1940                                targetPCRootClass,
1941                                JDOMetaData.JDOFlagsFieldName,
1942                                JDOMetaData.JDOFlagsFieldSig)));
1943
1944            // test jdoFlags
1945
// skip loading for read if <= 0 / for update if == 0
1946
InsnTarget afterFetchDirty = new InsnTarget();
1947            insn = insn.append(
1948                Insn.create((fetch ? opc_ifle : opc_ifeq),
1949                            afterFetchDirty));
1950
1951            // get jdoStateManager
1952
insn = insn.append(Insn.create(opc_dup));
1953            insn = insn.append(
1954                Insn.create(opc_getfield,
1955                            pool.addFieldRef(
1956                                targetPCRootClass,
1957                                JDOMetaData.JDOStateManagerFieldName,
1958                                JDOMetaData.JDOStateManagerFieldSig)));
1959
1960            // invoke StateManager's load method
1961
insn = insn.append(
1962                new InsnInterfaceInvoke(
1963                    pool.addInterfaceMethodRef(
1964                        JDOMetaData.JDOStateManagerPath,
1965                        (fetch ? "loadForRead" : "loadForUpdate"),//NOI18N
1966
"()V"),//NOI18N
1967
1));
1968
1969            insn = insn.append(afterFetchDirty);
1970        }
1971
1972        //@olsen: added println() for debugging
1973
if (false) {
1974            System.out.println(" built annotation, "//NOI18N
1975
+ "required stack = "//NOI18N
1976
+ requiredStack);
1977        }
1978
1979        return new AnnotationFragment(basicAnnotation, requiredStack);
1980    }
1981
1982    /**
1983     * Assuming that an object reference is on the top of stack,
1984     * generate an instruction sequence to perform the annotation
1985     * indicated by the note.
1986     */

1987//@olsen: disabled feature
1988
/*
1989    private AnnotationFragment buildBasicAnnotation(InsnNote note) {
1990        Insn annotation = null; // used?
1991
1992        int requiredStack = 2;
1993        Insn basicAnnotation = null;
1994//@olsen: disabled feature
1995///
1996        ConstMethodRef methRef = null;
1997        InsnTarget afterFetchDirty = null;
1998        Insn flagsCheckAnnotation = null;
1999///
2000
2001//@olsen: disabled feature
2002///
2003        ClassAction targetCA = note.targetClassAction();
2004///
2005
2006//@olsen: disabled feature
2007///
2008        // we may need to save the argument in a register for later use
2009        Insn regStore = null;
2010        if (note.getArgReg() >= 0) {
2011            regStore = Insn.create(opc_dup);
2012            regStore.append(InsnUtils.aStore(note.getArgReg(), pool));
2013        }
2014///
2015
2016///
2017        if (methRef != null) {
2018            if (flagsCheckAnnotation == null) {
2019                basicAnnotation = Insn.create(opc_dup);
2020                basicAnnotation.append(Insn.create(opc_invokestatic, methRef));
2021            } else {
2022                basicAnnotation = flagsCheckAnnotation;
2023                basicAnnotation.append(Insn.create(opc_dup));
2024                basicAnnotation.append(Insn.create(opc_invokestatic, methRef));
2025                basicAnnotation.append(afterFetchDirty);
2026            }
2027        }
2028///
2029
2030//@olsen: disabled feature
2031///
2032        if (note.fetchPersistent() ||
2033            (note.fetchThis() && thisIsPersistent())) {
2034            methRef
2035                = pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "fetch",
2036                                    "(" + JDOMetaData.JDOPersistenceCapableSig + ")V");
2037            if (targetCA != null) {
2038                targetCA.ensureFlagsMemberValid();
2039
2040                if (targetCA.getFlagsMember() != null) {
2041                    ClassControl flagsCC = targetCA.getFlagsMemberClassControl();
2042
2043                    flagsCheckAnnotation = Insn.create(opc_dup);
2044                    //@olsen: changed to use JDOMetaData
2045                    flagsCheckAnnotation.append(
2046                        Insn.create(opc_getfield,
2047                                    pool.addFieldRef(
2048                                        targetPCRootClass,
2049                                        JDOMetaData.JDOFlagsFieldName,
2050                                        JDOMetaData.JDOFlagsFieldSig)));
2051                    flagsCheckAnnotation.append(
2052                        Insn.create(opc_getfield,
2053                                    pool.addFieldRef(flagsCC.className(),
2054                                                     targetCA.getFlagsMember(),
2055                                                     "B")));
2056                    afterFetchDirty = new InsnTarget();
2057                    //@olsen: skip loading for read if <= 0
2058                    flagsCheckAnnotation.append(
2059                        Insn.create(opc_ifle,
2060                                    afterFetchDirty));
2061                }
2062            }
2063        } else if (note.dirtyPersistent() ||
2064                   (note.dirtyThis() && thisIsPersistent())) {
2065            methRef
2066                = pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "dirty",
2067                                    "(" + JDOMetaData.JDOPersistenceCapableSig + ")V");
2068            if (targetCA != null) {
2069                targetCA.ensureFlagsMemberValid();
2070
2071                if (targetCA.getFlagsMember() != null) {
2072                    ClassControl flagsCC = targetCA.getFlagsMemberClassControl();
2073                    flagsCheckAnnotation = Insn.create(opc_dup);
2074                    //@olsen: changed to use JDOMetaData
2075                    flagsCheckAnnotation.append(
2076                        Insn.create(opc_getfield,
2077                                    pool.addFieldRef(
2078                                        targetPCRootClass,
2079                                        JDOMetaData.JDOFlagsFieldName,
2080                                        JDOMetaData.JDOFlagsFieldSig)));
2081                    flagsCheckAnnotation.append(
2082                        Insn.create(opc_getfield,
2083                                    pool.addFieldRef(flagsCC.className(),
2084                                                     targetCA.getFlagsMember(),
2085                                                     "B")));
2086                    afterFetchDirty = new InsnTarget();
2087                    flagsCheckAnnotation.append(Insn.create(opc_iconst_2));
2088                    flagsCheckAnnotation.append(Insn.create(opc_iand));
2089                    flagsCheckAnnotation.append(
2090                        Insn.create(opc_ifeq,
2091                                    afterFetchDirty));
2092                    // One more word is needed here for the constant
2093                    requiredStack = 2;
2094                }
2095            }
2096        } else if (note.fetchArray()) {
2097            String fetchSig =
2098                arrayFetchSignature(env.doArrayElementFetch()
2099                                    ? note.arrayElementType() : 0);
2100            methRef = pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "fetch", fetchSig);
2101        } else if (note.fetchObject()) {
2102            methRef = pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "fetch",
2103                                        "(Ljava/lang/Object;)V");
2104        } else if (note.dirtyArray()) {
2105            methRef = pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "dirty",
2106                                        "(Ljava/lang/Object;)V");
2107        } else if (note.dirtyObject()) {
2108            methRef = pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "dirty",
2109                                        "(Ljava/lang/Object;)V");
2110        }
2111
2112        if (methRef != null) {
2113            if (flagsCheckAnnotation == null) {
2114                basicAnnotation = Insn.create(opc_dup);
2115                basicAnnotation.append(Insn.create(opc_invokestatic, methRef));
2116            } else {
2117                basicAnnotation = flagsCheckAnnotation;
2118                basicAnnotation.append(Insn.create(opc_dup));
2119                basicAnnotation.append(Insn.create(opc_invokestatic, methRef));
2120                basicAnnotation.append(afterFetchDirty);
2121            }
2122
2123            boolean cacheResult = false;
2124
2125            if (env.doArrayOptimization() &&
2126                (note.fetchArray() || note.dirtyArray()) &&
2127                note.inLoop())
2128                cacheResult = true;
2129
2130            if (cacheResult || note.checkNull()) {
2131                // Since this method appears to create a loop of some sort,
2132                // add a cache to remember what array has been fetched
2133                int cacheSlot = 0;
2134                InsnTarget skipTo = new InsnTarget();
2135
2136                // This generally requires at least two words of stack
2137                if (cacheResult)
2138                    cacheSlot = newCacheSlot();
2139
2140                Insn skipAnnotation = Insn.create(opc_dup);
2141                if (note.checkNull()) {
2142                    // skip cache-check/fetch if null
2143                    skipAnnotation.append(Insn.create(opc_ifnull, skipTo));
2144
2145                    if (cacheResult)
2146                        // we used the dup'd result so dup again
2147                        skipAnnotation.append(Insn.create(opc_dup));
2148                }
2149
2150                if (cacheResult) {
2151                    skipAnnotation.append(InsnUtils.aLoad(cacheSlot, pool));
2152                    skipAnnotation.append(Insn.create(opc_if_acmpeq, skipTo));
2153                }
2154
2155                skipAnnotation.append(basicAnnotation);
2156
2157                if (cacheResult) {
2158                    skipAnnotation.append(Insn.create(opc_dup));
2159                    skipAnnotation.append(InsnUtils.aStore(cacheSlot, pool));
2160                }
2161
2162                if (requiredStack < 2)
2163                    requiredStack = 2;
2164
2165                skipAnnotation.append(skipTo);
2166                basicAnnotation = skipAnnotation;
2167            }
2168        }
2169///
2170
2171//@olsen: disabled feature
2172///
2173        // Put the unconditional store-arg-to-register annotation at the
2174        // front if non-null
2175        if (regStore != null) {
2176            regStore.append(basicAnnotation);
2177            basicAnnotation = regStore;
2178        }
2179///
2180
2181        if (basicAnnotation != null)
2182            return new AnnotationFragment(basicAnnotation, requiredStack);
2183
2184        return null;
2185    }
2186*/

2187
2188    /**
2189     * Compute the method signature for a array fetch() method call based
2190     * on the type of array element (as defined in AnnotationConstants
2191     */

2192//@olsen: disabled feature
2193
/*
2194    String arrayFetchSignature(int arrayElementType) {
2195        switch (arrayElementType) {
2196        case ArrayTypeBoolean:
2197            return "([Z)V";
2198        case ArrayTypeByte:
2199            return "([B)V";
2200        case ArrayTypeChar:
2201            return "([C)V";
2202        case ArrayTypeShort:
2203            return "([S)V";
2204        case ArrayTypeInt:
2205            return "([I)V";
2206        case ArrayTypeLong:
2207            return "([J)V";
2208        case ArrayTypeFloat:
2209            return "([F)V";
2210        case ArrayTypeDouble:
2211            return "([D)V";
2212        case ArrayTypeObject:
2213            return "([Ljava/lang/Object;)V";
2214        }
2215        // No special matching type - just use the default signature.
2216        return "(Ljava/lang/Object;)V";
2217    }
2218*/

2219
2220    /**
2221     * Allocate a two word temporary register
2222     * @param idx the index of the temporary register to return. If the
2223     * specified temporary hasn't been allocated, allocated it now.
2224     */

2225    private int tmpReg2(int idx) {
2226        if (tmpDoubleRegisters == null)
2227            tmpDoubleRegisters = new Vector JavaDoc(3);
2228
2229        // allocated as many 2 register pairs as necessary in order to
2230
// make idx be a valid index
2231
while (tmpDoubleRegisters.size() <= idx) {
2232            final CodeAttribute codeAttr = method.codeAttribute();
2233            final int reg = codeAttr.localsUsed();
2234            tmpDoubleRegisters.addElement(new Integer JavaDoc(reg));
2235            codeAttr.setLocalsUsed(reg+2);
2236        }
2237
2238        return ((Integer JavaDoc)tmpDoubleRegisters.elementAt(idx)).intValue();
2239    }
2240
2241    /**
2242     * Allocate a one word temporary register
2243     * @param idx the index of the temporary register to return. If the
2244     * specified temporary hasn't been allocated, allocated it now.
2245     */

2246    private int tmpReg(int idx) {
2247        if (tmpRegisters == null)
2248            tmpRegisters = new Vector JavaDoc(3);
2249
2250        // allocate as many registers as necessary in order to
2251
// make idx be a valid index
2252
while (tmpRegisters.size() <= idx) {
2253            final CodeAttribute codeAttr = method.codeAttribute();
2254            final int reg = codeAttr.localsUsed();
2255            tmpRegisters.addElement(new Integer JavaDoc(reg));
2256            codeAttr.setLocalsUsed(reg+1);
2257        }
2258        return ((Integer JavaDoc)tmpRegisters.elementAt(idx)).intValue();
2259    }
2260
2261    /**
2262     * Allocate an object fetch/store cache slot
2263     */

2264//@olsen: disabled feature
2265
/*
2266    private int newCacheSlot() {
2267        CodeAttribute codeAttr = method.codeAttribute();
2268        int slot = codeAttr.localsUsed();
2269        codeAttr.setLocalsUsed(slot+1);
2270        if (caches == null)
2271            caches = new Vector(3);
2272        caches.addElement(new Integer(slot));
2273        return slot;
2274    }
2275*/

2276
2277    /**
2278     * Note the following amount of stack used by a single annotation.
2279     */

2280    private void noteStack(int stk) {
2281        if (stk > annotationStack)
2282            annotationStack = (short)stk;
2283    }
2284
2285    /**
2286     * Is this a non-static method of a persistence-capable class?
2287     */

2288//@olsen: disabled feature
2289
/*
2290    private boolean thisIsPersistent() {
2291        return (ca.persistCapable() &&
2292                !method.isStatic());
2293    }
2294*/

2295
2296// ---------------------------------------------------------------------------
2297

2298    /**
2299     * Attempt to locate the instruction which deposits to the top of stack
2300     * the 1 word stack argument to currInsn which is argDepth deep on the
2301     * stack (top of stack == 0).
2302     * If unable to determine this with confidence, return null.
2303     *
2304     * Note that this method will not look back past a target.
2305     * Also, the operations performed by the dup2, dup_x1, dup_x2, dup2_x1,
2306     * dup2_x2 instructions are currently not understood by this method so
2307     * we don't attempt to chain back through these instructions.
2308     */

2309    private Insn findArgDepositer(Insn currInsn, int argDepth) {
2310        Insn depositer = null;
2311        for (Insn i = currInsn.prev(); argDepth >= 0; i = i.prev()) {
2312            // At control flow branch/merge points, abort the search for the
2313
// target operand.
2314
if (i.branches() ||
2315                ((i instanceof InsnTarget) && ((InsnTarget)i).isBranchTarget()))
2316                break;
2317
2318            int nArgs = i.nStackArgs();
2319            int nResults = i.nStackResults();
2320
2321            if (argDepth - nResults < 0) {
2322                // This instruction does deposit the value
2323
// For now, don't return depositers other than opc_dup which
2324
// deposit more than one value. These are the
2325
// long/doubleinstructions (which can't be depositing a one
2326
// word value) and the dupX variants
2327
if (nResults > 1 && i.opcode() != opc_dup)
2328                    break;
2329                depositer = i;
2330
2331                // consider special cases which may cause us to look further
2332
switch (i.opcode()) {
2333                case opc_dup:
2334                    if (argDepth == 0)
2335                        // keep going to find the real depositer at a greater depth
2336
argDepth++;
2337                    break;
2338                case opc_checkcast:
2339                    // keep going to find the real depositer
2340
break;
2341                default:
2342                    return i;
2343                }
2344            }
2345
2346            argDepth += (nArgs - nResults);
2347        }
2348
2349        return depositer;
2350    }
2351
2352    /**
2353     * Assume that after the execution of state.insn there is a word on
2354     * the stack which is state.argDepth words deep.
2355     * Scan backwards through the instruction sequence, attempting to
2356     * locate an instruction after which the argument is at a minimal
2357     * depth w.r.t. the top of stack. Update the state to indicate
2358     * progress.
2359     * Note that this method will not look back past a target.
2360     */

2361    private void minimizeStack(StackState state) {
2362        Insn i = state.insn;
2363        int argDepth = state.argDepth;
2364
2365        Stack JavaDoc argTypesStack = new Stack JavaDoc();
2366        Stack JavaDoc resultTypesStack = new Stack JavaDoc();
2367        Stack JavaDoc stackTypes = new Stack JavaDoc();
2368        copyStack(state.stackTypes, stackTypes);
2369
2370        for (; argDepth > 0; i = i.prev()) {
2371            // At control flow branch/merge points, abort the search for the
2372
// target operand. The caller will have to make do with the best
2373
// stack state computed thus far.
2374
if (i.branches() ||
2375                ((i instanceof InsnTarget)
2376                 && ((InsnTarget)i).isBranchTarget()))
2377                break;
2378
2379            int nArgs = i.nStackArgs();
2380            int nResults = i.nStackResults();
2381            String JavaDoc argTypes = i.argTypes();
2382            String JavaDoc resultTypes = i.resultTypes();
2383
2384            argDepth -= nResults;
2385            // If the target argument was placed there by an instruction which
2386
// deposited multiple results (one of the dup type instructions)
2387
// then we don't have the smarts to figure out where it came from
2388
// so just quit looking
2389
if (argDepth < 0)
2390                break;
2391            argDepth += nArgs;
2392
2393            if (i.opcode() == opc_swap) {
2394                Object JavaDoc x = stackTypes.pop();
2395                Object JavaDoc y = stackTypes.pop();
2396                stackTypes.push(x);
2397                stackTypes.push(y);
2398            } else {
2399                // Make sure the arg types and result types stacks are empty
2400
while (!argTypesStack.empty()) argTypesStack.pop();
2401                while (!resultTypesStack.empty()) resultTypesStack.pop();
2402
2403                Descriptor.computeStackTypes(argTypes, argTypesStack);
2404                Descriptor.computeStackTypes(resultTypes, resultTypesStack);
2405
2406                int expectWords = 0;
2407                while (!resultTypesStack.empty())
2408                    expectWords += Descriptor.elementSize(
2409                        ((Integer JavaDoc) resultTypesStack.pop()).intValue());
2410
2411                while (expectWords > 0)
2412                    expectWords -= Descriptor.elementSize(
2413                        ((Integer JavaDoc) stackTypes.pop()).intValue());
2414
2415                if (expectWords < 0) {
2416                    // perhaps we ought to signal an exception, but returning
2417
// will keep things going just fine.
2418
return;
2419                }
2420
2421                transferStackArgs(argTypesStack, stackTypes);
2422            }
2423
2424            if (argDepth >= 0 && argDepth < state.argDepth &&
2425                knownTypes(stackTypes, argDepth)) {
2426                state.argDepth = argDepth;
2427                state.insn = i.prev();
2428                copyStack(stackTypes, state.stackTypes);
2429            }
2430        }
2431    }
2432
2433    /* Take all stack elements in fromStack and push them onto toStack
2434     * such that they are in the same relative stack positions */

2435    private final void transferStackArgs(Stack JavaDoc fromStack, Stack JavaDoc toStack) {
2436        if (!fromStack.empty()) {
2437            Object JavaDoc o = fromStack.pop();
2438            transferStackArgs(fromStack, toStack);
2439            toStack.push(o);
2440        }
2441    }
2442
2443    /* Make toStack look just like fromStack */
2444    private final void copyStack(Stack JavaDoc fromStack, Stack JavaDoc toStack) {
2445        while (!toStack.empty())
2446            toStack.pop();
2447
2448        // take advantage of Stack's inheritance from Vector
2449
for (int i=0; i<fromStack.size(); i++)
2450            toStack.addElement(fromStack.elementAt(i));
2451    }
2452
2453    /* Check that the top nWords worth of types on stack are well defined */
2454    private final boolean knownTypes(Stack JavaDoc stack, int nWords) {
2455        // take advantage of Stack's inheritance from Vector
2456
for (int i=stack.size()-1; i>= 0 && nWords > 0; i--) {
2457            int words = 0;
2458            switch (((Integer JavaDoc)stack.elementAt(i)).intValue()) {
2459            case T_UNKNOWN:
2460            case T_WORD:
2461            case T_TWOWORD:
2462                return false;
2463
2464            case T_BOOLEAN:
2465            case T_CHAR:
2466            case T_FLOAT:
2467            case T_BYTE:
2468            case T_SHORT:
2469            case T_INT:
2470            case TC_OBJECT:
2471            case TC_INTERFACE:
2472            case TC_STRING:
2473                words = 1;
2474
2475            case T_DOUBLE:
2476            case T_LONG:
2477                words = 2;
2478
2479            default:
2480                break;
2481            }
2482            nWords -= words;
2483        }
2484        return true;
2485    }
2486
2487// ---------------------------------------------------------------------------
2488

2489    /**
2490     * Add a list of notes to the note list.
2491     */

2492    //@olsen: made final
2493
private final void addNoteList(InsnNote note) {
2494        insnNotes.put(note.insn, note);
2495    }
2496
2497    /**
2498     * Find the note list for the specified instruction.
2499     */

2500    //@olsen: made final
2501
private final InsnNote getNoteList(Insn insn) {
2502        return (InsnNote)insnNotes.get(insn);
2503    }
2504}
2505
2506// ---------------------------------------------------------------------------
2507

2508/**
2509 * Class loop is a simple class to represent a possible looping construct
2510 * within a method.
2511 */

2512//@olsen: disabled feature
2513
/*
2514class Loop {
2515    int loopStart; // instruction offset - inclusive
2516    int loopEnd; // instruction offset - inclusive
2517
2518    Loop(int lStart, int lEnd) {
2519        loopStart = lStart;
2520        loopEnd = lEnd;
2521    }
2522*/

2523
2524    /**
2525     * Scan the instructions looking for backward branches which suggests a
2526     * loop structure. If any are found, return a Loop object which
2527     * represents the largest possible loop.
2528     */

2529//@olsen: disabled feature
2530
/*
2531    static Loop checkLoops(Insn code) {
2532        // Use 999999 to represent an impossibly large instruction offset
2533        // The current VM design limits methods to 64k of instructions
2534        int loopStart = 999999;
2535        int loopEnd = 0;
2536
2537        for (Insn i = code; i != null; i = i.next()) {
2538            if (i instanceof InsnTargetOp) {
2539                InsnTarget targ = ((InsnTargetOp) i).target();
2540                if (targ.offset() < i.offset()) {
2541                    // a backward branch
2542                    if (targ.offset() < loopStart)
2543                        loopStart = targ.offset();
2544                    if (i.offset() > loopEnd)
2545                        loopEnd = i.offset();
2546                }
2547            }
2548        }
2549
2550        if (loopStart < loopEnd)
2551            return new Loop(loopStart, loopEnd);
2552        return null;
2553    }
2554*/

2555
2556    /**
2557     * Is the instruction contained within the loop?
2558     * Note that the instruction must have a valid offset for this
2559     * to answer correctly.
2560     */

2561//@olsen: disabled feature
2562
/*
2563    boolean contains(Insn i) {
2564        return i.offset() >= loopStart && i.offset() <= loopEnd;
2565    }
2566}
2567*/

2568
2569// ---------------------------------------------------------------------------
2570

2571/**
2572 * A structure to record what annotation requirements are implied
2573 * by a particular VM instruction.
2574 */

2575class InsnNote
2576    extends Support
2577    implements AnnotationConstants {
2578    //@olsen: made final
2579
final Insn insn;
2580    int insnFlags;
2581    final int argWord;
2582//@olsen: disabled feature
2583
/*
2584    int argReg = -1;
2585*/

2586    final String JavaDoc stackSig;
2587
2588    //@olsen: added fields
2589
final String JavaDoc targetClassName;
2590    final String JavaDoc targetFieldName;
2591    final int targetFieldIndex;
2592    final String JavaDoc targetPCRootClass;
2593//@olsen: disabled feature
2594
/*
2595    final ClassAction targetClassAction;
2596*/

2597
2598    /**
2599     * Return the next instruction note in this instruction sequence.
2600     * Most instructions need only a single note, but subtypes may need
2601     * to be chained, and should re-implement next().
2602     */

2603    InsnNote next() {
2604        return null;
2605    }
2606
2607    /**
2608     * Return a descriptor for the current stack state. This descriptor
2609     * is a sequence of VM element type descriptors in decreasing stack
2610     * depth order. That is, the element on the top of stack is the last
2611     * element in the descriptor signature. This descriptor is only
2612     * guaranteed to represent the objects between the instruction stack
2613     * operand (which is offset arg()) deep on the stack and the top of
2614     * stack at the time insn is to be executed. It may however contain
2615     * additional descriptor elements.
2616     */

2617     final String JavaDoc sig() {
2618        return stackSig;
2619    }
2620
2621//@olsen: disabled feature
2622
/*
2623    final ClassAction targetClassAction() {
2624        return targetClassAction;
2625    }
2626*/

2627
2628    /**
2629     * Return the offset from the top of the stack of the argument
2630     */

2631    final int arg() {
2632        return argWord;
2633    }
2634
2635    final boolean fetchThis() {
2636        return (insnFlags & FetchThis) != 0;
2637    }
2638
2639//@olsen: disabled feature
2640
/*
2641    final void dontFetchThis() {
2642        insnFlags &= ~FetchThis;
2643    }
2644*/

2645
2646    final boolean dirtyThis() {
2647        return (insnFlags & DirtyThis) != 0;
2648    }
2649
2650//@olsen: disabled feature
2651
/*
2652    final void dontDirtyThis() {
2653        insnFlags &= ~DirtyThis;
2654    }
2655*/

2656
2657//@olsen: disabled feature
2658
/*
2659    final boolean unconditional() {
2660        return (insnFlags & Unconditional) != 0;
2661    }
2662*/

2663
2664//@olsen: disabled feature / not used anymore
2665
/*
2666    final boolean fetchObject() {
2667        return (insnFlags & FetchObject) != 0;
2668    }
2669
2670    final boolean dirtyObject() {
2671        return (insnFlags & DirtyObject) != 0;
2672    }
2673*/

2674
2675    final boolean fetchPersistent() {
2676        return (insnFlags & FetchPersistent) != 0;
2677    }
2678
2679    final boolean dirtyPersistent() {
2680        return (insnFlags & DirtyPersistent) != 0;
2681    }
2682
2683    //@olsen: added method
2684
final boolean dfgFieldAccess() {
2685        return (insnFlags & DFGField) != 0;
2686    }
2687
2688    //@olsen: added method
2689
final boolean pkFieldAccess() {
2690        return (insnFlags & PKField) != 0;
2691    }
2692
2693//@olsen: disabled feature
2694
/*
2695    final boolean fetchArray() {
2696        return (insnFlags & FetchArray) != 0;
2697    }
2698
2699    final boolean dirtyArray() {
2700        return (insnFlags & DirtyArray) != 0;
2701    }
2702
2703    final int arrayElementType() {
2704        return insnFlags & ArrayTypeMask;
2705    }
2706
2707    final boolean inLoop() {
2708        return (insnFlags & InLoop) != 0;
2709    }
2710
2711    final boolean checkNull() {
2712        return (insnFlags & CheckNull) != 0;
2713    }
2714*/

2715
2716    /* If getArgReg returns < 0, the argReg is not set */
2717//@olsen: disabled feature
2718
/*
2719    final int getArgReg() {
2720        return argReg;
2721    }
2722
2723    final void setArgReg(int reg) {
2724        argReg = reg;
2725    }
2726*/

2727
2728    /**
2729     * Construct an instruction note.
2730     * @param argWord must be the depth of the word on the stack in
2731     * word units
2732     * @param stackSig a stack descriptor for the stack - see
2733     * the doc for sig().
2734     */

2735    InsnNote(Insn i, int flags, int argWord,
2736             String JavaDoc stackSig,
2737             String JavaDoc targetClassName,
2738             String JavaDoc targetFieldName,
2739             int targetFieldIndex,
2740             String JavaDoc targetPCRootClass) {
2741//@olsen: disabled feature
2742
/*
2743       InsnNote(Insn i, int flags, int argWord,
2744             String stackSig, ClassAction targetClassAction) {
2745*/

2746        insn = i;
2747        insnFlags = flags;
2748        this.stackSig = stackSig;
2749        this.argWord = argWord;
2750//@olsen: disabled feature
2751
/*
2752        this.targetClassAction = targetClassAction;
2753*/

2754        this.targetClassName = targetClassName;
2755        this.targetFieldName = targetFieldName;
2756        this.targetFieldIndex = targetFieldIndex;
2757        this.targetPCRootClass = targetPCRootClass;
2758
2759        //@olsen: added consistency check
2760
affirm(!(insn == null
2761                 || argWord < 0
2762                 || targetClassName == null
2763                 || targetFieldName == null
2764                 || targetFieldIndex < 0
2765                 || targetPCRootClass == null),
2766               "Inconsistent instruction annotation note.");//NOI18N
2767
}
2768}
2769
2770/**
2771 * A specialized form of instruction note for method invocation arguments.
2772 * The only thing that this adds is a link element to allow multiple notes
2773 * to apply to an instruction.
2774 */

2775//@olsen: disabled feature
2776
/*
2777class InsnArgNote extends InsnNote {
2778    InsnArgNote nextNote;
2779
2780    InsnNote next() {
2781        return nextNote;
2782    }
2783
2784    InsnArgNote(Insn i, int flags, int argWord, String stackSig) {
2785        super(i, flags, argWord, stackSig, null, null);
2786    }
2787}
2788*/

2789
2790// ---------------------------------------------------------------------------
2791

2792/**
2793 * StackState is really just a simple association of instruction
2794 * and the depth of some stack operand on the operand stack.
2795 */

2796class StackState implements VMConstants {
2797    /* number of words deep that the target word is */
2798    int argDepth;
2799
2800    /* Stack of types */
2801    Stack JavaDoc stackTypes;
2802
2803    /* the instruction after which, the word is argDepth deep */
2804    Insn insn;
2805
2806    StackState(int depth, String JavaDoc stackSig, Insn i) {
2807        stackTypes = new Stack JavaDoc();
2808        Descriptor.computeStackTypes(stackSig, stackTypes);
2809        argDepth = depth;
2810        insn = i;
2811    }
2812}
2813
2814/**
2815 * AnnotationFragment is really just a simple association of instruction
2816 * and the number of words of stack used during the execution of the
2817 * fragment.
2818 */

2819class AnnotationFragment {
2820    Insn annotation;
2821    int stackRequired;
2822
2823    AnnotationFragment(Insn i, int stack) {
2824        annotation = i;
2825        stackRequired = stack;
2826    }
2827}
2828
2829// ---------------------------------------------------------------------------
2830

2831
Popular Tags