/**********************************************************************
 * This file is part of the "Object Teams Runtime Environment"
 *
 * Copyright 2002-2009 Berlin Institute of Technology, Germany.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Please visit http://www.objectteams.org for updates and contact.
 *
 * Contributors:
 * Berlin Institute of Technology - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otre;

import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.*;

import java.util.*;

import org.eclipse.objectteams.otre.jplis.JPLISEnhancer;
import org.eclipse.objectteams.otre.util.*;
import org.objectteams.OTREInternalError;

/**
 * for callin-role-methods with recursive method-calls (base calls) we add a
 * method with extendend signature.
 * Within the extendend method recursive calls are replaced by the corresponding
 * (chaining)base-call.<p>
 * For example:
 * <pre>
 *      callin m1() { m1(); } -->
 *      callin m1(Team _OT$teams[], int _OT$teamIDs[],
 *                int _OT$idx, int _OT$baseMethTag){
 *          liftToRole(b1._OT$m1$chain(Team _OT$teams[],
 *                                     int _OT$teamIDs[],
 *                                     int _OT$idx,
 *                                     int _OT$baseMethTag));
 *      }
 * </pre>
 *
 * @version $Id: BaseCallRedirection.java 23408 2010-02-03 18:07:35Z stephan $
 * @author  Christine Hundt
 * @author Stephan Herrmann
 */
public class BaseCallRedirection extends ObjectTeamsTransformation {

    static class IHPair {
		private InstructionHandle _ih1, _ih2;
		public IHPair (InstructionHandle ih1, InstructionHandle ih2) {
			_ih1 = ih1;
			_ih2 = ih2;
		}
		public InstructionHandle fst() {return _ih1; }
		public InstructionHandle snd() {return _ih2; }
	}

    public BaseCallRedirection(Object loader) {
    	super(loader);
    }
    
    /**
     * @param ce
     * @param cg
     */
    public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
    	factory = new InstructionFactory(cg);
    	String class_name = cg.getClassName();

        ConstantPoolGen cpg = cg.getConstantPool();
    	checkReadClassAttributes(ce, cg, class_name, cpg);
            
    	if (!CallinBindingManager.isRole(class_name)) {
    		return;
    	}
						
    	if (!cg.isInterface()) {
	    	Set<String> boundBaseMethods = CallinBindingManager.getBoundRoleMethods(class_name);    	
	    	addBaseCallSurrogatesForReplaceBindings(ce, boundBaseMethods, cg);
    	}

    	Method[] methods = cg.getMethods();
    	for (int i=0; i<methods.length; i++) {
    		Method m = methods[i];
    		String method_name  = m.getName();
    		String method_signature = m.getSignature();
            
    		if (candidateForImplicitActivation(m, cg, cpg)) { // TODO: check the other preconditions, like not abstact etc. 
    			cg.replaceMethod(m, genImplicitActivation(m, class_name, cpg, true));
    	    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
    		}
    		
    		if (!isCallin(m, cg))
    			continue;
            if (logging) printLogMessage(method_name + " in " + class_name
                        + " IS A CALLIN-METHOD!");
    		if (method_name.startsWith(OT_PREFIX)) {
    			method_name = revertToOriginalName(method_name);
    			if (logging) printLogMessage("Reverted tsuper name to " + method_name);
    		}
    		// code SHOULD contain at least one base call.
            if(logging) printLogMessage("----->will add another method " + method_name
    						+ " with enhanced signature");
             
//{SH: retrench signature because otherwise the binding will not be found,
//     as a result an empty basecall surrogate will be generated leading to repetetive methods...
//     TODO(SH) is this the proper way to retrench??
			String enhancedPrefix = "([Lorg/objectteams/Team;[IIII[Ljava/lang/Object;";
			if (method_signature.startsWith(enhancedPrefix)) 
    			method_signature = "("+method_signature.substring(enhancedPrefix.length());
// SH}    		
    		
    		boolean roleMethodIsBound = CallinBindingManager.roleMethodHasBinding(class_name, 
    																	   method_name,
																		   method_signature);

    		//if (mbs.isEmpty()) {
    		if (!roleMethodIsBound) {
    			if (logging) printLogMessage("callin method " + method_name + method_signature
    						+ " was not bound in this class!!!");
    		}
    		MethodGen baseCallSurrogate = null;
    		if (!IS_COMPILER_13X_PLUS) { // since 1.3.0 this part is legacy:
	    		if (!roleMethodIsBound && !methodHasCallinFlags(m, cg, OVERRIDING) && !m.isStatic()) {
	    			// method not bound in current class and doesn't inherit a base call surrogate
	    			baseCallSurrogate = generateEmptyBaseCallSurrogate(cg, m);
	    		}
	    		if (baseCallSurrogate != null)
	    			ce.addMethod(baseCallSurrogate.getMethod(), cg);
    		}
    		
    	}
    }

	/**
	 *  Generates an "empty" base call surrogate method, which just throws an 'Error'.
	 *  This method should normaly never be called, but overwritten in a subclass. 
	 *  It has to be generated just for the wellformedness of the class file.
	 * @param cg
	 * @param m
	 * @param mbs
	 * @param baseClassName
	 * @return
	 */
	private MethodGen generateEmptyBaseCallSurrogate(ClassGen cg, Method m/*, List mbs*/) {
		if (m.getName().startsWith(OT_PREFIX))
			return null; // ot-internal methods don't need this?

		ConstantPoolGen cpg = cg.getConstantPool();
		String class_name = cg.getClassName();
		MethodGen mg = newMethodGen(m, class_name, cpg);
		
		if (isTSuperWrapper(mg)) {
			// tsuper wrapper do not need base call surrogates
			return null;
		}
		
		// role method already was enhanced by compiler
		Type[] enhancedArgumentTypes = mg.getArgumentTypes();
		if (IS_COMPILER_GREATER_123) {
			// add super flag between enhancement and real arguments:
			int len = enhancedArgumentTypes.length;
			Type[] newArgumentTypes = new Type[len+1];
			System.arraycopy(enhancedArgumentTypes, 0, newArgumentTypes, 0, EXTRA_ARGS);
			newArgumentTypes[EXTRA_ARGS] = Type.BOOLEAN;
			System.arraycopy(enhancedArgumentTypes, EXTRA_ARGS, newArgumentTypes, EXTRA_ARGS+1, len-EXTRA_ARGS);
			enhancedArgumentTypes = newArgumentTypes;
		}
		Type   enhancedReturnType    = mg.getReturnType();
		
// {SH: interface method has no argument names? generate dummy names: 
		String[] argumentNames = new String[enhancedArgumentTypes.length];
		for (int i = 0; i < argumentNames.length; i++) {
			argumentNames[i] = "arg"+i;
		}
			
		// role method already was enhanced by compiler:
		String[] enhancedArgumentNames = argumentNames;
// }	
		InstructionList il = new InstructionList();
		//int accessFlags = m.getAccessFlags();
		int accessFlags = Constants.ACC_PROTECTED; // no unanticipated calls possible

// {SH: interface methods must be public abstract:
		if (cg.isInterface()) 
			accessFlags = Constants.ACC_ABSTRACT|Constants.ACC_PUBLIC;
// }
		
		MethodGen baseCallSurrogate = new MethodGen(accessFlags,
													enhancedReturnType,
													enhancedArgumentTypes,
													enhancedArgumentNames,
													getBaseCallSurrogateName(m.getName(), m.isStatic(), class_name /*genRoleInterfaceName(class_name)*/), 
													class_name,
													il, cpg);
// {SH: no code for interface method:
		if (!cg.isInterface()) {
			// orig:
			if (logging)
				printLogMessage("Exception has to be thrown!");

			createThrowInternalError(cpg, il, new InstructionList(new PUSH(cpg, "Binding-Error: base-call impossible!")));

			il.append(InstructionFactory.createNull(enhancedReturnType));
			il.append(InstructionFactory.createReturn(enhancedReturnType));

			if (debugging)
				baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER);
		}
