import eclipse 3.1 M4 compiler
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / codegen / CodeStream.java
index 4d7a6ef..343c4e6 100644 (file)
@@ -49,7 +49,9 @@ public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, Bas
        public AbstractMethodDeclaration methodDeclaration;
        public ExceptionLabel[] exceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
        static ExceptionLabel[] noExceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
-       public int exceptionHandlersNumber;
+       public int exceptionHandlersIndex;
+       public int exceptionHandlersCounter;
+       
        public static FieldBinding[] ImplicitThis = new FieldBinding[] {};
        public boolean generateLineNumberAttributes;
        public boolean generateLocalVariableTableAttributes;
@@ -65,11 +67,15 @@ public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, Bas
        public boolean wideMode = false;
        public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0, 0);
        
-public CodeStream(ClassFile classFile) {
-       generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0;
-       generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0;
-       if (generateLineNumberAttributes) {
-               lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
+       // target level to manage different code generation between different target levels
+       private long targetLevel;
+       
+public CodeStream(ClassFile classFile, long targetLevel) {
+       this.targetLevel = targetLevel;
+       this.generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0;
+       this.generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0;
+       if (this.generateLineNumberAttributes) {
+               this.lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
        }
 }
 final public void aaload() {
@@ -248,7 +254,7 @@ public final void anewarray(TypeBinding typeBinding) {
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_anewarray;
-       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+       writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 final public void areturn() {
        if (DEBUG) System.out.println(position + "\t\tareturn"); //$NON-NLS-1$
@@ -482,14 +488,14 @@ final public void castore() {
        bCodeStream[classFileOffset++] = OPC_castore;
 }
 public final void checkcast(TypeBinding typeBinding) {
-       if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding); //$NON-NLS-1$
+       if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding.debugName()); //$NON-NLS-1$
        countLabels = 0;
        if (classFileOffset + 2 >= bCodeStream.length) {
                resizeByteArray();
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_checkcast;
-       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+       writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 final public void d2f() {
        if (DEBUG) System.out.println(position + "\t\td2f"); //$NON-NLS-1$
@@ -1260,80 +1266,85 @@ public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBin
                this.getTYPE(accessedType.id);
                return;
        }
-       endLabel = new Label(this);
-
-       if (syntheticFieldBinding != null) { // non interface case
-               this.getstatic(syntheticFieldBinding);
-               this.dup();
-               this.ifnonnull(endLabel);
-               this.pop();
-       }
-
-       /* Macro for building a class descriptor object... using or not a field cache to store it into...
-       this sequence is responsible for building the actual class descriptor.
-       
-       If the fieldCache is set, then it is supposed to be the body of a synthetic access method
-       factoring the actual descriptor creation out of the invocation site (saving space).
-       If the fieldCache is nil, then we are dumping the bytecode on the invocation site, since
-       we have no way to get a hand on the field cache to do better. */
-
 
-       // Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError
-
-       anyExceptionHandler = new ExceptionLabel(this, BaseTypes.NullBinding /* represents ClassNotFoundException*/);
-       this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
-       this.invokeClassForName();
-
-       /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565
-       if (accessedType == BaseTypes.NullBinding) {
-               this.ldc("java.lang.Object"); //$NON-NLS-1$
-       } else if (accessedType.isArrayType()) {
-               this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.'));
+       if (this.targetLevel >= ClassFileConstants.JDK1_5) {
+               // generation using the new ldc_w bytecode
+               this.ldc(accessedType);
        } else {
-               // we make it an array type (to avoid class initialization)
-               this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$
-       }
-       this.invokeClassForName();
-       if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class
-               this.invokeJavaLangClassGetComponentType();
-       }       
-       */
-       /* We need to protect the runtime code from binary inconsistencies
-       in case the accessedType is missing, the ClassNotFoundException has to be converted
-       into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */
-       anyExceptionHandler.placeEnd();
+               endLabel = new Label(this);
+               if (syntheticFieldBinding != null) { // non interface case
+                       this.getstatic(syntheticFieldBinding);
+                       this.dup();
+                       this.ifnonnull(endLabel);
+                       this.pop();
+               }
 
-       if (syntheticFieldBinding != null) { // non interface case
-               this.dup();
-               this.putstatic(syntheticFieldBinding);
+               /* Macro for building a class descriptor object... using or not a field cache to store it into...
+               this sequence is responsible for building the actual class descriptor.
+               
+               If the fieldCache is set, then it is supposed to be the body of a synthetic access method
+               factoring the actual descriptor creation out of the invocation site (saving space).
+               If the fieldCache is nil, then we are dumping the bytecode on the invocation site, since
+               we have no way to get a hand on the field cache to do better. */
+       
+       
+               // Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError
+       
+               anyExceptionHandler = new ExceptionLabel(this, BaseTypes.NullBinding /* represents ClassNotFoundException*/);
+               this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
+               this.invokeClassForName();
+       
+               /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565
+               if (accessedType == BaseTypes.NullBinding) {
+                       this.ldc("java.lang.Object"); //$NON-NLS-1$
+               } else if (accessedType.isArrayType()) {
+                       this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.'));
+               } else {
+                       // we make it an array type (to avoid class initialization)
+                       this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$
+               }
+               this.invokeClassForName();
+               if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class
+                       this.invokeJavaLangClassGetComponentType();
+               }       
+               */
+               /* We need to protect the runtime code from binary inconsistencies
+               in case the accessedType is missing, the ClassNotFoundException has to be converted
+               into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */
+               anyExceptionHandler.placeEnd();
+       
+               if (syntheticFieldBinding != null) { // non interface case
+                       this.dup();
+                       this.putstatic(syntheticFieldBinding);
+               }
+               this.goto_(endLabel);
+       
+       
+               // Generate the body of the exception handler
+               saveStackSize = stackDepth;
+               stackDepth = 1;
+               /* ClassNotFoundException on stack -- the class literal could be doing more things
+               on the stack, which means that the stack may not be empty at this point in the
+               above code gen. So we save its state and restart it from 1. */
+       
+               anyExceptionHandler.place();
+       
+               // Transform the current exception, and repush and throw a 
+               // NoClassDefFoundError(ClassNotFound.getMessage())
+       
+               this.newNoClassDefFoundError();
+               this.dup_x1();
+               this.swap();
+       
+               // Retrieve the message from the old exception
+               this.invokeThrowableGetMessage();
+       
+               // Send the constructor taking a message string as an argument
+               this.invokeNoClassDefFoundErrorStringConstructor();
+               this.athrow();
+               stackDepth = saveStackSize;
+               endLabel.place();
        }
-       this.goto_(endLabel);
-
-
-       // Generate the body of the exception handler
-       saveStackSize = stackDepth;
-       stackDepth = 1;
-       /* ClassNotFoundException on stack -- the class literal could be doing more things
-       on the stack, which means that the stack may not be empty at this point in the
-       above code gen. So we save its state and restart it from 1. */
-
-       anyExceptionHandler.place();
-
-       // Transform the current exception, and repush and throw a 
-       // NoClassDefFoundError(ClassNotFound.getMessage())
-
-       this.newNoClassDefFoundError();
-       this.dup_x1();
-       this.swap();
-
-       // Retrieve the message from the old exception
-       this.invokeThrowableGetMessage();
-
-       // Send the constructor taking a message string as an argument
-       this.invokeNoClassDefFoundErrorStringConstructor();
-       this.athrow();
-       endLabel.place();
-       stackDepth = saveStackSize;
 }
 /**
  * This method generates the code attribute bytecode
@@ -1346,41 +1357,57 @@ final public void generateCodeAttributeForProblemMethod(String problemMessage) {
        athrow();
 }
 public void generateConstant(Constant constant, int implicitConversionCode) {
-       int targetTypeID = implicitConversionCode >> 4;
-       switch (targetTypeID) {
-               case T_boolean :
-                       generateInlinedValue(constant.booleanValue());
-                       break;
-               case T_char :
-                       generateInlinedValue(constant.charValue());
-                       break;
-               case T_byte :
-                       generateInlinedValue(constant.byteValue());
-                       break;
-               case T_short :
-                       generateInlinedValue(constant.shortValue());
-                       break;
-               case T_int :
-                       generateInlinedValue(constant.intValue());
-                       break;
-               case T_long :
-                       generateInlinedValue(constant.longValue());
-                       break;
-               case T_float :
-                       generateInlinedValue(constant.floatValue());
-                       break;
-               case T_double :
-                       generateInlinedValue(constant.doubleValue());
-                       break;
-               default : //String or Object
-                       ldc(constant.stringValue());
+       int targetTypeID = (implicitConversionCode & IMPLICIT_CONVERSION_MASK) >> 4;
+       if (targetTypeID != 0) {
+               switch (targetTypeID) {
+                       case T_boolean :
+                               generateInlinedValue(constant.booleanValue());
+                               break;
+                       case T_char :
+                               generateInlinedValue(constant.charValue());
+                               break;
+                       case T_byte :
+                               generateInlinedValue(constant.byteValue());
+                               break;
+                       case T_short :
+                               generateInlinedValue(constant.shortValue());
+                               break;
+                       case T_int :
+                               generateInlinedValue(constant.intValue());
+                               break;
+                       case T_long :
+                               generateInlinedValue(constant.longValue());
+                               break;
+                       case T_float :
+                               generateInlinedValue(constant.floatValue());
+                               break;
+                       case T_double :
+                               generateInlinedValue(constant.doubleValue());
+                               break;
+                       case T_JavaLangString :
+                               ldc(constant.stringValue());
+               }
+       } else {
+               ldc(constant.stringValue());
+       }
+       if ((implicitConversionCode & BOXING) != 0) {
+               // need boxing
+               generateBoxingConversion(targetTypeID);
        }
 }
+
 /**
+ * Generates the sequence of instructions which will perform the conversion of the expression
+ * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted).
  * @param implicitConversionCode int
  */
 public void generateImplicitConversion(int implicitConversionCode) {
-       switch (implicitConversionCode) {
+       if ((implicitConversionCode & UNBOXING) != 0) {
+               final int typeId = implicitConversionCode & COMPILE_TYPE_MASK;
+               generateUnboxingConversion(typeId);
+               // unboxing can further involve base type conversions
+       }
+       switch (implicitConversionCode & IMPLICIT_CONVERSION_MASK) {
                case Float2Char :
                        this.f2i();
                        this.i2c();
@@ -1477,6 +1504,11 @@ public void generateImplicitConversion(int implicitConversionCode) {
                case Float2Long :
                        this.f2l();
        }
+       if ((implicitConversionCode & BOXING) != 0) {
+               // need to unbox/box the constant
+               final int typeId = (implicitConversionCode & IMPLICIT_CONVERSION_MASK) >> 4;
+               generateBoxingConversion(typeId);
+       }
 }
 public void generateInlinedValue(byte inlinedValue) {
        switch (inlinedValue) {
@@ -1699,27 +1731,27 @@ public void generateOuterAccess(Object[] mappingSequence, ASTNode invocationSite
  * @param oper1 the first expression
  * @param oper2 the second expression
  */
-public void generateStringAppend(BlockScope blockScope, Expression oper1, Expression oper2) {
+public void generateStringConcatenationAppend(BlockScope blockScope, Expression oper1, Expression oper2) {
        int pc;
        if (oper1 == null) {
                /* Operand is already on the stack, and maybe nil:
                note type1 is always to  java.lang.String here.*/
-               this.newStringBuffer();
+               this.newStringContatenation();
                this.dup_x1();
                this.swap();
                // If argument is reference type, need to transform it 
                // into a string (handles null case)
-               this.invokeStringValueOf(T_Object);
-               this.invokeStringBufferStringConstructor();
+               this.invokeStringValueOf(T_JavaLangObject);
+               this.invokeStringConcatenationStringConstructor();
        } else {
                pc = position;
-               oper1.generateOptimizedStringBufferCreation(blockScope, this, oper1.implicitConversion & 0xF);
+               oper1.generateOptimizedStringConcatenationCreation(blockScope, this, oper1.implicitConversion & COMPILE_TYPE_MASK);
                this.recordPositionsFrom(pc, oper1.sourceStart);
        }
        pc = position;
-       oper2.generateOptimizedStringBuffer(blockScope, this, oper2.implicitConversion & 0xF);
+       oper2.generateOptimizedStringConcatenation(blockScope, this, oper2.implicitConversion & COMPILE_TYPE_MASK);
        this.recordPositionsFrom(pc, oper2.sourceStart);
-       this.invokeStringBufferToString();
+       this.invokeStringConcatenationToString();
 }
 /**
  * Code responsible to generate the suitable code to supply values for the synthetic enclosing
@@ -1795,7 +1827,7 @@ public void generateSyntheticOuterArgumentValues(BlockScope currentScope, Refere
 /**
  * @param accessBinding the access method binding to generate
  */
-public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForConstructorAccess(SyntheticMethodBinding accessBinding) {
 
        initializeMaxLocals(accessBinding);
 
@@ -1804,8 +1836,14 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
        int length = parameters.length;
        int resolvedPosition = 1;
        this.aload_0();
-       if (constructorBinding.declaringClass.isNestedType()) {
-               NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+       // special name&ordinal argument generation for enum constructors
+       TypeBinding declaringClass = constructorBinding.declaringClass;
+       if (declaringClass.erasure().id == T_JavaLangEnum || declaringClass.isEnum()) {
+               this.aload_1(); // pass along name param as name arg
+               this.iload_2(); // pass along ordinal param as ordinal arg
+       }       
+       if (declaringClass.isNestedType()) {
+               NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
                SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticEnclosingInstances();
                for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
                        TypeBinding type;
@@ -1824,8 +1862,8 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
                        resolvedPosition++;
        }
        
-       if (constructorBinding.declaringClass.isNestedType()) {
-               NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+       if (declaringClass.isNestedType()) {
+               NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
                SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
                for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
                        TypeBinding type;
@@ -1839,7 +1877,82 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
        this.invokespecial(constructorBinding);
        this.return_();
 }
-public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding accessBinding) {
+//static X[] values() {
+// X[] values;
+// int length;
+// X[] result;
+// System.arraycopy(values = $VALUES, 0, result = new X[length= values.length], 0, length)
+// return result;
+//}
+public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) {
+       ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
+       FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
+       initializeMaxLocals(methodBinding);
+       TypeBinding enumArray = methodBinding.returnType;
+       
+       this.getstatic(enumValuesSyntheticfield);
+       this.dup();
+       this.astore_0();
+       this.iconst_0();
+       this.aload_0();
+       this.arraylength();
+       this.dup();
+       this.istore_1();
+       this.newArray((ArrayBinding) enumArray);
+       this.dup();
+       this.astore_2();
+       this.iconst_0();
+       this.iload_1();
+       this.invokeSystemArraycopy();
+       this.aload_2();
+       this.areturn();
+}
+//static X valueOf(String name) {
+// X[] values;
+// for (int i = (values = $VALUES).length; --i >= 0;) {
+//              X value;
+//              if (name.equals(value = values[i].name())) return value;
+// }
+// throw new IllegalArgumentException(name);
+//}            
+public void generateSyntheticBodyForEnumValueOf(SyntheticMethodBinding methodBinding) {
+       ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
+       FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
+       initializeMaxLocals(methodBinding);
+       Label loopCond = new Label(this);
+       Label loopStart = new Label(this);
+       Label wrongConstant = new Label(this);
+
+       this.getstatic(enumValuesSyntheticfield);
+       this.dup();
+       this.astore_1();
+       this.arraylength();
+       this.istore_2();
+       this.goto_(loopCond);
+       loopStart.place();
+       this.aload_0();
+       this.aload_1();
+       this.iload_2();
+       this.aaload();
+       this.dup();
+       this.astore_3();
+       this.invokeJavaLangEnumname(this.classFile.referenceBinding);
+       this.invokeStringEquals();
+       this.ifeq(wrongConstant);
+       this.aload_3();
+       this.areturn();
+       wrongConstant.place();
+       loopCond.place();
+       this.iinc(2, -1);               
+       this.iload_2();
+       this.ifge(loopStart);
+       this.newJavaLangIllegalArgumentException();
+       this.dup();
+       this.aload_0();
+       this.invokeJavaLangIllegalArgumentExceptionStringConstructor();
+       this.athrow();
+}
+public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) {
        initializeMaxLocals(accessBinding);
        FieldBinding fieldBinding = accessBinding.targetReadField;
        TypeBinding type;
@@ -1866,7 +1979,7 @@ public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding
        } else
                this.areturn();
 }
-public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForFieldWriteAccess(SyntheticMethodBinding accessBinding) {
        initializeMaxLocals(accessBinding);
        FieldBinding fieldBinding = accessBinding.targetWriteField;
        if (fieldBinding.isStatic()) {
@@ -1879,12 +1992,15 @@ public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBindin
        }
        this.return_();
 }
-public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForMethodAccess(SyntheticMethodBinding accessBinding) {
 
        initializeMaxLocals(accessBinding);
        MethodBinding methodBinding = accessBinding.targetMethod;
        TypeBinding[] parameters = methodBinding.parameters;
        int length = parameters.length;
+       TypeBinding[] arguments = accessBinding.kind == SyntheticMethodBinding.BridgeMethod 
+                                                                                                       ? accessBinding.parameters
+                                                                                                       : null;
        int resolvedPosition;
        if (methodBinding.isStatic())
                resolvedPosition = 0;
@@ -1893,8 +2009,16 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
                resolvedPosition = 1;
        }
        for (int i = 0; i < length; i++) {
-               load(parameters[i], resolvedPosition);
-               if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding))
+           TypeBinding parameter = parameters[i];
+           if (arguments != null) { // for bridge methods
+                   TypeBinding argument = arguments[i];
+                       load(argument, resolvedPosition);
+                       if (argument != parameter) 
+                           checkcast(parameter);
+           } else {
+                       load(parameter, resolvedPosition);
+               }
+               if ((parameter == DoubleBinding) || (parameter == LongBinding))
                        resolvedPosition += 2;
                else
                        resolvedPosition++;
@@ -1906,10 +2030,10 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
                if (methodBinding.isConstructor()
                        || methodBinding.isPrivate()
                        // qualified super "X.super.foo()" targets methods from superclass
-                       || accessBinding.accessType == SyntheticAccessMethodBinding.SuperMethodAccess){
+                       || accessBinding.kind == SyntheticMethodBinding.SuperMethodAccess){
                        this.invokespecial(methodBinding);
                } else {
-                       if (methodBinding.declaringClass.isInterface()){
+                       if ((methodBinding.declaringClass.modifiers & AccInterface) != 0) { // interface or annotation type
                                this.invokeinterface(methodBinding);
                        } else {
                                this.invokevirtual(methodBinding);
@@ -1936,6 +2060,172 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
        else
                this.areturn();
 }
+public void generateBoxingConversion(int unboxedTypeID) {
+       switch (unboxedTypeID) {
+               case T_byte :
+                       // invokestatic: Byte.valueOf(byte)
+                       this.invoke(
+                               OPC_invokestatic,
+                               1, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangByteConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.byteByteSignature); //$NON-NLS-1$
+                       break;
+               case T_short :
+                       // invokestatic: Short.valueOf(short)
+                       this.invoke(
+                               OPC_invokestatic,
+                               1, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangShortConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.shortShortSignature); //$NON-NLS-1$
+                       break;
+               case T_char :
+                       // invokestatic: Character.valueOf(char)
+                       this.invoke(
+                               OPC_invokestatic,
+                               1, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangCharacterConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.charCharacterSignature); //$NON-NLS-1$
+                       break;
+               case T_int :
+                       // invokestatic: Integer.valueOf(int)
+                       this.invoke(
+                               OPC_invokestatic,
+                               1, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangIntegerConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.IntIntegerSignature); //$NON-NLS-1$
+                       break;
+               case T_long :
+                       // invokestatic: Long.valueOf(long)
+                       this.invoke(
+                               OPC_invokestatic,
+                               2, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangLongConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.longLongSignature); //$NON-NLS-1$
+                       break;
+               case T_float :
+                       // invokestatic: Float.valueOf(float)
+                       this.invoke(
+                               OPC_invokestatic,
+                               1, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangFloatConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.floatFloatSignature); //$NON-NLS-1$
+                       break;
+               case T_double :
+                       // invokestatic: Double.valueOf(double)
+                       this.invoke(
+                               OPC_invokestatic,
+                               2, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangDoubleConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.doubleDoubleSignature); //$NON-NLS-1$
+                       break;
+               case T_boolean :
+                       // invokestatic: Boolean.valueOf(boolean)
+                       this.invoke(
+                               OPC_invokestatic,
+                               1, // argCount
+                               1, // return type size
+                               ConstantPool.JavaLangBooleanConstantPoolName,
+                               ConstantPool.ValueOf,
+                               ConstantPool.booleanBooleanSignature); //$NON-NLS-1$
+       }
+}
+public void generateUnboxingConversion(int unboxedTypeID) {
+       switch (unboxedTypeID) {
+               case T_byte :
+                       // invokevirtual: byteValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       1, // return type size
+                                       ConstantPool.JavaLangByteConstantPoolName,
+                                       ConstantPool.BYTEVALUE_BYTE_METHOD_NAME,
+                                       ConstantPool.BYTEVALUE_BYTE_METHOD_SIGNATURE);
+                       break;
+               case T_short :
+                       // invokevirtual: shortValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       1, // return type size
+                                       ConstantPool.JavaLangShortConstantPoolName,
+                                       ConstantPool.SHORTVALUE_SHORT_METHOD_NAME,
+                                       ConstantPool.SHORTVALUE_SHORT_METHOD_SIGNATURE);
+                       break;
+               case T_char :
+                       // invokevirtual: charValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       1, // return type size
+                                       ConstantPool.JavaLangCharacterConstantPoolName,
+                                       ConstantPool.CHARVALUE_CHARACTER_METHOD_NAME,
+                                       ConstantPool.CHARVALUE_CHARACTER_METHOD_SIGNATURE);
+                       break;
+               case T_int :
+                       // invokevirtual: intValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       1, // return type size
+                                       ConstantPool.JavaLangIntegerConstantPoolName,
+                                       ConstantPool.INTVALUE_INTEGER_METHOD_NAME,
+                                       ConstantPool.INTVALUE_INTEGER_METHOD_SIGNATURE);
+                       break;
+               case T_long :
+                       // invokevirtual: longValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       2, // return type size
+                                       ConstantPool.JavaLangLongConstantPoolName,
+                                       ConstantPool.LONGVALUE_LONG_METHOD_NAME,
+                                       ConstantPool.LONGVALUE_LONG_METHOD_SIGNATURE);
+                       break;
+               case T_float :
+                       // invokevirtual: floatValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       1, // return type size
+                                       ConstantPool.JavaLangFloatConstantPoolName,
+                                       ConstantPool.FLOATVALUE_FLOAT_METHOD_NAME,
+                                       ConstantPool.FLOATVALUE_FLOAT_METHOD_SIGNATURE);
+                       break;
+               case T_double :
+                       // invokevirtual: doubleValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       2, // return type size
+                                       ConstantPool.JavaLangDoubleConstantPoolName,
+                                       ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_NAME,
+                                       ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE);
+                       break;
+               case T_boolean :
+                       // invokevirtual: booleanValue()
+                       this.invoke(
+                                       OPC_invokevirtual,
+                                       0, // argCount
+                                       1, // return type size
+                                       ConstantPool.JavaLangBooleanConstantPoolName,
+                                       ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_NAME,
+                                       ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE);
+       }
+}
 final public byte[] getContents() {
        byte[] contents;
        System.arraycopy(bCodeStream, 0, contents = new byte[position], 0, position);
@@ -1943,88 +2233,161 @@ final public byte[] getContents() {
 }
 final public void getfield(FieldBinding fieldBinding) {
        if (DEBUG) System.out.println(position + "\t\tgetfield:"+fieldBinding); //$NON-NLS-1$
-       countLabels = 0;
+       int returnTypeSize = 1;
        if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
-               if (++stackDepth > stackMax)
-                       stackMax = stackDepth;
+               returnTypeSize = 2;
+       }
+       generateFieldAccess(
+                       OPC_getfield,
+                       returnTypeSize,
+                       fieldBinding.declaringClass.constantPoolName(),
+                       fieldBinding.name,
+                       fieldBinding.type.signature());
+}
+private void generateFieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] name, char[] signature) {
+       countLabels = 0;
+       switch(opcode) {
+               case OPC_getfield :
+                       if (returnTypeSize == 2) {
+                               stackDepth++;
+                       }
+                       break;
+               case OPC_getstatic :
+                       if (returnTypeSize == 2) {
+                               stackDepth += 2;
+                       } else {
+                               stackDepth++;
+                       }
+                       break;
+               case OPC_putfield :
+                       if (returnTypeSize == 2) {
+                               stackDepth -= 3;
+                       } else {
+                               stackDepth -= 2;
+                       }
+                       break;
+               case OPC_putstatic :
+                       if (returnTypeSize == 2) {
+                               stackDepth -= 2;
+                       } else {
+                               stackDepth--;
+                       }
+       }
+       if (stackDepth > stackMax) {
+               stackMax = stackDepth;
        }
        if (classFileOffset + 2 >= bCodeStream.length) {
                resizeByteArray();
        }
        position++;
-       bCodeStream[classFileOffset++] = OPC_getfield;
-       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+       bCodeStream[classFileOffset++] = opcode;
+       writeUnsignedShort(constantPool.literalIndexForField(declaringClass, name, signature));
 }
 final public void getstatic(FieldBinding fieldBinding) {
        if (DEBUG) System.out.println(position + "\t\tgetstatic:"+fieldBinding); //$NON-NLS-1$
-       countLabels = 0;
-       if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long))
-               stackDepth += 2;
-       else
-               stackDepth += 1;
-       if (stackDepth > stackMax)
-               stackMax = stackDepth;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       int returnTypeSize = 1;
+       if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+               returnTypeSize = 2;
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_getstatic;
-       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+       generateFieldAccess(
+                       OPC_getstatic,
+                       returnTypeSize,
+                       fieldBinding.declaringClass.constantPoolName(),
+                       fieldBinding.name,
+                       fieldBinding.type.signature());
 }
 public void getTYPE(int baseTypeID) {
        countLabels = 0;
-       if (++stackDepth > stackMax)
-               stackMax = stackDepth;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_getstatic;
        switch (baseTypeID) {
                case T_byte :
                        // getstatic: java.lang.Byte.TYPE                       
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Byte.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangByteTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangByteConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_short :
                        // getstatic: java.lang.Short.TYPE                      
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Short.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangShortTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangShortConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_char :
                        // getstatic: java.lang.Character.TYPE                  
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Character.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangCharacterTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangCharacterConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_int :
                        // getstatic: java.lang.Integer.TYPE                    
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Integer.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangIntegerTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangIntegerConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_long :
                        // getstatic: java.lang.Long.TYPE                       
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Long.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangLongTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangLongConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_float :
                        // getstatic: java.lang.Float.TYPE                      
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Float.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangFloatTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangFloatConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_double :
                        // getstatic: java.lang.Double.TYPE                     
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Double.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangDoubleTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangDoubleConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_boolean :
                        // getstatic: java.lang.Boolean.TYPE                    
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Boolean.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangBooleanTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangBooleanConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
                case T_void :
                        // getstatic: java.lang.Void.TYPE
                        if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Void.TYPE"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangVoidTYPE());
+                       generateFieldAccess(
+                                       OPC_getstatic,
+                                       1,
+                                       ConstantPool.JavaLangVoidConstantPoolName,
+                                       ConstantPool.TYPE,
+                                       ConstantPool.JavaLangClassSignature);
                        break;
        }
 }
