KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > core > translators > WrappeeTranslator_BCEL


1 /*
2   Copyright (C) 2002-2003 Fabrice Legond-Aubry, Renaud Pawlak,
3   Lionel Seinturier, Laurent Martelli
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU Lesser General Public License as
7   published by the Free Software Foundation; either version 2 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18   USA */

19
20 package org.objectweb.jac.core.translators;
21
22 import java.lang.reflect.Modifier JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Vector JavaDoc;
31 import org.apache.bcel.Constants;
32 import org.apache.bcel.Repository;
33 import org.apache.bcel.classfile.*;
34 import org.apache.bcel.generic.*;
35 import org.apache.bcel.generic.BranchInstruction;
36 import org.apache.log4j.Logger;
37 import org.objectweb.jac.core.JacLoader;
38 import org.objectweb.jac.core.JacPropLoader;
39 import org.objectweb.jac.core.WrappeeTranslator;
40 import org.objectweb.jac.core.rtti.InvokeInfo;
41 import org.objectweb.jac.core.rtti.LoadtimeRTTI;
42 import org.objectweb.jac.util.ExtArrays;
43 import org.objectweb.jac.util.Stack;
44
45 public class WrappeeTranslator_BCEL implements WrappeeTranslator {
46     static Logger logger = Logger.getLogger("translator");
47     static Logger loggerRtti = Logger.getLogger("rtti.detect");
48     static Logger loggerBytecode = Logger.getLogger("translator.bytecode");
49
50     LoadtimeRTTI rtti;
51
52     /**
53      * Translator initializator. */

54
55     public WrappeeTranslator_BCEL(LoadtimeRTTI rtti) {
56         this.rtti = rtti;
57     }
58
59     private static final String JavaDoc nextWrapper_signature =
60     "(Lorg/objectweb/jac/core/Interaction;)Ljava/lang/Object;";
61
62     private static final String JavaDoc newInteraction_signature =
63     "(Lorg/objectweb/jac/core/WrappingChain;Lorg/objectweb/jac/core/Wrappee;"+
64     "Lorg/objectweb/jac/core/rtti/AbstractMethodItem;"+
65     "[Ljava/lang/Object;)V";
66
67     private static final String JavaDoc getWrappingChain_signature =
68     "(Lorg/objectweb/jac/core/Wrappee;Lorg/objectweb/jac/core/rtti/AbstractMethodItem;)Lorg/objectweb/jac/core/WrappingChain;";
69
70     private String JavaDoc primitiveTypeName(Type t)
71     {
72         if (t==Type.BOOLEAN)
73             return "boolean";
74         if (t==Type.BYTE)
75             return "byte";
76         if (t==Type.INT)
77             return "int";
78         if (t==Type.LONG)
79             return "long";
80         if (t==Type.SHORT)
81             return "short";
82         if (t==Type.FLOAT)
83             return "float";
84         if (t==Type.CHAR)
85             return "char";
86         if (t==Type.DOUBLE)
87             return "double";
88         return null;
89     }
90
91     private String JavaDoc primitiveTypeAsObject(Type t)
92     {
93         if (t==Type.BOOLEAN)
94             return "java.lang.Boolean";
95         if (t==Type.BYTE)
96             return "java.lang.Byte";
97         if (t==Type.INT)
98             return "java.lang.Integer";
99         if (t==Type.LONG)
100             return "java.lang.Long";
101         if (t==Type.SHORT)
102             return "java.lang.Short";
103         if (t==Type.FLOAT)
104             return "java.lang.Float";
105         if (t==Type.CHAR)
106             return "java.lang.Character";
107         if (t==Type.DOUBLE)
108             return "java.lang.Double";
109         return null;
110     }
111    
112     private void generateStubMethod(ClassGen classGen,
113                                     ConstantPoolGen constPool,
114                                     Method method, String JavaDoc gSNewName,
115                                     int staticFieldIndex,
116                                     List JavaDoc staticFieldIndexes,
117                                     int wrappingChainIndex,
118                                     List JavaDoc wrappingChainIndexes,
119                                     InstructionList callSuper)
120     {
121         logger.debug("Generating stub method "+
122                      method.getName()+method.getSignature());
123         InstructionList il = new InstructionList();
124         InstructionFactory ifactory = new InstructionFactory(classGen);
125         //create the stub method
126

127         Type[] argumentTypes = Type.getArgumentTypes(method.getSignature());
128         Type returnType = Type.getReturnType(method.getSignature());
129         MethodGen stubMethod =
130             new MethodGen(
131                 method.getAccessFlags(),
132                 returnType,argumentTypes,
133                 null,
134                 method.getName(),classGen.getClassName(),
135                 il,constPool);
136         int lineNumber = 0;
137         // generate the super call when its a constructor
138
if (stubMethod.getName().equals("<init>")) {
139             logger.debug("Generating stub method "+
140                          classGen.getClassName()+"."+
141                          method.getName()+method.getSignature());
142             if (callSuper!=null) {
143                 logger.debug(" insert call to super");
144                 il.append(callSuper);
145             } else {
146                 logger.debug(" insert super()");
147                 il.append(new ALOAD(0));
148                 il.append(
149                     ifactory.createInvoke(classGen.getSuperclassName(), "<init>",
150                                           Type.VOID,
151                                           emptyTypeArray,
152                                           Constants.INVOKESPECIAL));
153             }
154             // initialize the wrapping chains
155
for(int i=0;i<wrappingChainIndexes.size();i++) {
156                 if(wrappingChainIndexes.get(i)==null) continue;
157                 il.append(InstructionFactory.createThis());
158                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
159                 il.append(InstructionFactory.createThis());
160                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
161                 il.append(new GETSTATIC(
162                     ((Integer JavaDoc)staticFieldIndexes.get(i)).intValue()));
163                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
164                 il.append(ifactory.createInvoke(
165                     "org.objectweb.jac.core.Wrapping", "getWrappingChain",
166                     Type.getReturnType(getWrappingChain_signature),
167                     Type.getArgumentTypes(getWrappingChain_signature),
168                     Constants.INVOKESTATIC));
169                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
170                 WCIndex chainIndex = (WCIndex)wrappingChainIndexes.get(i);
171                 if (chainIndex.isStatic) {
172                     il.append(new PUTSTATIC(chainIndex.index));
173                 } else {
174                     il.append(new PUTFIELD(chainIndex.index));
175                 }
176                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
177             }
178         }
179
180         ///////////////////////////////////
181
// LOOK AT THIS ! NEED TEST
182
///////////////////////////////////////
183
stubMethod.removeExceptionHandlers();
184
185         // create an Interaction object
186
il.append(ifactory.createNew("org.objectweb.jac.core.Interaction"));
187         stubMethod.addLineNumber(il.getEnd(),il.size()-1);
188         il.append(new DUP());
189         stubMethod.addLineNumber(il.getEnd(),il.size()-1);
190
191         // get the wrapping chain
192
if (method.isStatic()) {
193             il.append(new GETSTATIC(wrappingChainIndex));
194             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
195         } else {
196             il.append(InstructionFactory.createThis());
197             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
198             il.append(new GETFIELD(wrappingChainIndex));
199             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
200         }
201       
202         // push the ref on this object in case of a non-static method on stack
203
if( !stubMethod.isStatic() ) {
204             il.append(InstructionFactory.createThis());
205             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
206         } else {
207             il.append(new ACONST_NULL());
208             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
209         }
210
211         // push the static field containing the AbstractMethodItem on the stack
212
il.append(new GETSTATIC(staticFieldIndex));
213         stubMethod.addLineNumber(il.getEnd(),il.size()-1);
214
215         //create an array of Objects that are the parameters for the
216
//original method
217
if (argumentTypes.length==0) {
218             il.append(
219                 ifactory.createGetStatic(
220                     "org.objectweb.jac.core.Wrapping",
221                     "emptyArray",
222                     Type.getType("[Ljava.lang.Object;")));
223             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
224         } else {
225             il.append(new PUSH(constPool, argumentTypes.length));
226             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
227             //create a array and put its ref on the stack
228
il.append((Instruction)ifactory.createNewArray(Type.OBJECT,(short)1));
229             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
230             int j = (stubMethod.isStatic())?0:1; // index of argument on the stack
231
for (int i=0; i<argumentTypes.length; i++)
232             {
233                 //duplicate the ref on the array to keep it for next operation
234
il.append(InstructionFactory.createDup(1));
235                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
236                 //get the index [in the array] in which we will store the ref
237
il.append(new PUSH(constPool, i));
238                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
239                 // is the parameter an object ?
240
if (!Utils.isPrimitive(argumentTypes[i])) {
241                     //get the ref of the j st parameter of the local function
242
il.append(InstructionFactory.createLoad(Type.OBJECT,j));
243                     stubMethod.addLineNumber(il.getEnd(),il.size()-1);
244                     //effectively store the ref in the array
245
il.append(InstructionFactory.createArrayStore(Type.OBJECT));
246                     stubMethod.addLineNumber(il.getEnd(),il.size()-1);
247                     //increment the counter for the next object
248
j++;
249                 } else {
250                     //create a new object similar to the primitive type
251
String JavaDoc objectType = primitiveTypeAsObject(argumentTypes[i]);
252                     il.append (ifactory.createNew(objectType));
253                     stubMethod.addLineNumber(il.getEnd(),il.size()-1);
254                     //call the constructor of the new object with the primitive value
255
il.append(InstructionFactory.createDup(1));
256                     stubMethod.addLineNumber(il.getEnd(),il.size()-1);
257                     il.append(InstructionFactory.createLoad(argumentTypes[i],j));
258                     stubMethod.addLineNumber(il.getEnd(),il.size()-1);
259                     il.append(ifactory.createInvoke(objectType, "<init>", Type.VOID,
260                                                     new Type[] {argumentTypes[i]},
261                                                     Constants.INVOKESPECIAL));
262                     stubMethod.addLineNumber(il.getEnd(),il.size()-1);
263                     //store the new object in the array
264
il.append(InstructionFactory.createArrayStore(Type.OBJECT));
265                     stubMethod.addLineNumber(il.getEnd(),il.size()-1);
266                     j++;
267                     if (argumentTypes[i]==Type.LONG ||
268                         argumentTypes[i]==Type.DOUBLE)
269                         // long and double take 2 slots on the stack
270
j++;
271                 }
272             
273             }
274         }
275
276         // <init> the Interaction
277
il.append(
278             ifactory.createInvoke(
279                 "org.objectweb.jac.core.Interaction", "<init>",
280                 Type.getReturnType(newInteraction_signature),
281                 Type.getArgumentTypes(newInteraction_signature),
282                 Constants.INVOKESPECIAL));
283         stubMethod.addLineNumber(il.getEnd(),il.size()-1);
284
285         //make invocation of "nextWrapper"
286
if (method.isStatic()||method.getName().equals("<init>")) {
287             il.append(
288                 ifactory.createInvoke(
289                     "org.objectweb.jac.core.Wrapping", "nextWrapper",
290                     Type.getReturnType(nextWrapper_signature),
291                     Type.getArgumentTypes(nextWrapper_signature),
292                     Constants.INVOKESTATIC));
293             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
294         } else {
295             il.append(
296                 ifactory.createInvoke(
297                     "org.objectweb.jac.core.Wrapping", "methodNextWrapper",
298                     Type.getReturnType(nextWrapper_signature),
299                     Type.getArgumentTypes(nextWrapper_signature),
300                     Constants.INVOKESTATIC));
301             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
302         }
303
304         //parse the return value if it is a primitive one
305
if (Utils.isPrimitive(returnType))
306         {
307             //ouch ! the return primitive types are also wrapped.
308
//test the cast for the object returned ....
309
//is this really usefull ?
310

311             il.append(
312                 ifactory.createCheckCast(
313                     (ReferenceType)Type.getReturnType(
314                         "()L"+primitiveTypeAsObject(returnType).replace('.','/')+";")));
315             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
316                 
317             //get the value wrapped in the object
318
il.append(
319                 ifactory.createInvoke(
320                     primitiveTypeAsObject(returnType),
321                     primitiveTypeName(returnType)+"Value",
322                     stubMethod.getReturnType(), emptyTypeArray,
323                     Constants.INVOKEVIRTUAL));
324             stubMethod.addLineNumber(il.getEnd(),il.size()-1);
325         }
326         // else make a simple checkcast (avoid the checkcast on the VOID type)
327
//is this also really useful ?
328
else
329             if (stubMethod.getReturnType()!=Type.VOID) {
330                 il.append (
331                     ifactory.createCheckCast((ReferenceType)returnType));
332                 stubMethod.addLineNumber(il.getEnd(),il.size()-1);
333             }
334         // finally return ! HOURRA !
335
il.append (InstructionFactory.createReturn(returnType));
336         stubMethod.addLineNumber(il.getEnd(),il.size()-1);
337         // compile all this stuff, generate the method
338
stubMethod.setMaxLocals();
339         stubMethod.setMaxStack();
340         //System.out.println ("il=\n"+il);
341
classGen.addMethod(stubMethod.getMethod());
342     }
343
344     /**
345      * Generate a default constructor --which takes no argument-- which
346      * just calls super().
347      *
348      * !!! IT SHOULD ALSO INITIALIZE FIELDS !!!
349      * We could use the "this" method generated by jikes-1.18
350      */

351     private void generateDefaultConstructor(ClassGen classGen)
352     {
353         logger.debug("class "+classGen.getClassName()+
354                   " ==> Generating default constructor");
355         ConstantPoolGen constPool = classGen.getConstantPool();
356         InstructionList instructions = new InstructionList();
357         InstructionFactory ifactory = new InstructionFactory(classGen);
358
359         instructions.append(new ALOAD(0));
360         instructions.append(ifactory.createInvoke(classGen.getSuperclassName(),
361                                                   "<init>",
362                                                   Type.VOID,
363                                                   emptyTypeArray,
364                                                   Constants.INVOKESPECIAL));
365       
366         instructions.append(new RETURN());
367
368         MethodGen constructor = new MethodGen(Modifier.PUBLIC,
369                                               Type.VOID,
370                                               new Type[] {}, new String JavaDoc[] {},
371                                               "<init>", classGen.getClassName(),
372                                               instructions, constPool);
373
374         constructor.setMaxLocals();
375         constructor.setMaxStack();
376         classGen.addMethod(constructor.getMethod());
377     }
378
379     /**
380      * Remove call to super()
381      * Replace collection attributes with the wrappable org.objectweb.jac.lib version
382      *
383      * @param classGen the class of the constructor
384      * @param origConstructor
385      * @param constructor the constructor to translate
386      * @param callSuper store bytecodes that do the call to the super
387      * constructor in it
388      * @param removeSuperCall wether to remove the call to super bytecodes
389      */

390     private void translateConstructor(ClassGen classGen,
391                                       Method origConstructor,
392                                       MethodGen constructor,
393                                       InstructionList callSuper,
394                                       boolean removeSuperCall) {
395         logger.debug("constructor translation of "+
396                      constructor.getName()+constructor.getSignature());
397         InstructionList instructions = constructor.getInstructionList();
398         ConstantPoolGen constPool = classGen.getConstantPool();
399         InstructionFactory ifactory = new InstructionFactory(classGen);
400         instructions.setPositions();
401         int i=0;
402         // Represents the state of the JVM stack
403
// (contains ThisPointer or DontCare)
404
boolean superRemoved = false;
405         VMStack stack = new VMStack(constPool,origConstructor.getCode(),
406                                     constructor.getArgumentTypes().length,false);
407         InstructionHandle first = null;
408         Iterator JavaDoc it = instructions.iterator();
409         while(it.hasNext()) {
410             InstructionHandle ih = (InstructionHandle)it.next();
411             InstructionHandle next = ih.getNext();
412             if (first==null)
413                 first = ih;
414             Instruction instruction = ih.getInstruction();
415             stack.preExecute(ih);
416             if (!superRemoved && !constructor.getName().equals("this")) {
417                 if (callSuper!=null) {
418                     if (instruction instanceof BranchInstruction) {
419                         callSuper.append((BranchInstruction)instruction);
420                     } else {
421                         callSuper.append(instruction);
422                     }
423                 }
424                 // remove call to super <init>
425
if (instruction instanceof INVOKESPECIAL &&
426                     stack.getSubstance((INVOKESPECIAL)instruction)==VMStack.thisPointer)
427                 {
428                     superRemoved = true;
429                     INVOKESPECIAL invoke = (INVOKESPECIAL)instruction;
430                     if (removeSuperCall) {
431                         if (!invoke.getClassName(constPool).equals(classGen.getClassName()))
432                         {
433                             try {
434                                 logger.debug("deleting call to super, callSuper = \n"+callSuper);
435                                 instructions.delete(first,ih);
436                             } catch (TargetLostException e) {
437                                 logger.debug("TargetLostException..., callSuper = \n"+callSuper);
438                                 InstructionHandle[] targets = e.getTargets();
439                                 for(int j=0; j<targets.length; j++) {
440                                     InstructionTargeter[] targeters =
441                                         targets[j].getTargeters();
442                                     for(int k=0; k<targeters.length; k++)
443                                         targeters[k].updateTarget(targets[j], next);
444                                 }
445                             }
446                         } else {
447                             //if(classGen.containsMethod(
448
// invoke.getMethodName(constPool),
449
// invoke.getSignature(constPool)).isPublic())
450
//{
451
// if it calls another constructor of the same class,
452
// replace it with a call to the renamed constructor
453
ih.setInstruction(
454                                 ifactory.createInvoke(
455                                     classGen.getClassName(),
456                                     prefix+classGen.getClassName()
457                                     .substring(classGen.getClassName().lastIndexOf(".")+1),
458                                     Type.VOID,
459                                     invoke.getArgumentTypes(constPool),
460                                     Constants.INVOKEVIRTUAL
461                                 )
462                             );
463                             //}
464
}
465                     }
466                 }
467                 stack.execute(instruction,ih);
468             } else if (JacPropLoader.translateFields(constructor.getClassName())) {
469
470                 // Replace java.util. with org.objectweb.jac.lib.java.util
471
// for collections
472

473                 if (instruction instanceof PUTFIELD &&
474                     stack.peek(1) == VMStack.thisPointer &&
475                     stack.peek() instanceof VMStack.Instance &&
476                     isCollection(((VMStack.Instance)stack.peek()).type) ) {
477                     // this.putfield(...)
478
PUTFIELD putfield = (PUTFIELD)instruction;
479                     if (!classGen.containsField(putfield.getFieldName(constPool)).isTransient()) {
480                         VMStack.Instance collection = (VMStack.Instance)stack.peek();
481                         /*
482                           System.out.println("collection: "+collection.type+"( new="+
483                           collection.newHandle+",init="+
484                           collection.initHandle+")");
485                         */

486                         collection.newHandle.setInstruction(
487                             ifactory.createNew("org.objectweb.jac.lib."+collection.type));
488                         collection.initHandle.setInstruction(
489                             ifactory.createInvoke(
490                                 "org.objectweb.jac.lib."+collection.type,
491                                 "<init>",
492                                 Type.VOID,
493                                 ((INVOKESPECIAL)collection.initHandle.getInstruction()).getArgumentTypes(constPool),
494                                 Constants.INVOKESPECIAL));
495                         logger.debug("Found collection field initialization: "+
496                                   putfield.getFieldName(constPool));
497                     }
498                 } else if (instruction instanceof INVOKESPECIAL) {
499                     INVOKESPECIAL invoke = (INVOKESPECIAL)instruction;
500                     Object JavaDoc substance =
501                         stack.peek(VMStack.getConsumed(invoke,constPool)-1);
502                     if (substance instanceof VMStack.Instance) {
503                         logger.debug("Found collection <init> for "+substance);
504                         ((VMStack.Instance)substance).initHandle = ih;
505                     }
506                 }
507                 stack.execute(instruction,ih);
508             }
509             i++;
510         }
511         logger.debug("callSuper = \n"+callSuper);
512         instructions.setPositions();
513         constructor.setInstructionList(instructions);
514         constructor.removeLineNumbers();
515     }
516
517     /**
518      * Rename the method "xxx" in "_org_xxx".
519      *
520      * <p>If the method is a constructor, it's translated.</p>
521      *
522      * @param classGen the class of the method to rename
523      * @param constPool
524      * @param method the method to rename
525      * @param newProposedName new name for the translated method
526      * @param callSuper store bytecodes that do the call to the super
527      * constructor in this list
528      *
529      * @see #translateConstructor(ClassGen,Method,MethodGen,InstructionList)
530      */

531     private String JavaDoc renameMethod(ClassGen classGen, ConstantPoolGen constPool,
532                                 Method method, String JavaDoc newProposedName,
533                                 InstructionList callSuper)
534     {
535         logger.debug("Rename "+method.getName()+" -> "+newProposedName);
536         // handles constructors specific translations
537
if (method.getName().equals("<init>")) {
538             MethodGen newNamedMethod =
539                 new MethodGen(method, classGen.getClassName(), constPool);
540             newNamedMethod.setName(newProposedName);
541             translateConstructor(classGen,method,newNamedMethod,callSuper,true);
542             //why the hell is all this stuff necessary ?!
543
newNamedMethod.removeLocalVariables();
544             // newNamedMethod.setMaxLocals();
545
// newNamedMethod.setMaxStack();
546
//move the original method into the new "_org_xxx" method
547
classGen.replaceMethod(method, newNamedMethod.getMethod());
548         } else {
549             Method newMethod = new Method(method);
550             newMethod.setNameIndex(constPool.addUtf8(newProposedName));
551             classGen.replaceMethod(method,newMethod);
552         }
553         return newProposedName;
554     }
555
556     /**
557      * Generate RTTI information for a method.
558      *
559      * @param classGen the class of the method
560      * @param constPool the constant pool of the method
561      * @param method the method
562      * @param passive if true, do not perform any translation
563      */

564     Method fillRTTI(ClassGen classGen, ConstantPoolGen constPool, Method method,
565                     boolean passive)
566     {
567         String JavaDoc className = classGen.getClassName();
568         String JavaDoc methodName = method.getName();
569         MethodGen methodGen = new MethodGen(method,className,constPool);
570         Iterator JavaDoc instructions = methodGen.getInstructionList().iterator();
571         String JavaDoc methodSign = null;
572         if (methodName.startsWith(prefix)) {
573             methodName = methodName.substring(prefix.length());
574         }
575         methodSign = className+"."+getMethodFullName(method);
576         VMStack stack = new VMStack(constPool,method.getCode(),
577                                     methodGen.getArgumentTypes().length,method.isStatic());
578         loggerRtti.debug("detecting RTTI for "+methodSign);
579         while (instructions.hasNext()) {
580             InstructionHandle ih=(InstructionHandle)instructions.next();
581             Instruction instruction = ih.getInstruction();
582             loggerBytecode.debug("offset: "+ih.getPosition());
583             stack.preExecute(ih);
584          
585             if (instruction instanceof PUTFIELD &&
586                 stack.peek(1)==VMStack.thisPointer) {
587                 // setters and modifiers
588
PUTFIELD putfield = (PUTFIELD)instruction;
589                 String JavaDoc fieldName = putfield.getFieldName(constPool);
590                 if (!isSystemField(fieldName)) {
591                     if (stack.peek() instanceof VMStack.Argument) {
592                         loggerRtti.debug(" sets field "+fieldName);
593                         rtti.addltSetField(className,methodSign,fieldName);
594                         // TODO: check if the type is translated collection
595
}
596                     loggerRtti.debug(" modifies field "+fieldName);
597                     rtti.addltModifiedField(className,methodSign,fieldName);
598                 }
599             } else if (instruction instanceof PUTSTATIC &&
600                        ((PUTSTATIC)instruction).getClassName(constPool).equals(classGen.getClassName())) {
601                 // static setters and modifiers
602
PUTSTATIC putfield = (PUTSTATIC)instruction;
603                 String JavaDoc fieldName = putfield.getFieldName(constPool);
604                 if (!isSystemField(fieldName)) {
605                     if (stack.peek() instanceof VMStack.Argument) {
606                         loggerRtti.debug(methodSign+" sets static field "+fieldName);
607                         rtti.addltSetField(className,methodSign,fieldName);
608                         // TODO: check if the type is translated collection
609
}
610                     loggerRtti.debug(" modifies static field "+fieldName);
611                     rtti.addltModifiedField(className,methodSign,fieldName);
612                 }
613             } else if (instruction instanceof ReturnInstruction &&
614                        !(instruction instanceof RETURN)) {
615                 if (stack.peek() instanceof VMStack.FieldValue) {
616                     // *the* getter
617
VMStack.FieldValue fieldValue = (VMStack.FieldValue)stack.peek();
618                     if (!isSystemField(fieldValue.field)) {
619                         if (fieldValue.substance==VMStack.thisPointer) {
620                             loggerRtti.debug(" returns field "+fieldValue.field);
621                             rtti.addltReturnedField(className,methodSign,fieldValue.field);
622                         } else {
623                             loggerRtti.debug(" returns "+stack.peek());
624                             rtti.addltReturnedField(className,methodSign,null);
625                             rtti.setltIsGetter(className,methodSign,false);
626                         }
627                     }
628                 } else {
629                     loggerRtti.debug(" returns "+stack.peek());
630                     rtti.setltIsGetter(className,methodSign,false);
631                 }
632             } else if (instruction instanceof GETFIELD &&
633                        stack.peek()==VMStack.thisPointer) {
634                 // getters
635
String JavaDoc fieldName = ((GETFIELD)instruction).getFieldName(constPool);
636                 if (!isSystemField(fieldName)) {
637                     loggerRtti.debug(" accesses field "+fieldName);
638                     rtti.addltAccessedField(className,methodSign,fieldName);
639                 }
640             } else if (instruction instanceof GETSTATIC &&
641                        ((GETSTATIC)instruction).getClassName(constPool).equals(classGen.getClassName())) {
642                 // getters
643
String JavaDoc fieldName = ((GETSTATIC)instruction).getFieldName(constPool);
644                 if (!isSystemField(fieldName)) {
645                     loggerRtti.debug(" accesses static field "+fieldName);
646                     rtti.addltAccessedField(className,methodSign,fieldName);
647                 }
648             } else if ((instruction instanceof INVOKEVIRTUAL ||
649                         instruction instanceof INVOKEINTERFACE) &&
650                        !className.startsWith("org.objectweb.jac.lib.java")) {
651                 // adders and removers
652
InvokeInstruction invoke = (InvokeInstruction)instruction;
653                 String JavaDoc invokedClass = invoke.getClassName(constPool);
654                 String JavaDoc invokedMethodName = invoke.getMethodName(constPool);
655                 int numArgs = invoke.getArgumentTypes(constPool).length;
656                 Object JavaDoc substance = stack.invokedObject(invoke);
657                 loggerBytecode.info("substance="+substance);
658                 if (substance instanceof VMStack.FieldValue) {
659                     VMStack.FieldValue fieldValue = (VMStack.FieldValue)substance;
660                     loggerBytecode.info("detected INVOKE on field "+substance);
661                     ConstantFieldref fieldref =
662                         (ConstantFieldref)constPool.getConstant(fieldValue.index);
663                     ConstantNameAndType nameAndType =
664                         (ConstantNameAndType)constPool.getConstant(
665                             fieldref.getNameAndTypeIndex());
666                     String JavaDoc signature =
667                         nameAndType.getSignature(constPool.getConstantPool());
668