// }

		il.setPositions();
		baseCallSurrogate.removeNOPs();
		baseCallSurrogate.setMaxStack();
		baseCallSurrogate.setMaxLocals();
		return baseCallSurrogate;		
	}

	/**
	 * @param mg
	 * @return
	 */
	private static boolean isTSuperWrapper(MethodGen mg) {
		Type[] argTypes = mg.getArgumentTypes();
		if (argTypes.length == 0) {
			return false; // no tsuper marker interface argument existing 
		}
		String lastArgument = (argTypes[argTypes.length - 1]).toString();
		return lastArgument.contains(OTDT_PREFIX);
	}

	/**
	 * Adds base call surrogate method for all role method bindings in the current role class.
	 * Thereby method bindings which are defined in super roles are accumulated and 
	 * considered as well. 
	 * @param ce				the ClassEnhancer to which the new method has to be added
	 * @param boundRoleMethods	the bound methods of the role class
	 * @param cg 				the ClassGen for the role class
	 */
	private void addBaseCallSurrogatesForReplaceBindings(ClassEnhancer ce, Set<String> boundRoleMethods, ClassGen cg)
	{
		Iterator<String> it = boundRoleMethods.iterator();
		while (it.hasNext()) {
			String nameAndSignature = it.next();
			int dotIndex = nameAndSignature.indexOf('.');
			String methodName = nameAndSignature.substring(0, dotIndex);
			String methodSignature = nameAndSignature.substring(dotIndex + 1);
			List<MethodBinding> mbs = CallinBindingManager.getBindingsForRoleMethod(cg.getClassName(), 
																	 methodName, 
																	 methodSignature);
			MethodBinding anyMethodBinding = mbs.get(0);
			if (!anyMethodBinding.isReplace()) {
				continue; 
			}
			mbs.addAll(CallinBindingManager.getInheritedRoleMethodBindings(cg.getClassName(),
																		   methodName,
																		   methodSignature));
			
			if (anyMethodBinding.hasStaticRoleMethod())
				continue; // base call surrogates for static methods are generated within the enclosing team class
			// TODO: remove this check as soon as static replace method bindings are no longer in 'CallinMethodMappings'
			MethodGen baseCallSurrogate = genBaseCallSurrogate(cg, mbs);
			ce.addOrReplaceMethod(baseCallSurrogate.getMethod(), cg);
		}
	}

	/**
	 * Generates base call surrogate method for the role method for which the method bindings 'mbs' are.
	 * Thereby a switch-case for each bound base method is generated.
	 * This method is only for nonstatic role methods. Base call surrogates for static methods 
	 * are generated within the enclosing team class
	 * @param cg			the ClassGen for the role class	
	 * @param mbs			the method bindings for one role method
	 * @param baseClassName	the name of the base class
	 */
	MethodGen genBaseCallSurrogate(ClassGen cg, List<MethodBinding> mbs) {
		
		//baseClassName would not be needed here, if I could find out the root-base-class-type...
		ConstantPoolGen cpg = cg.getConstantPool();
		String class_name = cg.getClassName();

		MethodBinding anyBindingForRoleMethod = mbs.get(0);
		String baseClassName = anyBindingForRoleMethod.getRootBoundBase();
		String roleMethodSignature = anyBindingForRoleMethod.getRoleMethodSignature();

		Type[] enhancedArgumentTypes;
		{
			Type[] argTypesTail = Type.getArgumentTypes(roleMethodSignature);
			if (IS_COMPILER_GREATER_123) {
				// add super flag between enhancement and real arguments:
				int len = argTypesTail.length;
				System.arraycopy(argTypesTail, 0, argTypesTail=new Type[len+1], 1, len);
				argTypesTail[0] = Type.BOOLEAN;
			}
			enhancedArgumentTypes = enhanceArgumentTypes(argTypesTail);
		}
		Type enhancedReturnType = generalizeReturnType(Type.getReturnType(roleMethodSignature));
		String methodName = anyBindingForRoleMethod.getRoleMethodName();
		InstructionList il = new InstructionList();
		int accessFlags = Constants.ACC_PROTECTED;

		MethodGen baseCallSurrogate = new MethodGen(accessFlags,
													enhancedReturnType,
													enhancedArgumentTypes,
													null, // no explicit names
													getBaseCallSurrogateName(methodName, false, 
																			 genRoleInterfaceName(class_name)), 
													class_name,
													il, cpg);

		ObjectType baseClass = new ObjectType(baseClassName);
		ObjectType outerClass;
		{
			String outerClassName = getOuterClassName(class_name);
			outerClass = new ObjectType(outerClassName);
		}
			
		LocalVariableGen otResult = null;
		
		otResult = baseCallSurrogate.addLocalVariable("_OT$result",
				enhancedReturnType, null, null);

		il.insert(InstructionFactory.createStore(enhancedReturnType,
				otResult.getIndex()));
		il.insert(new ACONST_NULL());
		il.setPositions(); // about to retrieve instruction handles.
		
		if (logging) printLogMessage("base-call switch has to be inserted!");	
		InstructionList loading = new InstructionList();
		loading.append(InstructionFactory.createThis());
		int index = 1;
		for (int i = 0; i < enhancedArgumentTypes.length; i++) {
			loading.append(InstructionFactory.createLoad(enhancedArgumentTypes[i],index));
			index += enhancedArgumentTypes[i].getSize();
		}
		
		Type[] argumentTypes = Type.getArgumentTypes(roleMethodSignature);
		Type returnType = Type.getReturnType(roleMethodSignature);
		
		if (debugging) {
			baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER);
		}
		
		boolean generateSuperAccess = false;
		List<SuperMethodDescriptor> superAccesses = IS_COMPILER_GREATER_123 ? CallinBindingManager.getSuperAccesses(baseClassName) : null;
		if (superAccesses != null) {
			outer: for (SuperMethodDescriptor superMethod : superAccesses) {
				for (MethodBinding methodBinding : mbs) {
					if (   superMethod.methodName.equals(methodBinding.getBaseMethodName())
						&& superMethod.signature.equals(methodBinding.getBaseMethodSignature())) 
					{
						generateSuperAccess = true; 
						break outer;
					}
				}
			}
		}

		BranchInstruction ifSuper = new IFEQ(null);
		GotoInstruction skipElse  = new GOTO(null);
		if (generateSuperAccess) {
			// gen: if (isSuperAccess) { _OT$base._OT$m$super(args); } else ...
			il.append(InstructionFactory.createLoad(Type.BOOLEAN, EXTRA_ARGS+1)); // last synthetic arg is super-flag
			il.append(ifSuper);
			il.append(genBaseCallSwitch(cpg, mbs, baseCallSurrogate,
										 argumentTypes,
										 outerClass, baseClass,
										 returnType, 
										 otResult, loading, true));
			il.append(skipElse);
		}
		InstructionList 
		basecall = genBaseCallSwitch(cpg, mbs, baseCallSurrogate,
									 argumentTypes,
									 outerClass, baseClass,
									 returnType,
									 otResult, loading, false);
		InstructionHandle callStart = basecall.getStart(); // store handle before append eats the list
		il.append(basecall);
		if (generateSuperAccess) {
			ifSuper.setTarget(callStart);
			skipElse.setTarget(il.append(new NOP()));
		}
		
		il.append(InstructionFactory.createLoad(enhancedReturnType, otResult.getIndex()));
		il.append(InstructionFactory.createReturn(enhancedReturnType));							
		
		il.setPositions();
		baseCallSurrogate.removeNOPs();
		baseCallSurrogate.setMaxStack();
		baseCallSurrogate.setMaxLocals();
		return baseCallSurrogate;		
	}