@@ -2691,7 +3054,8 @@ public void init(ClassFile targetClassFile) {
                noExceptionHandlers = new ExceptionLabel[length];
        }
        System.arraycopy(noExceptionHandlers, 0, exceptionHandlers, 0, length);
-       exceptionHandlersNumber = 0;
+       exceptionHandlersIndex = 0;
+       exceptionHandlersCounter = 0;
        
        length = labels.length;
        if (noLabels.length < length) {
@@ -2710,41 +3074,50 @@ public void init(ClassFile targetClassFile) {
  */
 public void initializeMaxLocals(MethodBinding methodBinding) {
 
-       maxLocals = (methodBinding == null || methodBinding.isStatic()) ? 0 : 1;
+       if (methodBinding == null) {
+               this.maxLocals = 0;
+               return;
+       }
+       
+       this.maxLocals = methodBinding.isStatic() ? 0 : 1;
+       
+       // take into account enum constructor synthetic name+ordinal
+       if (methodBinding.isConstructor() && methodBinding.declaringClass.isEnum()) {
+               this.maxLocals += 2; // String and int (enum constant name+ordinal)
+       }
+       
        // take into account the synthetic parameters
-       if (methodBinding != null) {
-               if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) {
-                       ReferenceBinding enclosingInstanceTypes[];
-                       if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) {
-                               for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
-                                       maxLocals++; // an enclosingInstanceType can only be a reference binding. It cannot be
-                                       // LongBinding or DoubleBinding
-                               }
-                       }
-                       SyntheticArgumentBinding syntheticArguments[];
-                       if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
-                               for (int i = 0, max = syntheticArguments.length; i < max; i++) {
-                                       TypeBinding argType;
-                                       if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) {
-                                               maxLocals += 2;
-                                       } else {
-                                               maxLocals++;
-                                       }
-                               }
+       if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) {
+               ReferenceBinding enclosingInstanceTypes[];
+               if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) {
+                       for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
+                               this.maxLocals++; // an enclosingInstanceType can only be a reference binding. It cannot be
+                               // LongBinding or DoubleBinding
                        }
                }
-               TypeBinding[] arguments;
-               if ((arguments = methodBinding.parameters) != null) {
-                       for (int i = 0, max = arguments.length; i < max; i++) {
+               SyntheticArgumentBinding syntheticArguments[];
+               if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
+                       for (int i = 0, max = syntheticArguments.length; i < max; i++) {
                                TypeBinding argType;
-                               if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
-                                       maxLocals += 2;
+                               if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) {
+                                       this.maxLocals += 2;
                                } else {
-                                       maxLocals++;
+                                       this.maxLocals++;
                                }
                        }
                }
        }
+       TypeBinding[] arguments;
+       if ((arguments = methodBinding.parameters) != null) {
+               for (int i = 0, max = arguments.length; i < max; i++) {
+                       TypeBinding argType;
+                       if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
+                               this.maxLocals += 2;
+                       } else {
+                               this.maxLocals++;
+                       }
+               }
+       }
 }
 /**
  * This methods searches for an existing entry inside the pcToSourceMap table with a pc equals to @pc.
@@ -2792,45 +3165,53 @@ final public void instance_of(TypeBinding typeBinding) {
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_instanceof;
-       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+       writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 public void invokeClassForName() {
        // invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;
        if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokestatic;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangClassForName());
+       this.invoke(
+               OPC_invokestatic,
+               1, // argCount
+               1, // return type size
+               ConstantPool.JavaLangClassConstantPoolName,
+               ConstantPool.ForName,
+               ConstantPool.ForNameSignature);
 }
-
 public void invokeJavaLangClassDesiredAssertionStatus() {
        // invokevirtual: java.lang.Class.desiredAssertionStatus()Z;
        if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.desiredAssertionStatus()Z;"); //$NON-NLS-1$
-       countLabels = 0;
-       stackDepth--;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangClassDesiredAssertionStatus());
+       this.invoke(
+                       OPC_invokevirtual,
+                       0, // argCount
+                       1, // return type size
+                       ConstantPool.JavaLangClassConstantPoolName,
+                       ConstantPool.DesiredAssertionStatus,
+                       ConstantPool.DesiredAssertionStatusSignature);
 }
 
 public void invokeJavaLangClassGetComponentType() {
        // invokevirtual: java.lang.Class.getComponentType()java.lang.Class;
        if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.getComponentType()java.lang.Class;"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangClassGetComponentType());
+       this.invoke(
+                       OPC_invokevirtual,
+                       0, // argCount
+                       1, // return type size
+                       ConstantPool.JavaLangClassConstantPoolName,
+                       ConstantPool.GetComponentType,
+                       ConstantPool.GetComponentTypeSignature);
+}
+public void invokeEnumOrdinal(char[] enumTypeConstantPoolName) {
+       // invokevirtual: <enumConstantPoolName>.ordinal()
+       if (DEBUG) System.out.println(position + "\t\tinvokevirtual: "+new String(enumTypeConstantPoolName)+".ordinal()"); //$NON-NLS-1$ //$NON-NLS-2$
+       this.invoke(
+                       OPC_invokevirtual,
+                       0, // argCount
+                       1, // return type size
+                       enumTypeConstantPoolName,
+                       ConstantPool.Ordinal,
+                       ConstantPool.OrdinalSignature);
 }
-
 final public void invokeinterface(MethodBinding methodBinding) {
        // initialized to 1 to take into account this  immediately
        if (DEBUG) System.out.println(position + "\t\tinvokeinterface: " + methodBinding); //$NON-NLS-1$
@@ -2868,37 +3249,35 @@ final public void invokeinterface(MethodBinding methodBinding) {
 public void invokeJavaLangErrorConstructor() {
        // invokespecial: java.lang.Error<init>(Ljava.lang.String;)V
        if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.Error<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokespecial;
-       stackDepth -= 2;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangErrorConstructor());
+       this.invoke(
+                       OPC_invokespecial,
+                       1, // argCount
+                       0, // return type size
+                       ConstantPool.JavaLangErrorConstantPoolName,
+                       ConstantPool.Init,
+                       ConstantPool.StringConstructorSignature);
 }
 public void invokeNoClassDefFoundErrorStringConstructor() {
        // invokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V
        if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokespecial;
-       stackDepth -= 2;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundErrorStringConstructor());
+       this.invoke(
+                       OPC_invokespecial,
+                       1, // argCount
+                       0, // return type size
+                       ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName,
+                       ConstantPool.Init,
+                       ConstantPool.StringConstructorSignature);
 }
 public void invokeObjectGetClass() {
        // invokevirtual: java.lang.Object.getClass()Ljava.lang.Class;
        if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Object.getClass()Ljava.lang.Class;"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangObjectGetClass());
+       this.invoke(
+                       OPC_invokevirtual,
+                       0, // argCount
+                       1, // return type size
+                       ConstantPool.JavaLangObjectConstantPoolName,
+                       ConstantPool.GetClass,
+                       ConstantPool.GetClassSignature);
 }
 
 final public void invokespecial(MethodBinding methodBinding) {
@@ -2984,121 +3363,393 @@ final public void invokestatic(MethodBinding methodBinding) {
  * The equivalent code performs a string conversion of the TOS
  * @param typeID <CODE>int</CODE>
  */