/*
    Type findBaseFieldType(JavaClass c, ConstantPoolGen cpg) {
           Field[] fields = c.getFields();
            for (int l=0; l<fields.length; l++) {
                Field f = fields[l];
                if (f.getName().equals(BASE)) {
                    FieldGen fg = new FieldGen(f, cpg);
                    return fg.getType();
                }
            }
			JavaClass superClass = Repository.lookupClass(c.getSuperclassName());
			// BCEL bug: super class of "Object" is "Object":
			//System.err.println("Superclass of "+ c.getClassName()+" is " +c.getSuperclassName());
			if (!superClass.getClassName().equals("java.lang.Object")) {
					return findBaseFieldType(superClass, cpg);
			}
            return null;
    }*/

    /**
	 * Iterate through the instructions of a callin method.
	 * <ul>
	 *   <li>Adjust local variable instructions due to inserted extra arguments.
	 *   <li>Replace base-calls and calls to activate.
	 * </ul>
	 * @param cg
	 * @param m
	 * @param mbs List<MethodBinding>
	 * @return MethodGen
	 */
    MethodGen replaceBaseCalls(ClassGen cg, Method m, List<MethodBinding> mbs) {

    	int indexOffset = m.isStatic() ? -1 : 0; // argument indices are decremented for static methods, 
												 // because of the missing 'this'
        
    	ConstantPoolGen cpg = cg.getConstantPool();
        String class_name   = cg.getClassName();
        String method_name  = m.getName();

        MethodGen mg = newMethodGen(m, class_name, cpg);

		Type[]   argumentTypes         = mg.getArgumentTypes();
        Type     returnType            = mg.getReturnType();
       
        Type[] enhancedArgumentTypes = enhanceArgumentTypes(mg.getArgumentTypes());
// {SH abstract methods may not have argument names??        
        String[] argumentNames;
        if (m.isAbstract()) {
        	argumentNames = new String[argumentTypes.length];
			int index = 0;
        	for (int i = 0; i < argumentNames.length; i++) {
				argumentNames[i] = "arg" + index/* i */;
				index += argumentTypes[i].getSize();
			}
			
/*			
//			load regular arguments:
				 int index = 1;
				 for (int i=0; i<argTypes.length; i++) {
					 il.append(InstructionFactory.createLoad(argTypes[i],index));
					 index += argTypes[i].getSize();
				 }
//*/
			
        } else {
        	argumentNames = mg.getArgumentNames();
        }
        String[] enhancedArgumentNames = enhanceArgumentNames(argumentNames);
// orig:        String[] enhancedArgumentNames = enhanceArgumentNames(mg.getArgumentNames());
// SH}       

        Type enhancedMethodReturnType  = generalizeReturnType(m.getSignature());

// {SH instruction list may be null for abstract method		
// orig:   InstructionList il = mg.getInstructionList().copy();
		InstructionList il = mg.getInstructionList();
		if (il != null)
			il = il.copy();
		else
			il = new InstructionList();
// SH}		

        MethodGen enhancedMethod = new MethodGen(m.getAccessFlags(),
                                                 enhancedMethodReturnType,
                                                 enhancedArgumentTypes,
                                                 enhancedArgumentNames,
                                                 method_name, class_name,
                                                 il, cpg);
		//not needed??:
		// or not??????
		copyLocalVariables(mg, enhancedMethod);
		copyLineNumbers(mg, enhancedMethod);
		
        boolean returnValueAdded   =    (returnType               == Type.VOID)
                                     && (enhancedMethodReturnType != Type.VOID);

		// all exception handlers of this method, which have to be updated later.
		CodeExceptionGen [] handlers = copyExceptionHandlers(mg, enhancedMethod, il);
		// list of instruction handles (old and new) that are replaced in the sequel
		ArrayList<IHPair> replacedInstructions = new ArrayList<IHPair>(); // of IHPair;
		// set of instruction handles which signal TargetLostException during delete().
		HashSet<InstructionHandle> targetLost = new HashSet<InstructionHandle>(); // of InstructionHandle

        // create  LocalVariable Object _OT$result:
        LocalVariableGen otResult = null;
        
        int slot = mg.getMaxLocals() + EXTRA_ARGS-indexOffset;
        otResult = enhancedMethod.addLocalVariable("_OT$result", enhancedMethodReturnType,
												   slot, null, null);
        
        // subtract EXTRA_ARGS since this offset will be added again below.
        il.insert(InstructionFactory.createStore(enhancedMethodReturnType,
        							    		 otResult.getIndex() - EXTRA_ARGS));

        il.insert(new ACONST_NULL());
        il.setPositions(); // about to retrieve instruction handles.

        InstructionHandle[] ihs = il.getInstructionHandles();
        //printLogMessage("every call of base." + method_name + "(...) will be replaced by "
        //            + liftMethodName + BASE + "."+baseChainMethodName+"(...))");

        int actInstruction = 0;
        int offset = EXTRA_ARGS;
        while (actInstruction < ihs.length) {
			Instruction act_instruction = ihs[actInstruction].getInstruction();
/****************************** variable index adaption: **********************************/
   			if(act_instruction instanceof LocalVariableInstruction) {
            // add offset to the index of every variable load or store instruction,
			// because of the inserted EXTRA_ARGS  arguments:
                LocalVariableInstruction localVariableInstruction = (LocalVariableInstruction) act_instruction;
                if (localVariableInstruction.getIndex() != 0 || (enhancedMethod.isStatic())) { // 'this' stays at index 0
                    if (localVariableInstruction instanceof StoreInstruction) {
                        localVariableInstruction =
							InstructionFactory.createStore(localVariableInstruction.getType(cpg),
														   offset+localVariableInstruction.getIndex());
                    } else if (localVariableInstruction instanceof LoadInstruction) {
                        localVariableInstruction =
							InstructionFactory.createLoad(localVariableInstruction.getType(cpg),
											   			  offset+localVariableInstruction.getIndex());
                    } else if (localVariableInstruction instanceof IINC) {
                    	localVariableInstruction.setIndex(offset+localVariableInstruction.getIndex());
                    	// TODO: check, if this is enough for all kinds of LocalVariableInstructions 
                    	//               and if there are more instructions which use variable indizes!!
                    }
                    ihs[actInstruction].setInstruction(localVariableInstruction);
                }
            } else if (act_instruction instanceof RET) {
                RET ret = (RET)act_instruction;
                if (ret.getIndex() != 0)
                    ihs[actInstruction].setInstruction(new RET(offset + ret.getIndex()));

/*************************** "super"- & "tsuper"-call enhancement: **********************************/
   			} else if (super_or_tsuper_instruction(act_instruction, method_name, cpg) ) {

				InvokeInstruction ii = (InvokeInstruction)act_instruction;
				InstructionHandle next = ihs[actInstruction+1];
				InstructionList changedArea;
				InstructionHandle[] delim = new InstructionHandle[2];
				int stackDepth = computeArgumentStackDepth(cpg, ii);
				InstructionList loading = pruneLoading(il, ihs, actInstruction,
													   stackDepth, cpg,
													   targetLost, delim, true);
				if (loading == null) {
					actInstruction++;
					continue;
				}
				 
				changedArea = genEnhancedSuperCall(cpg, ii, enhancedMethod, loading);
				if (returnValueAdded) {
                    changedArea.append(InstructionFactory.createStore(
                            enhancedMethodReturnType, otResult.getIndex()));
                } else {
					InstructionHandle ih = adjustValue(changedArea, changedArea.getEnd(), enhancedMethodReturnType, returnType);
					if (debugging && ih != null)
						mg.addLineNumber(ih, STEP_OVER_LINENUMBER);
				}
				replacedInstructions.add(new IHPair(delim[0], changedArea.getStart()));
				replacedInstructions.add(new IHPair(delim[1], changedArea.getEnd()));

				il.insert(next, changedArea);
				actInstruction++;
				continue;
				
/*************************** "activate" substitution and base-call generation: ************/
            //} else if (act_instruction instanceof INVOKEVIRTUAL) {
            //    INVOKEVIRTUAL iv = (INVOKEVIRTUAL)act_instruction;
			} else if (act_instruction instanceof InvokeInstruction) {
				InvokeInstruction iv = (InvokeInstruction)act_instruction;
                String iv_name = iv.getName(cpg);

                // FIXME(SH): is this still needed? 
                //            - activate is commented-out,
                //            - base call is now generated by the compiler.
                if(!(iv_name.equals(method_name) ||
                     iv_name.equals("activate")))
				{
                    actInstruction++;
                    continue;
                }
                InstructionHandle next = ihs[actInstruction+1];
                InstructionList changedArea;
				InstructionHandle[] delim = new InstructionHandle[2];
               /*
                if (iv_name.equals("activate")) {
					// blank original invokevirtual:
					ihs[actInstruction].setInstruction(new NOP());
					Type [] ivArgTypes = iv.getArgumentTypes(cpg);
					int activateArgCount = ivArgTypes.length;
					InstructionList loading = null;
					if (activateArgCount == 1)
						loading = pruneLoading (il, ihs, actInstruction,
												ivArgTypes[0].getSize(), cpg,
												targetLost, delim, false);
					changedArea = enhanceActivateCall(factory, cpg, loading, iv);
					if (activateArgCount == 1) {
						replacedInstructions.add(new IHPair(delim[0],
															changedArea.getStart()));
						replacedInstructions.add(new IHPair(delim[1],
															changedArea.getEnd()));
					}
                } else*/ { // base call:
                    int            stackDepth = computeArgumentStackDepth(cpg, iv);
                    boolean deleteThis = true;
                   
                    if(enhancedMethod.isStatic())
                    	deleteThis = false;
                    
                    /*
                    if (iv.getOpcode()==Constants.INVOKESTATIC) 
                    	deleteThis = false; 
                    */
                    InstructionList   loading = pruneLoading(il, ihs, actInstruction,
															 stackDepth, cpg,
															 targetLost, delim, /*true*/deleteThis);
					//System.err.println(loading);
					if (loading == null) {
						actInstruction++;
						continue;
					}

					// insert call of base-call surrogate method:
					String roleInterfaceName = genRoleInterfaceName(cg.getClassName());
					
					String calleeClassName = null;
					if(m.isStatic()) {
						calleeClassName = extractTeamName(roleInterfaceName);
					}
					changedArea = genBaseCallSurrogateCall(cpg, iv, enhancedMethod, loading, extractRoleName(roleInterfaceName), calleeClassName);

					if (returnValueAdded) {
						changedArea.append(InstructionFactory.createStore(enhancedMethodReturnType,
																		 otResult.getIndex()));				
                	} else {
						InstructionHandle ih = adjustValue(changedArea, changedArea.getEnd(), enhancedMethodReturnType, returnType);
						if (debugging && ih != null)
							mg.addLineNumber(ih, STEP_OVER_LINENUMBER);
                	}
                    replacedInstructions.add(new IHPair(delim[0], changedArea.getStart()));
                    replacedInstructions.add(new IHPair(delim[1], changedArea.getEnd()));

				} // if (activate or base call)

                il.insert(next, changedArea);


/*************************** "return" enhancements: ************/
			} else if (act_instruction instanceof ReturnInstruction) {
				// replace return statement by result preparation and a new return statement
				// construct back to front, to keep the insertion position!
				InstructionHandle oldReturn    = ihs[actInstruction];
				InstructionHandle replacedPos  = oldReturn;
				il.append(oldReturn, InstructionFactory.createReturn(enhancedMethodReturnType));
				if (returnValueAdded) {
					// load ot_result:
					oldReturn.setInstruction(InstructionFactory.createLoad(enhancedMethodReturnType,
																otResult.getIndex()));
				} else {
					oldReturn.setInstruction(new NOP());
					replacedPos =
						adjustValue(il, oldReturn, returnType, enhancedMethodReturnType);
					if (debugging && replacedPos != null)
						mg.addLineNumber(replacedPos, STEP_OVER_LINENUMBER);
				}
				if (replacedPos != null)
					replacedInstructions.add(new IHPair(oldReturn, replacedPos));
            } // conditional over instruction types
			actInstruction++;
        } //end while

		// tidy:
		checkUpdate(handlers, replacedInstructions, targetLost);
        enhancedMethod.removeNOPs();
		il.setPositions();
        enhancedMethod.setMaxStack();
        enhancedMethod.setMaxLocals();

        return enhancedMethod;
    }

    /**
     * Given an invokevirtual compute the space its arguments use on the stack.
     * @param cpg
     * @param iv
     * @return int stack size.
     */
    static int computeArgumentStackDepth(ConstantPoolGen cpg, InvokeInstruction ii) {
        Type [] iiargs = ii.getArgumentTypes(cpg);
        int depth=0;
        for (int i=0; i<iiargs.length; i++)
            depth += iiargs[i].getSize();
        return depth;
    }

	/**
	 *  Copy all local variables from <tt>src</tt> to <tt>dest</tt>.
	 *  While doing so, increment their index by EXTRA_ARGS.
	 */
	static void copyLocalVariables(MethodGen src, MethodGen dest) {
		Type[] argumentTypes = src.getArgumentTypes();
		LocalVariableGen[] lvgs = src.getLocalVariables();
		for (int l=argumentTypes.length; l<lvgs.length; l++) {
			LocalVariableGen lvg = lvgs[l];
			if (lvg.getIndex() > 0) {
				dest.addLocalVariable(lvg.getName(),
									  			   lvg.getType(),
									  			   lvg.getIndex()+(EXTRA_ARGS+1), // +1?????
									  			   null, null);
				//System.err.println("adding:" +src.getClassName() +" "+src.getName()+" "+lvg.getName() +" " + lvg.getType() +" "+ (lvg.getIndex()+(EXTRA_ARGS+1)));
			}	
		}
	}
	/** Copy all line numbers from <tt>src</tt> to <tt>dest</tt>. */
	static void copyLineNumbers(MethodGen src, MethodGen dest) {
		InstructionList il_dest = dest.getInstructionList();
		il_dest.setPositions();
		LineNumberGen[] src_lng = src.getLineNumbers();
		for (int i=0; i<src_lng.length; i++) {
			int position = src_lng[i].getInstruction().getPosition();
			InstructionHandle ih = il_dest.findHandle(position);
			dest.addLineNumber(ih, src_lng[i].getSourceLine());
		}
	}
   /**
     * Prune a invokevirtual portion from a given instruction list.
     * Note, that arguments don't include 'this', which is not pruned but blanked
     * (need to keep as possible jump target).
     * @param il the source list
     * @param ihs array of handles of this list
     * @param idx points to a invokevirtual that shall be removed
     * @param stackDepth size of the called method's arguments on the stack.
	 *                   This is how deep we need to cut into the stack.
     * @param cpg
     * @param targetLost set of lost InstructionHandles to be filled
     * @param delim array of two handles, which should be filled with start and end of
	 *              the pruned region.
	 * @param blankThis should the 'this' call target be overwritten?
     * @return InstructionList a copy of the original value loading.
     */
    static InstructionList pruneLoading (InstructionList il, InstructionHandle[] ihs, int idx,
								  int stackDepth, ConstantPoolGen cpg,
								  HashSet<InstructionHandle> targetLost, InstructionHandle[] delim,
								  boolean blankThis)
    {
        InstructionList nlist = new InstructionList();
        InstructionHandle start = ihs[idx];
        InstructionHandle end = ihs[idx--];
        while (stackDepth > 0) {
            start = ihs[idx--];
            Instruction instr = start.getInstruction();
            stackDepth -= stackDiff(instr, cpg);
            nlist.insert(instr);
        }
		if (blankThis) {
			if (!isALoad0(ihs[idx].getInstruction()))
				return null;
			ihs[idx].setInstruction(new NOP()); // keep as jump target but delete 'this'
		}
        delim[0] = start;
        delim[1] = end;
        safeDelete(il, start, end, targetLost);
		return nlist;
    }

	static boolean isALoad0(Instruction i) {
		if (!(i instanceof ALOAD)) return false;
		return ((ALOAD)i).getIndex() == 0;
	}

	/** Get the lenght of the longest base method signature in mbs.
	 *  @param mbs List of {@link MethodBinding MethodBinding}
	 */
//	static int getMaxBaseArgLen (List mbs) {
//		int max=0;
//		Iterator it = mbs.iterator();
//		while (it.hasNext()) {
//			MethodBinding mb = (MethodBinding)it.next();
//			String sign = mb.getBaseMethodSignature();
//			int len = Type.getArgumentTypes(sign).length;
//			if (len>max) max = len;
//		}
//		return max;
//	}

	/**
     * Generate a dispatching switch statement which calls the proper base method.
	 * @param cpg
     * @param mbs list of MethodBinding that applies to this callin method
     * @param enhancedMethod the enhanced callin method
	 * @param roleArgumentTypes arg types of the callin method
     * @param outerClass the Team
     * @param baseClass the base bound to this role
     * @param returnType the return type of the original callin method
     * @param otResult the local variable storing the base call result
     * @param loading an instruction list holding the original instructions for
	 *        loading parameters
     * @return InstructionList the complete replacement implementing the base call.
     */
	InstructionList genBaseCallSwitch (ConstantPoolGen cpg,
									   List<MethodBinding> mbs, MethodGen enhancedMethod,
									   Type[] roleArgumentTypes,
									   ObjectType outerClass, ObjectType baseClass,
                                       Type returnType, LocalVariableGen otResult,
                                       InstructionList loading,
                                       boolean isSuperAccess)
    {
    	
        String  className                = enhancedMethod.getClassName();
        Type    enhancedMethodReturnType = enhancedMethod.getReturnType();
		boolean callinHasReturnValue     = returnType != Type.VOID;

		InstructionList il = new InstructionList();

		// Setup a variable which holds the result of this base call.
		// This variabel is local to this segment of code and used only
		// to transport this result out off the switch statement.
		int     localResult = -1;
		LocalVariableGen lg = null;
		if (callinHasReturnValue) {
			lg = enhancedMethod.addLocalVariable("_OT$tmpResult", returnType,
												 null, null);
			localResult = lg.getIndex();
			il.append(InstructionFactory.createNull (returnType));
			il.append(InstructionFactory.createStore(returnType, localResult));
		}
		
				// ---- Prepare the switch: ----
        InstructionHandle switchStart = il.append
			(InstructionFactory.createLoad(Type.INT, BASE_METH_ARG));
		// generated: _OT$baseMethTag
		
        removeDuplicatedBaseMethodTags(mbs);
        
        // one break for each case clause
        int numberOfCases = mbs.size();
        GOTO[] breaks = new GOTO[numberOfCases];
        for (int i=0; i<numberOfCases; i++)
            breaks[i] = new GOTO(null);

        int[]               matches = new int[numberOfCases];
        InstructionHandle[] targets = new InstructionHandle[numberOfCases];
		int caseCounter = 0;

		Iterator<MethodBinding> it = mbs.iterator();
		while (it.hasNext()) {

			MethodBinding mb = it.next();

			String wrapperName  = mb.getWrapperName();
			int[] paramPositions = CallinBindingManager.getParamPositions(outerClass.getClassName(),
																	wrapperName);
            if (logging) printLogMessage("param pos(" + wrapperName + ")=" + paramPositions);
			
            matches[caseCounter] = CallinBindingManager.getBaseCallTag(mb.getBaseClassName(),
            														   mb.getBaseMethodName(),
            														   mb.getBaseMethodSignature());
            InstructionHandle nextBranch = il.append(new NOP());

            short invocationKind = isSuperAccess 
            						? Constants.INVOKESTATIC
					   				: Constants.INVOKEVIRTUAL;
            
            String boundBaseClassName 		 = mb.getBaseClassName();
            if (boundBaseClassName.indexOf(OTDT_PREFIX) != -1) {
            	// if base is a role class, switch now to the interface part to support base-side implicit inheritance:
				boundBaseClassName = ObjectTeamsTransformation.genRoleInterfaceName(boundBaseClassName);
				invocationKind = Constants.INVOKEINTERFACE;
			}
			String baseMethodName            = mb.getBaseMethodName();
			String baseMethodSignature       = mb.getBaseMethodSignature();
			Type[] baseMethodArgumentTypes   = Type.getArgumentTypes(baseMethodSignature);
			Type   baseMethodReturnType      = Type.getReturnType   (baseMethodSignature);
			
			String baseChainMethodName;
			Type   baseChainReturnType;
			Type[] enhancedBaseArgumentTypes;
			if (isSuperAccess) {
				baseChainMethodName 		 = OT_PREFIX+baseMethodName+"$super";
				baseChainReturnType          = returnType;
				// base arguments are un-enhanced but have a leading base instance:
				int len = baseMethodArgumentTypes.length;
				System.arraycopy(baseMethodArgumentTypes, 0, enhancedBaseArgumentTypes=new Type[len+1], 1, len);  
				enhancedBaseArgumentTypes[0] = baseClass; 
			} else {
				baseChainMethodName          = genChainMethName(baseMethodName);
				baseChainReturnType          = object; // ALWAYS
				enhancedBaseArgumentTypes    = enhanceArgumentTypes(baseMethodArgumentTypes);
			}
			
			// --- call target: ---

			// if base class type is a role type _OT$base field has role interface type:
			{
				String baseClassName = baseClass.toString();
				if (baseClassName.indexOf(OTDT_PREFIX) != -1) {
					baseClass = new ObjectType(ObjectTeamsTransformation.genRoleInterfaceName(baseClassName));
					if(logging) printLogMessage(baseClassName + " --> " + ObjectTeamsTransformation.genRoleInterfaceName(baseClassName));
				}
			}

			// load '_OT$base' field:
			InstructionHandle baseCallLine = il.append(InstructionFactory.createThis());
			il.append(factory.createFieldAccess(className, BASE, baseClass, Constants.GETFIELD));
			
			if (!baseClass.getClassName().equals(boundBaseClassName)) {
				// playedBy has been refined in the sub role;
				// create a cast to the sub base class:
				il.append(factory.createCast(baseClass, new ObjectType(boundBaseClassName)));
			}
			
			// --- load arguments of the new method: ---
			//     (letters refer to document parameter-passing.odg)
			
			// (u) generate extra arguments (indices are equal at role and base):
			if (!isSuperAccess)
				for (int idx = 0; idx < EXTRA_ARGS; idx++) 
					il.append(InstructionFactory.createLoad(enhancedMethod.getArgumentTypes()[idx], 
													        idx+1/*translating non-static*/));		
			
			// (v)(w)(x) split loading sequence and transfer source-level arguments
			// (includes reverse-application of parameter mappings):

			// Start at EXTRA_ARGS, because one set of enhancement has already been loaded,
			// except when doing super access which only has one extra arg: base instance.
			int start = isSuperAccess ? 1 : EXTRA_ARGS; 
			il.append(translateLoads(splitLoading(cpg,
											      loading.copy(),
												  roleArgumentTypes), 
									 enhancedMethod.getArgumentTypes(), 
									 enhancedBaseArgumentTypes, 
									 paramPositions,
									 extractTeamName(enhancedMethod.getClassName()), 
									 className,
									 new BaseMethodInfo(mb.baseMethodIsCallin(), false/*static*/, mb.getTranslationFlags()),
									 start,
									 cpg));
			// --- done loading ---									 

			// invoke the chaining method of the base class (base-call!):
			il.append(factory.createInvoke(boundBaseClassName,
										   baseChainMethodName,
										   baseChainReturnType,
										   enhancedBaseArgumentTypes,
										   invocationKind
										   ));
										   
			boolean resultLiftingNecessary = ((mb.getTranslationFlags()&1)!=0);
			
			if (resultLiftingNecessary) { // call the lift-method:
				// STATIC_PARTS_OK: in role: lift method call
				String liftMethodName = mb.getLiftMethodName();
				Type liftMethodReturnType = Type.getReturnType(mb.getLiftMethodSignature());
				Type[] liftMethodArgs = Type.getArgumentTypes(mb.getLiftMethodSignature());
				
				il.append(factory.createCast(baseChainReturnType, baseMethodReturnType));
                
				// determine receiver for lift-call:
                ObjectType liftType = (ObjectType)((liftMethodReturnType instanceof ArrayType)
			                						? ((ArrayType) liftMethodReturnType).getBasicType()
			                						: liftMethodReturnType);
                int liftedDepth = countOccurrences(liftType.getClassName(), '$');
                int thisNestingDepth = countOccurrences(className, '$');
                ObjectType liftReceiverType = outerClass; // default;
                if (liftedDepth == thisNestingDepth) {
                	// normal case: liftedType is at the same nesting level as "this" 
                	il.append(InstructionFactory.createThis());
                	il.append(factory.createGetField(className, "this$" + (thisNestingDepth-1), outerClass)); // access enclosing team-this
                } else if (liftedDepth == thisNestingDepth+1){
                	// current role is already the team containing the role to get
                	liftReceiverType = new ObjectType(className);
                	il.append(new ALOAD(0));
                } else {
                	throw new OTREInternalError("Mismatching nesting levels for lift-call in base-call-surrogate: "+thisNestingDepth+" vs. "+liftedDepth);
                }

                il.append(new SWAP()); // -> .., liftReceiver, (BaseType)result
				
				il.append(factory.createInvoke(liftReceiverType.getClassName(),
											   liftMethodName,
											   liftMethodReturnType,
											   liftMethodArgs,
											   Constants.INVOKEVIRTUAL));
			}
			
			InstructionHandle afterBaseCallLine = il.append(new NOP());
			
			if (baseChainReturnType != Type.VOID) {
				// adjust the return value to the type expected by the WRAPPER:
				il.append(new DUP()); // keep for adjustment below
				if (!resultLiftingNecessary)
					adjustValue(il, null, baseChainReturnType, enhancedMethodReturnType);
				il.append(InstructionFactory.createStore(enhancedMethodReturnType,
						otResult.getIndex())); // store "globally"
				// this store is needed to tunnel unused results through the callin.

				// adjust the return value to the type expected by the ORIGINAL CALLIN:
				adjustValue(il, null,  baseChainReturnType, returnType);
				if (callinHasReturnValue)
					il.append(InstructionFactory.createStore(returnType, localResult)); // store "locally"
	 			    // this store is useful for callins which make use of the result.
			}  
		
            targets[caseCounter] = nextBranch;
            il.append(breaks[caseCounter]);
            // generated: break;

            caseCounter++;
            
            if (debugging) {
            	enhancedMethod.addLineNumber(baseCallLine, STEP_INTO_LINENUMBER);
            	enhancedMethod.addLineNumber(afterBaseCallLine, STEP_OVER_LINENUMBER);
            }
		}
		// Default case: throw an exception reporting the situation:
		// create: String msg = ("Unhandled base-call case!"+base_method_tag)
		InstructionList messagePush = new InstructionList();
		messagePush.append(factory.createNew(OTConstants.STRING_BUFFER_NAME));
		messagePush.append(new DUP());
		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, Constants.CONSTRUCTOR_NAME, Type.VOID, new Type[0], Constants.INVOKESPECIAL));
		messagePush.append(new PUSH(cpg, "Unhandled base-call case: "));
		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "append", Type.STRINGBUFFER, new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL));
		messagePush.append(InstructionFactory.createLoad(Type.INT, BASE_METH_ARG));
		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "append", Type.STRINGBUFFER, new Type[]{Type.INT}, Constants.INVOKEVIRTUAL));
		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "toString", Type.STRING, new Type[0], Constants.INVOKEVIRTUAL));
		// create: throw new OTREInternalError(msg)
		InstructionHandle defaultCase = createThrowInternalError(cpg, il, messagePush);
		
        InstructionHandle afterSwitch = il.append(new NOP()); // all breaks point here.

		il.append(switchStart, createLookupSwitch(matches, targets, breaks,
												  defaultCase, afterSwitch));

		// retrieve locally stored result:
		if (callinHasReturnValue) {
			il.append(InstructionFactory.createLoad(returnType, localResult));
			lg.setStart(il.getStart()); // restrict local variable to this segment.
			lg.setEnd(il.getEnd());
		}

        return il;
	}

	/**
	 * Removes duplicated method bindings with the same base call tag from the list, to avoid duplicated 
	 * cases in the base call surrogate-switch.
	 * @param mbs
	 */
	private static void removeDuplicatedBaseMethodTags(List<MethodBinding> mbs) {
		if (mbs.size() < 2) // nothing to remove
			return;
		
		MethodBinding[] mbArray = mbs.toArray(new MethodBinding[mbs.size()]);
		
		Comparator<MethodBinding> baseCallTagComparator = new Comparator<MethodBinding>() {
			public int compare(MethodBinding firstMB, MethodBinding secondMB) {
				int firstBaseTag = CallinBindingManager.getBaseCallTag(firstMB.getBaseClassName(), 
																	   firstMB.getBaseMethodName(), 
																	   firstMB.getBaseMethodSignature());
				int secondBaseTag = CallinBindingManager.getBaseCallTag(secondMB.getBaseClassName(), 
						   											    secondMB.getBaseMethodName(), 
						   											    secondMB.getBaseMethodSignature());
				
				if (firstBaseTag < secondBaseTag)
					return -1;
				if (firstBaseTag > secondBaseTag)
					return 1;
				return 0;
			}
		};
		Arrays.sort(mbArray, baseCallTagComparator);
		for (int i = 0; i + 1 < mbArray.length; i++) {
			if (baseCallTagComparator.compare(mbArray[i], mbArray[i + 1]) == 0) {
				mbs.remove(mbArray[i + 1]);
			}
		}
	}


	/**
	 * @param className
	 * @return
	 */
	private static String extractTeamName(String roleClassName) {
		int lastDollarIndex = roleClassName.lastIndexOf('$');
		return roleClassName.substring(0, lastDollarIndex);
	}
	
	/** 
	 * @param className
	 * @return
	 */
	private static String extractRoleName(String roleClassName) {
		int lastDollarIndex = roleClassName.lastIndexOf('$');
		return roleClassName.substring(lastDollarIndex+1, roleClassName.length());
	}

	/**
	 * FIXME(SH): obsolete!
	 * @param baseMethodReturnType
	 * @param returnType
	 * @return
	 */