-public void invokeStringBufferAppendForType(int typeID) {
-       if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$
-       countLabels = 0;
-       int usedTypeID;
-       if (typeID == T_null)
-               usedTypeID = T_String;
-       else
-               usedTypeID = typeID;
-       // invokevirtual
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+public void invokeStringConcatenationAppendForType(int typeID) {
+       if (DEBUG) {
+               if (this.targetLevel >= JDK1_5) {
+                       System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuilder.append(...)"); //$NON-NLS-1$
+               } else {
+                       System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$
+               }
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferAppend(typeID));
-       if ((usedTypeID == T_long) || (usedTypeID == T_double))
-               stackDepth -= 2;
-       else
-               stackDepth--;
+       int argCount = 1;
+       int returnType = 1;
+       char[] declarinClass = null;
+       char[] selector = ConstantPool.Append;
+       char[] signature = null;
+       switch (typeID) {
+               case T_int :
+               case T_byte :
+               case T_short :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendIntSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendIntSignature;
+                       }
+                       break;
+               case T_long :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendLongSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendLongSignature;
+                       }
+                       argCount = 2;
+                       break;
+               case T_float :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendFloatSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendFloatSignature;
+                       }
+                       break;
+               case T_double :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendDoubleSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendDoubleSignature;
+                       }
+                       argCount = 2;
+                       break;
+               case T_char :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendCharSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendCharSignature;
+                       }
+                       break;
+               case T_boolean :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendBooleanSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendBooleanSignature;
+                       }
+                       break;
+               case T_undefined :
+               case T_JavaLangObject :
+               case T_null :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendObjectSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendObjectSignature;
+                       }
+                       break;
+               case T_JavaLangString :
+                       if (this.targetLevel >= JDK1_5) {
+                               declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+                               signature = ConstantPool.StringBuilderAppendStringSignature;
+                       } else {
+                               declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+                               signature = ConstantPool.StringBufferAppendStringSignature;
+                       }
+                       break;
+       }
+       this.invoke(
+                       OPC_invokevirtual,
+                       argCount, // argCount
+                       returnType, // return type size
+                       declarinClass,
+                       selector,
+                       signature);
 }
 
 public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) {
        // invokespecial: java.lang.AssertionError.<init>(typeBindingID)V
        if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>(typeBindingID)V"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       int argCount = 1;
+       char[] signature = null;
+       switch (typeBindingID) {
+               case T_int :
+               case T_byte :
+               case T_short :
+                       signature = ConstantPool.IntConstrSignature;
+                       break;
+               case T_long :
+                       signature = ConstantPool.LongConstrSignature;
+                       argCount = 2;
+                       break;
+               case T_float :
+                       signature = ConstantPool.FloatConstrSignature;
+                       break;
+               case T_double :
+                       signature = ConstantPool.DoubleConstrSignature;
+                       argCount = 2;
+                       break;
+               case T_char :
+                       signature = ConstantPool.CharConstrSignature;
+                       break;
+               case T_boolean :
+                       signature = ConstantPool.BooleanConstrSignature;
+                       break;
+               case T_JavaLangObject :
+               case T_JavaLangString :
+               case T_null :
+                       signature = ConstantPool.ObjectConstrSignature;
+                       break;
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokespecial;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorConstructor(typeBindingID));
-       stackDepth -= 2;
+       this.invoke(
+                       OPC_invokespecial,
+                       argCount, // argCount
+                       0, // return type size
+                       ConstantPool.JavaLangAssertionErrorConstantPoolName,
+                       ConstantPool.Init,
+                       signature);
 }
 
 public void invokeJavaLangAssertionErrorDefaultConstructor() {
        // invokespecial: java.lang.AssertionError.<init>()V
        if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>()V"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokespecial;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorDefaultConstructor());
-       stackDepth --;
+       this.invoke(
+                       OPC_invokespecial,
+                       0, // argCount
+                       0, // return type size
+                       ConstantPool.JavaLangAssertionErrorConstantPoolName,
+                       ConstantPool.Init,
+                       ConstantPool.DefaultConstructorSignature);
+}
+public void invokeJavaLangEnumname(TypeBinding typeBinding) {
+       // invokevirtual: java.lang.Enum.name()String
+       if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Enum.name()Ljava/lang/String;"); //$NON-NLS-1$
+       this.invoke(
+                       OPC_invokevirtual,
+                       0,
+                       1,
+                       typeBinding.constantPoolName(),
+                       ConstantPool.Name,
+                       ConstantPool.NameSignature);
+}
+public void invokeJavaLangIllegalArgumentExceptionStringConstructor() {
+       // invokespecial: java.lang.IllegalArgumentException.<init>(String)V
+       if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.IllegalArgumentException.<init>(java.lang.String)V"); //$NON-NLS-1$
+       this.invoke(
+                       OPC_invokespecial,
+                       1, // argCount
+                       0, // return type size
+                       ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName,
+                       ConstantPool.Init,
+                       ConstantPool.StringConstructorSignature);
 }
 