//	private static boolean returnTypeCompatible(Type from, Type to) {
//		System.out.println("test for " + from + "->" + to);
//		if (from.equals(to))
//			return true;
//		if (from instanceof ObjectType && to instanceof ObjectType) {// how to handle compatible basic types??
//			ObjectType otFrom = (ObjectType) from;
//			ObjectType otTo = (ObjectType) to;
//			if (otFrom.subclassOf(otTo))
//				return true;	
//		}
//		return false;
//	}

	/**
	 *	Copy all exception handlers of a method.
	 *  @param source the method from where to copy
	 *  @param dest the method where to copy to
	 *  @param il instructions of `dest' which must still have the same positions
	 *            as the instructions in `source'.
	 *  @return an array of handler generators, which still has to be maintained,
	 *     whenever instructions are replaced in the methods instruction list.
	 */
	static CodeExceptionGen[] copyExceptionHandlers(MethodGen source,
											 MethodGen dest,
											 InstructionList il) {
		il.setPositions(); // needed to retrieve handles by position.
		CodeExceptionGen[] excGens = source.getExceptionHandlers();
		CodeExceptionGen[] newGens = new CodeExceptionGen[excGens.length];
		if ((excGens != null) && excGens.length > 0) {
			for (int hcount=0; hcount<excGens.length; hcount++) {
				CodeExceptionGen excGen = excGens[hcount];
				InstructionHandle excStart   = il.findHandle(excGen.getStartPC().getPosition());
				InstructionHandle excEnd     = il.findHandle(excGen.getEndPC().getPosition());
				InstructionHandle excHandler = il.findHandle(excGen.getHandlerPC().getPosition());
				ObjectType catchType =  excGen.getCatchType();
				newGens[hcount] =
					dest.addExceptionHandler(excStart, excEnd, excHandler, catchType);
			}
		}
		return newGens;
	}

	/**
	 *  Update the positions of all exception handlers.
	 *  @param handlers the handlers of this method.
	 *  @param replaced a pair of InstructionHandles, the first is replaced by the second.
	 */
	static void updateHandlers (CodeExceptionGen[] handlers, IHPair replaced) {
		InstructionHandle old = replaced.fst();
		InstructionHandle neu = replaced.snd();
		for (int i=0; i<handlers.length; i++) {
            // System.out.println("handler "+handlers[i]);
			if (handlers[i].containsTarget(old) && (old != neu)) {
                // System.out.println("update "+old+"->"+neu);
				handlers[i].updateTarget(old, neu);
			}
		}
	}

	/**
	 * Delete a range of instructions, whithout throwing TargetLostException.
	 * @param il the list to delete from
	 * @param start handle to first instruction to delete.
	 * @param end handle to last instruction to delete.
	 * @param collect a set of InstructionHandle which are still targeted.
	 */
	static void safeDelete(InstructionList il,
					InstructionHandle start, InstructionHandle end,
					HashSet<InstructionHandle> collect)
	{
		try {
			il.delete(start, end);
		} catch(TargetLostException e) {
			//	System.out.print("Loosing:"+e+" ");
			InstructionHandle [] targets = e.getTargets();
			for (int tcount = 0; tcount < targets.length; tcount++) {
				collect.add(targets[tcount]);
				// System.out.println(targets[tcount]+"!!");
			}
		}
	}

	/**
	 *  Update all exceptions handlers with respect to all instructions that were replaced.
	 *  Check that this covers all instruction handles in 'lost'.
	 *  @param handles the exception handlers of this method.
	 *  @param replacedList list of IHPairs describing what has been modified.
	 *  @param lost set of instruction handles that were still referred to when
	 *    they were deleted. All these handles should be updated.
	 */
	static void checkUpdate(CodeExceptionGen[] handlers, ArrayList<IHPair> replacedList, HashSet<InstructionHandle> lost) {
        // System.out.println("Update "+replacedList+"/"+lost);
		Iterator<IHPair> iter = replacedList.iterator();
		while (iter.hasNext()) {
			IHPair replaced = iter.next();
			updateHandlers(handlers, replaced);
			lost.remove(replaced.fst());
		}
		if (!lost.isEmpty()) {
			System.err.println("Warning: "+lost.size()+" target(s) lost: ");
			Iterator<InstructionHandle> it = lost.iterator();
			while (it.hasNext())
				System.out.println(it.next());
		}
	}

	/**
	 * While adding extra args to an activate call:
	 * <ul>
	 *   <li>Check whether an activationLevel was passed (single argument)
	 *   <li>if so, insert the loading sequence for that expression.
	 *   <li>also the return differs (void or int), should however be
	 *      consistent between plain and enhanced version.
	 *   <li>decrement "idx" so this team is the currently active in the chain.
	 * </ul>
	 * @param factory
	 * @param cpg
	 * @param loading sequence, which loads "level" argument, else null.
	 * @param iv the invokevirtual for "activate", used to inspect the
	 *   original signature.
	 * @return the full sequence for loading the arguments, but not the
	 *   call target (because that's the enclosing team and is kept
	 *   unmodified in the original instruction list).
	 */