-public void invokeStringBufferDefaultConstructor() {
+public void invokeJavaUtilIteratorHasNext() {
+       // invokeinterface java.util.Iterator.hasNext()Z
+       if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.hasNext()Z"); //$NON-NLS-1$
+       this.invoke(
+                       OPC_invokeinterface,
+                       0, // argCount
+                       1, // return type size
+                       ConstantPool.JavaUtilIteratorConstantPoolName,
+                       ConstantPool.HasNext,
+                       ConstantPool.HasNextSignature);
+}
+public void invokeJavaUtilIteratorNext() {
+       // invokeinterface java.util.Iterator.next()java.lang.Object
+       if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.next()java.lang.Object"); //$NON-NLS-1$
+       this.invoke(
+                       OPC_invokeinterface,
+                       0, // argCount
+                       1, // return type size
+                       ConstantPool.JavaUtilIteratorConstantPoolName,
+                       ConstantPool.Next,
+                       ConstantPool.NextSignature);
+}
+public void invokeStringConcatenationDefaultConstructor() {
        // invokespecial: java.lang.StringBuffer.<init>()V
-       if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.<init>()V"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       if (DEBUG) {
+               if (this.targetLevel >= JDK1_5) {
+                       System.out.println(position + "\t\tinvokespecial: java.lang.StringBuilder.<init>()V"); //$NON-NLS-1$
+               } else {
+                       System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.<init>()V"); //$NON-NLS-1$
+               }
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokespecial;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferDefaultConstructor());
-       stackDepth--;
-}
-public void invokeStringBufferStringConstructor() {
-       // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
-       if (DEBUG) System.out.println(position + "\t\tjava.lang.StringBuffer.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+       if (this.targetLevel >= JDK1_5) {
+               declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+       }
+       this.invoke(
+                       OPC_invokespecial,
+                       0, // argCount
+                       0, // return type size
+                       declaringClass,
+                       ConstantPool.Init,
+                       ConstantPool.DefaultConstructorSignature);
+}
+public void invokeStringConcatenationStringConstructor() {
+       if (DEBUG) {
+               if (this.targetLevel >= JDK1_5) {
+                       System.out.println(position + "\t\tjava.lang.StringBuilder.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
+               } else {
+                       System.out.println(position + "\t\tjava.lang.StringBuffer.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
+               }
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokespecial;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferConstructor());
-       stackDepth -= 2;
+       char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+       if (this.targetLevel >= JDK1_5) {
+               declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+       }
+       this.invoke(
+                       OPC_invokespecial,
+                       1, // argCount
+                       0, // return type size
+                       declaringClass,
+                       ConstantPool.Init,
+                       ConstantPool.StringConstructorSignature);
 }
 
-public void invokeStringBufferToString() {
-       // invokevirtual: StringBuffer.toString()Ljava.lang.String;
-       if (DEBUG) System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+public void invokeStringConcatenationToString() {
+       if (DEBUG) {
+               if (this.targetLevel >= JDK1_5) {
+                       System.out.println(position + "\t\tinvokevirtual: StringBuilder.toString()Ljava.lang.String;"); //$NON-NLS-1$
+               } else {
+                       System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$
+               }
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferToString());
+       char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+       if (this.targetLevel >= JDK1_5) {
+               declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+       }
+       this.invoke(
+                       OPC_invokevirtual,
+                       0, // argCount
+                       1, // return type size
+                       declaringClass,
+                       ConstantPool.ToString,
+                       ConstantPool.ToStringSignature);
+}
+public void invokeStringEquals() {
+       // invokevirtual: java.lang.String.equals(java.lang.Object)
+       if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.equals(...)"); //$NON-NLS-1$
+       this.invoke(
+                       OPC_invokevirtual,
+                       1, // argCount
+                       1, // return type size
+                       ConstantPool.JavaLangStringConstantPoolName,
+                       ConstantPool.Equals,
+                       ConstantPool.EqualsSignature);
 }
 public void invokeStringIntern() {
        // invokevirtual: java.lang.String.intern()
        if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.intern()"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringIntern());
+       this.invoke(
+                       OPC_invokevirtual,
+                       0, // argCount
+                       1, // return type size
+                       ConstantPool.JavaLangStringConstantPoolName,
+                       ConstantPool.Intern,
+                       ConstantPool.InternSignature);
 }
 public void invokeStringValueOf(int typeID) {
        // invokestatic: java.lang.String.valueOf(argumentType)
        if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.String.valueOf(...)"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
-       }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokestatic;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID));
+       int argCount = 1;
+       char[] signature = null;
+       switch (typeID) {
+               case T_int :
+               case T_byte :
+               case T_short :
+                       signature = ConstantPool.ValueOfIntSignature;
+                       break;
+               case T_long :
+                       signature = ConstantPool.ValueOfLongSignature;
+                       argCount = 2;
+                       break;
+               case T_float :
+                       signature = ConstantPool.ValueOfFloatSignature;
+                       break;
+               case T_double :
+                       signature = ConstantPool.ValueOfDoubleSignature;
+                       argCount = 2;
+                       break;
+               case T_char :
+                       signature = ConstantPool.ValueOfCharSignature;
+                       break;
+               case T_boolean :
+                       signature = ConstantPool.ValueOfBooleanSignature;
+                       break;
+               case T_JavaLangObject :
+               case T_JavaLangString :
+               case T_null :
+               case T_undefined :
+                       signature = ConstantPool.ValueOfObjectSignature;
+                       break;
+       }
+       this.invoke(
+                       OPC_invokestatic,
+                       argCount, // argCount
+                       1, // return type size
+                       ConstantPool.JavaLangStringConstantPoolName,
+                       ConstantPool.ValueOf,
+                       signature);
+}
+public void invokeSystemArraycopy() {
+       // invokestatic #21 <Method java/lang/System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V>
+       if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V"); //$NON-NLS-1$
+       this.invoke(
+                       OPC_invokestatic,
+                       5, // argCount
+                       0, // return type size
+                       ConstantPool.JavaLangSystemConstantPoolName,
+                       ConstantPool.ArrayCopy,
+                       ConstantPool.ArrayCopySignature);
 }
 public void invokeThrowableGetMessage() {
        // invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;
        if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;"); //$NON-NLS-1$
-       countLabels = 0;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       this.invoke(
+                       OPC_invokevirtual,
+                       0, // argCount
+                       1, // return type size
+                       ConstantPool.JavaLangThrowableConstantPoolName,
+                       ConstantPool.GetMessage,
+                       ConstantPool.GetMessageSignature);
+}
+final public void invoke(int opcode, int argsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) {
+       countLabels = 0;
+       int argCount = argsSize;
+       switch(opcode) {
+               case OPC_invokeinterface :
+                       if (classFileOffset + 4 >= bCodeStream.length) {
+                               resizeByteArray();
+                       }
+                       position +=3;
+                       bCodeStream[classFileOffset++] = OPC_invokeinterface;
+                       writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, true));
+                       argCount++;
+                       bCodeStream[classFileOffset++] = (byte) argCount;
+                       bCodeStream[classFileOffset++] = 0;
+                       break;
+               case OPC_invokevirtual :
+               case OPC_invokespecial :
+                       if (classFileOffset + 2 >= bCodeStream.length) {
+                               resizeByteArray();
+                       }
+                       position++;
+                       bCodeStream[classFileOffset++] = (byte) opcode;
+                       writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
+                       argCount++;
+                       break;
+               case OPC_invokestatic :
+                       if (classFileOffset + 2 >= bCodeStream.length) {
+                               resizeByteArray();
+                       }
+                       position++;
+                       bCodeStream[classFileOffset++] = OPC_invokestatic;
+                       writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
+       }
+       stackDepth += returnTypeSize - argCount;
+       if (stackDepth > stackMax) {
+               stackMax = stackDepth;
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_invokevirtual;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage());
 }
 final public void invokevirtual(MethodBinding methodBinding) {
        if (DEBUG) System.out.println(position + "\t\tinvokevirtual:"+methodBinding); //$NON-NLS-1$
@@ -3433,13 +4084,13 @@ final public void lconst_1() {
        bCodeStream[classFileOffset++] = OPC_lconst_1;
 }
 final public void ldc(float constant) {
-       if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
        countLabels = 0;
        int index = constantPool.literalIndex(constant);
        stackDepth++;
        if (stackDepth > stackMax)
                stackMax = stackDepth;
        if (index > 255) {
+               if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
                // Generate a ldc_w
                if (classFileOffset + 2 >= bCodeStream.length) {
                        resizeByteArray();
@@ -3448,6 +4099,7 @@ final public void ldc(float constant) {
                bCodeStream[classFileOffset++] = OPC_ldc_w;
                writeUnsignedShort(index);
        } else {
+               if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
                // Generate a ldc
                if (classFileOffset + 1 >= bCodeStream.length) {
                        resizeByteArray();
@@ -3458,13 +4110,13 @@ final public void ldc(float constant) {
        }
 }
 final public void ldc(int constant) {
-       if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
        countLabels = 0;
        int index = constantPool.literalIndex(constant);
        stackDepth++;
        if (stackDepth > stackMax)
                stackMax = stackDepth;
        if (index > 255) {
+               if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
                // Generate a ldc_w
                if (classFileOffset + 2 >= bCodeStream.length) {
                        resizeByteArray();
@@ -3473,6 +4125,7 @@ final public void ldc(int constant) {
                bCodeStream[classFileOffset++] = OPC_ldc_w;
                writeUnsignedShort(index);
        } else {
+               if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
                // Generate a ldc
                if (classFileOffset + 1 >= bCodeStream.length) {
                        resizeByteArray();
@@ -3483,7 +4136,6 @@ final public void ldc(int constant) {
        }
 }
 final public void ldc(String constant) {
-       if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
        countLabels = 0;
        int currentConstantPoolIndex = constantPool.currentIndex;
        int currentConstantPoolOffset = constantPool.currentOffset;
@@ -3496,6 +4148,7 @@ final public void ldc(String constant) {
                if (stackDepth > stackMax)
                        stackMax = stackDepth;
                if (index > 255) {
+                       if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
                        // Generate a ldc_w
                        if (classFileOffset + 2 >= bCodeStream.length) {
                                resizeByteArray();
@@ -3504,6 +4157,7 @@ final public void ldc(String constant) {
                        bCodeStream[classFileOffset++] = OPC_ldc_w;
                        writeUnsignedShort(index);
                } else {
+                       if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
                        // Generate a ldc
                        if (classFileOffset + 1 >= bCodeStream.length) {
                                resizeByteArray();
@@ -3554,7 +4208,7 @@ final public void ldc(String constant) {
                }
                // check if all the string is encoded (PR 1PR2DWJ)
                // the string is too big to be encoded in one pass
-               newStringBuffer();
+               newStringContatenation();
                dup();
                // write the first part
                char[] subChars = new char[i];
@@ -3582,7 +4236,7 @@ final public void ldc(String constant) {
                        bCodeStream[classFileOffset++] = (byte) index;
                }
                // write the remaining part
-               invokeStringBufferStringConstructor();
+               invokeStringConcatenationStringConstructor();
                while (i < constantLength) {
                        length = 0;
                        utf8encoding = new byte[Math.min(constantLength - i + 100, 65535)];
@@ -3637,12 +4291,38 @@ final public void ldc(String constant) {
                                bCodeStream[classFileOffset++] = (byte) index;
                        }
                        // now on the stack it should be a StringBuffer and a string.
-                       invokeStringBufferAppendForType(T_String);
+                       invokeStringConcatenationAppendForType(T_JavaLangString);
                }
-               invokeStringBufferToString();
+               invokeStringConcatenationToString();
                invokeStringIntern();
        }
 }
+final public void ldc(TypeBinding typeBinding) {
+       countLabels = 0;
+       int index = constantPool.literalIndexForType(typeBinding.constantPoolName());
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (index > 255) {
+               if (DEBUG) System.out.println(position + "\t\tldc_w:"+ typeBinding); //$NON-NLS-1$
+               // Generate a ldc_w
+               if (classFileOffset + 2 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ldc_w;
+               writeUnsignedShort(index);
+       } else {
+               if (DEBUG) System.out.println(position + "\t\tldw:"+ typeBinding); //$NON-NLS-1$
+               // Generate a ldc
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_ldc;
+               bCodeStream[classFileOffset++] = (byte) index;
+       }
+}
 final public void ldc2_w(double constant) {
        if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$
        countLabels = 0;
@@ -4287,14 +4967,14 @@ final public void multianewarray(TypeBinding typeBinding, int dimensions) {
        }
        position += 2;
        bCodeStream[classFileOffset++] = OPC_multianewarray;
-       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+       writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
        bCodeStream[classFileOffset++] = (byte) dimensions;
 }
 /**
  * We didn't call it new, because there is a conflit with the new keyword
  */
 final public void new_(TypeBinding typeBinding) {
-       if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding); //$NON-NLS-1$
+       if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding.debugName()); //$NON-NLS-1$
        countLabels = 0;
        stackDepth++;
        if (stackDepth > stackMax)
@@ -4304,7 +4984,7 @@ final public void new_(TypeBinding typeBinding) {
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_new;
-       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+       writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
 }
 final public void newarray(int array_Type) {
        if (DEBUG) System.out.println(position + "\t\tnewarray:"+array_Type); //$NON-NLS-1$
@@ -4316,32 +4996,32 @@ final public void newarray(int array_Type) {
        bCodeStream[classFileOffset++] = OPC_newarray;
        bCodeStream[classFileOffset++] = (byte) array_Type;
 }
-public void newArray(Scope scope, ArrayBinding arrayBinding) {
-       TypeBinding component = arrayBinding.elementsType(scope);
+public void newArray(ArrayBinding arrayBinding) {
+       TypeBinding component = arrayBinding.elementsType();
        switch (component.id) {
                case T_int :
-                       this.newarray(10);
+                       this.newarray(INT_ARRAY);
                        break;
                case T_byte :
-                       this.newarray(8);
+                       this.newarray(BYTE_ARRAY);
                        break;
                case T_boolean :
-                       this.newarray(4);
+                       this.newarray(BOOLEAN_ARRAY);
                        break;
                case T_short :
-                       this.newarray(9);
+                       this.newarray(SHORT_ARRAY);
                        break;
                case T_char :
-                       this.newarray(5);
+                       this.newarray(CHAR_ARRAY);
                        break;
                case T_long :
-                       this.newarray(11);
+                       this.newarray(LONG_ARRAY);
                        break;
                case T_float :
-                       this.newarray(6);
+                       this.newarray(FLOAT_ARRAY);
                        break;
                case T_double :
-                       this.newarray(7);
+                       this.newarray(DOUBLE_ARRAY);
                        break;
                default :
                        this.anewarray(component);
@@ -4359,7 +5039,7 @@ public void newJavaLangError() {
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_new;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangError());
+       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangErrorConstantPoolName));
 }
 
 public void newJavaLangAssertionError() {
@@ -4374,9 +5054,22 @@ public void newJavaLangAssertionError() {
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_new;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError());
+       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangAssertionErrorConstantPoolName));
+}
+public void newJavaLangIllegalArgumentException() {
+       // new: java.lang.IllegalArgumentException
+       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.IllegalArgumentException"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_new;
+       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName));
 }
-
 public void newNoClassDefFoundError() {
        // new: java.lang.NoClassDefFoundError
        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.NoClassDefFoundError"); //$NON-NLS-1$
@@ -4389,21 +5082,33 @@ public void newNoClassDefFoundError() {
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_new;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError());
+       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName));
 }
-public void newStringBuffer() {
+public void newStringContatenation() {
        // new: java.lang.StringBuffer
-       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
+       // new: java.lang.StringBuilder
+       if (DEBUG) {
+               if (this.targetLevel >= JDK1_5) {
+                       System.out.println(position + "\t\tnew: java.lang.StringBuilder"); //$NON-NLS-1$
+               } else {
+                       System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
+               }
+       }
        countLabels = 0;
        stackDepth++;
-       if (stackDepth > stackMax)
+       if (stackDepth > stackMax) {
                stackMax = stackDepth;
+       }
        if (classFileOffset + 2 >= bCodeStream.length) {
                resizeByteArray();
        }
        position++;
        bCodeStream[classFileOffset++] = OPC_new;
-       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuffer());
+       if (this.targetLevel >= JDK1_5) {
+               writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangStringBuilderConstantPoolName));
+       } else {
+               writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangStringBufferConstantPoolName));
+       }
 }
 public void newWrapperFor(int typeID) {
        countLabels = 0;
@@ -4418,39 +5123,39 @@ public void newWrapperFor(int typeID) {
        switch (typeID) {
                case T_int : // new: java.lang.Integer
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Integer"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangInteger());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangIntegerConstantPoolName));
                        break;
                case T_boolean : // new: java.lang.Boolean
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Boolean"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangBooleanConstantPoolName));
                        break;
                case T_byte : // new: java.lang.Byte
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Byte"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangByte());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangByteConstantPoolName));
                        break;
                case T_char : // new: java.lang.Character
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Character"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangCharacterConstantPoolName));
                        break;
                case T_float : // new: java.lang.Float
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Float"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangFloat());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangFloatConstantPoolName));
                        break;
                case T_double : // new: java.lang.Double
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Double"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangDouble());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangDoubleConstantPoolName));
                        break;
                case T_short : // new: java.lang.Short
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Short"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangShort());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangShortConstantPoolName));
                        break;
                case T_long : // new: java.lang.Long
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Long"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangLong());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangLongConstantPoolName));
                        break;
                case T_void : // new: java.lang.Void
                        if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Void"); //$NON-NLS-1$
-                       writeUnsignedShort(constantPool.literalIndexForJavaLangVoid());
+                       writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangVoidConstantPoolName));
        }
 }
 final public void nop() {
@@ -4484,37 +5189,29 @@ final public void pop2() {
 }
 final public void putfield(FieldBinding fieldBinding) {
        if (DEBUG) System.out.println(position + "\t\tputfield:"+fieldBinding); //$NON-NLS-1$
-       countLabels = 0;
-       int id;
-       if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
-               stackDepth -= 3;
-       else
-               stackDepth -= 2;
-       if (stackDepth > stackMax)
-               stackMax = stackDepth;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       int returnTypeSize = 1;
+       if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+               returnTypeSize = 2;
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_putfield;
-       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+       generateFieldAccess(
+                       OPC_putfield,
+                       returnTypeSize,
+                       fieldBinding.declaringClass.constantPoolName(),
+                       fieldBinding.name,
+                       fieldBinding.type.signature());
 }
 final public void putstatic(FieldBinding fieldBinding) {
        if (DEBUG) System.out.println(position + "\t\tputstatic:"+fieldBinding); //$NON-NLS-1$
-       countLabels = 0;
-       int id;
-       if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
-               stackDepth -= 2;
-       else
-               stackDepth -= 1;
-       if (stackDepth > stackMax)
-               stackMax = stackDepth;
-       if (classFileOffset + 2 >= bCodeStream.length) {
-               resizeByteArray();
+       int returnTypeSize = 1;
+       if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+               returnTypeSize = 2;
        }
-       position++;
-       bCodeStream[classFileOffset++] = OPC_putstatic;
-       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+       generateFieldAccess(
+                       OPC_putstatic,
+                       returnTypeSize,
+                       fieldBinding.declaringClass.constantPoolName(),
+                       fieldBinding.name,
+                       fieldBinding.type.signature());
 }
 public void record(LocalVariableBinding local) {
        if (!generateLocalVariableTableAttributes)
@@ -4574,15 +5271,14 @@ public void recordPositionsFrom(int startPC, int sourcePos) {
                                        if (existingEntryIndex != -1) {
                                                // widen existing entry
                                                pcToSourceMap[existingEntryIndex] = startPC;
-                                       } else {
+                                       } else if (insertionIndex < 1 || pcToSourceMap[insertionIndex - 1] != newLine) {
                                                // we have to add an entry that won't be sorted. So we sort the pcToSourceMap.
                                                System.arraycopy(pcToSourceMap, insertionIndex, pcToSourceMap, insertionIndex + 2, pcToSourceMapSize - insertionIndex);
                                                pcToSourceMap[insertionIndex++] = startPC;
                                                pcToSourceMap[insertionIndex] = newLine;
                                                pcToSourceMapSize += 2;
                                        }
-                               }
-                               if (position != lastEntryPC) { // no bytecode since last entry pc
+                               } else if (position != lastEntryPC) { // no bytecode since last entry pc
                                        pcToSourceMap[pcToSourceMapSize++] = lastEntryPC;
                                        pcToSourceMap[pcToSourceMapSize++] = newLine;
                                }
@@ -4630,12 +5326,22 @@ public void recordPositionsFrom(int startPC, int sourcePos) {
  */
 public void registerExceptionHandler(ExceptionLabel anExceptionLabel) {
        int length;
-       if (exceptionHandlersNumber >= (length = exceptionHandlers.length)) {
+       if (exceptionHandlersIndex >= (length = exceptionHandlers.length)) {
                // resize the exception handlers table
                System.arraycopy(exceptionHandlers, 0, exceptionHandlers = new ExceptionLabel[length + LABELS_INCREMENT], 0, length);
        }
        // no need to resize. So just add the new exception label
-       exceptionHandlers[exceptionHandlersNumber++] = anExceptionLabel;
+       exceptionHandlers[exceptionHandlersIndex++] = anExceptionLabel;
+       exceptionHandlersCounter++;
+}
+public void removeExceptionHandler(ExceptionLabel exceptionLabel) {
+       for (int i = 0; i < exceptionHandlersIndex; i++) {
+               if (exceptionHandlers[i] == exceptionLabel) {
+                       exceptionHandlers[i] = null;
+                       exceptionHandlersCounter--;
+                       return;
+               }
+       }
 }
 public final void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
        // given some flow info, make sure we did not loose some variables initialization