//    static InstructionList enhanceActivateCall (final InstructionFactory factory,
//										 ConstantPoolGen cpg,
//										 InstructionList loading,
//										 INVOKEVIRTUAL iv) {
//        InstructionList changedArea = new InstructionList();
//
//        // load arguments of the new method:
//        int index = 1;
//        Type[] enhancedArgumentTypes = enhanceArgumentTypes(iv.getArgumentTypes(cpg),
//															0, false, false);
//		Type returnType = Type.VOID;
//		int kount = enhancedArgumentTypes.length;
//		if (iv.getArgumentTypes(cpg).length == 1) {
//			kount--; // "level" loaded separately via 'loading'
//			returnType = Type.INT;
//		}
//
//        for (int k=0; k<kount; k++) {
//            changedArea.append(InstructionFactory.createLoad(enhancedArgumentTypes[k], index));
//            index += enhancedArgumentTypes[k].getSize();
//        }
//		if (loading != null)
//			changedArea.append(loading);
//
//        // invoke the overloaded activate method:
//        changedArea.append(factory.createInvoke("org.objectteams.Team",
//                                                "activate",
//                                                returnType,
//                                                enhancedArgumentTypes,
//                                                Constants.INVOKEVIRTUAL));
//
//        // generate: idx--;
//        changedArea.append(InstructionFactory.createLoad(Type.INT, IDX_ARG));
//        changedArea.append(new ICONST(1));
//        changedArea.append(new ISUB());
//        changedArea.append(InstructionFactory.createStore(Type.INT, IDX_ARG));
//        
//        return changedArea;
//    }

	/**
	 * Generates the instructions to call the enhanced version of the 'super' respectively 'tsuper'
	 * call in a role method.
	 * @param cpg						the constant pool
	 * @param ii							the original invoke instruction
	 * @param enhancedMethod	the enhanced role method
	 * @param loading					the originally loaded arguments 
	 * @return	the instruction list containing the method call ingredients							
	 */
	@SuppressWarnings("deprecation") // ii.getClassName() is deprecated 
	InstructionList genEnhancedSuperCall(ConstantPoolGen cpg, InvokeInstruction ii,
										   MethodGen enhancedMethod, InstructionList loading)
	{
		Type returnType = enhancedMethod.getReturnType();
		//Type[] argTypes = enhancedMethod.getArgumentTypes();
		Type[] argTypes = enhanceArgumentTypes(ii.getArgumentTypes(cpg));
		InstructionList il = new InstructionList();

		il.append(InstructionFactory.createThis());
		// load all additional arguments of the enhanced method (first EXTRA_ARGS):
		int index = 1;
		for (int i=0; i<EXTRA_ARGS; i++) {
			il.append(InstructionFactory.createLoad(argTypes[i],index));
			index += argTypes[i].getSize();
		}
		// load arguments of the originally call:
		il.append(loading);

		// call super.<enhancedMethod>:
		short kind=0;
		if (ii instanceof INVOKESPECIAL)
			kind = Constants.INVOKESPECIAL;
		else
			kind = Constants.INVOKEVIRTUAL;

		il.append(factory.createInvoke(ii.getClassName(cpg), // deprecated but we're safe because we have not array here (super/tsuper call)
													 	ii.getMethodName(cpg),
												  	 	returnType,
														argTypes,
													 	kind));
			return il;
	}

	/**
	 * Generates the instructions to call the base call surrogate method.
	 * @param cpg						the constant pool
	 * @param iv							the original invoke instruction
	 * @param enhancedMethod	the enhanced role method
	 * @param loading					the originally loaded arguments 
	 * @return	the instruction list containing the method call ingredients		
	 */
	@SuppressWarnings("deprecation") // iv.getClassName is deprecated
	InstructionList genBaseCallSurrogateCall(ConstantPoolGen cpg, InvokeInstruction/*INVOKEVIRTUAL*/ iv,
											   MethodGen enhancedMethod, InstructionList loading, 
											   String roleClassName, String calleeClassName) //JU: added String roleClassName and teamClassName to the method signature
	{
		int indexOffset = enhancedMethod.isStatic()?-1:0; // argument indexes are decremented for static methods, 
																								// because of the missing 'this' 
		// for static methods callee is 'null' -> substitute by current class (JU)
		if(calleeClassName == null) {
			calleeClassName = iv.getClassName(cpg); // deprecated but we're safe because we have not array here (activate() call)
		}
		
		Type returnType = enhancedMethod.getReturnType();
		//Type[] argTypes = enhancedMethod.getArgumentTypes();
		Type[] argTypes = enhanceArgumentTypes(iv.getArgumentTypes(cpg));
		InstructionList il = new InstructionList();

		String methodName = getBaseCallSurrogateName(enhancedMethod.getName(), 
													 enhancedMethod.isStatic(),
													 roleClassName);
		short invokeKind;
				
		if (!enhancedMethod.isStatic()) {
			il.append(InstructionFactory.createThis());
			invokeKind = Constants.INVOKEVIRTUAL;
		
		} else { // role method is static: 
			invokeKind = Constants.INVOKESTATIC;
		}
			
		// load all additional arguments of the enhanced method (first EXTRA_ARGS):
		int index = 1;
		for (int i = 0; i < argTypes.length; i++) {
			if(i < EXTRA_ARGS){ // skip original arguments
				il.append(InstructionFactory.createLoad(argTypes[i], index+indexOffset));
			}
			//calculate the next index
			index += argTypes[i].getSize();
		}
		// load arguments of the originally call:
		il.append(loading);
			
		// call _OT$<enhancedMethod>$base():
		il.append(factory.createInvoke(calleeClassName,
													 methodName,
													 returnType,
													 argTypes,
													 invokeKind/*Constants.INVOKEVIRTUAL*/));
		return il;
	}
 
 		
	/**
	   * Checks, if a given instuction is a super or a tsuper call 
	   * @param instr					the instruction to check
	   * @param method_name	the name of the method from wich the 'inst' came
	   * @param cpg					the constant pool
	   * @return							true, if 'inst' is a super or tsuper call
	   */
	private static boolean super_or_tsuper_instruction(Instruction instr, String method_name, ConstantPoolGen cpg) {
		if (isTSuperCall(instr, method_name, cpg))
			return true;
		if (isSuperCall(instr, method_name, cpg))
			return true;
		return false;
	}   

	private static boolean isTSuperCall(Instruction instr, String method_name, ConstantPoolGen cpg) {
		if (instr instanceof INVOKEVIRTUAL) {
			INVOKEVIRTUAL iv = (INVOKEVIRTUAL)instr;
			String iv_name = iv.getName(cpg);
			Type[] argTypes = iv.getArgumentTypes(cpg);
			if (argTypes.length<1) // no tsuper marker interface parameter!
				return false;
			String lastArgument = (argTypes[argTypes.length-1]).toString();
			if (iv_name.equals(method_name) && (lastArgument.indexOf(TSUPER_PREFIX)!=-1)) {
				// if iv == <method_name>(..., TSuper__OT__<SuperTeamName>) -->
                if(logging) printLogMessage("tsuper-call to " + iv_name + " has to be enhanced!");
				return true;
			}
		}
		return false;
	}

	private static boolean isSuperCall(Instruction instr, String method_name, ConstantPoolGen cpg) {
		if (instr instanceof INVOKESPECIAL) { 			
			INVOKESPECIAL is = (INVOKESPECIAL)instr;
			String is_name = is.getName(cpg);
			
			if(is_name.equals(method_name)) {
               if(logging) printLogMessage("super-call to " + is_name + " has to be enhanced!");
			   return true;
			}
		}
		return false;
	}
	  
   /**
	* Generates the base call surrogate name for a given method name.
	* @param	method_name the name of the role method
	* @param	staticFlag 
	* @param	roleClassName the name of the role method
	* @return	the base call surrogate name
	*/
	private static String getBaseCallSurrogateName(String method_name, boolean staticFlag, String roleClassName) {
		//JU: for static methods the role class name should be inserted 
		if(staticFlag) {
			return OT_PREFIX+roleClassName+"$"+method_name+"$base";
		}
		return OT_PREFIX+method_name+"$base";
	}
		
   /**
	* Reverts a method name to its original by returning the substring after the last '$'
	* until the end.  
	* @param	method_name method name to be adjusted
	* @return	the original method name
	*/
	private static String revertToOriginalName(String method_name) {
		int p = method_name.lastIndexOf('$');
		return method_name.substring(p + 1);
	}

/*
 * (non-Javadoc)
 * 
 * @see org.eclipse.objectteams.otre.common.ObjectTeamsTransformation#doTransformCode(org.apache.bcel.generic.ClassGen)
 */
    public void doTransformCode(ClassGen cg) {
        // nothing to do
    }
}
