GetParameters() private method

private GetParameters ( ) : TypeWrapper[]
return TypeWrapper[]
Ejemplo n.º 1
0
 private void AddParameterMetadata(MethodBuilder method, MethodWrapper mw)
 {
     ParameterBuilder[] pbs;
     if((mw.DeclaringType.IsPublic && (mw.IsPublic || mw.IsProtected)) || classLoader.EmitDebugInfo)
     {
         string[] parameterNames = new string[mw.GetParameters().Length];
         GetParameterNamesFromXml(mw.Name, mw.Signature, parameterNames);
         GetParameterNamesFromSig(mw.Signature, parameterNames);
         pbs = GetParameterBuilders(method, parameterNames.Length, parameterNames);
     }
     else
     {
         pbs = GetParameterBuilders(method, mw.GetParameters().Length, null);
     }
     if((mw.Modifiers & Modifiers.VarArgs) != 0 && pbs.Length > 0)
     {
         AttributeHelper.SetParamArrayAttribute(pbs[pbs.Length - 1]);
     }
     AddXmlMapParameterAttributes(method, Name, mw.Name, mw.Signature, ref pbs);
 }
Ejemplo n.º 2
0
			internal InvokeArgsProcessor(MethodWrapper mw, MethodBase method, object original_obj, object[] original_args, [email protected] callerID)
			{
				TypeWrapper[] argTypes = mw.GetParameters();

				if(!mw.IsStatic && method.IsStatic && mw.Name != "<init>")
				{
					// we've been redirected to a static method, so we have to copy the 'obj' into the args
					object[] nargs = new object[original_args.Length + 1];
					nargs[0] = original_obj;
					original_args.CopyTo(nargs, 1);
					this.obj = null;
					this.args = nargs;
					for(int i = 0; i < argTypes.Length; i++)
					{
						if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost)
						{
							object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType);
							argTypes[i].GhostRefField.SetValue(v, args[i + 1]);
							args[i + 1] = v;
						}
					}
				}
				else
				{
					this.obj = original_obj;
					this.args = original_args;
					for(int i = 0; i < argTypes.Length; i++)
					{
						if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost)
						{
							if(this.args == original_args)
							{
								this.args = (object[])args.Clone();
							}
							object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType);
							argTypes[i].GhostRefField.SetValue(v, args[i]);
							this.args[i] = v;
						}
					}
				}

				if(mw.HasCallerID)
				{
					object[] nargs = new object[args.Length + 1];
					Array.Copy(args, nargs, args.Length);
					nargs[args.Length] = callerID;
					args = nargs;
				}
			}
Ejemplo n.º 3
0
			internal BaseFinalMethodWrapper(DotNetTypeWrapper tw, MethodWrapper m)
				: base(tw, m.Name, m.Signature, m.GetMethod(), m.ReturnType, m.GetParameters(), (m.Modifiers & ~Modifiers.Abstract) | Modifiers.Final, MemberFlags.None)
			{
				this.m = m;
			}
		private static bool MatchSignatures(MethodWrapper mw1, MethodWrapper mw2)
		{
			return mw1.ReturnType == mw2.ReturnType
				&& MatchTypes(mw1.GetParameters(), mw2.GetParameters());
		}
		private static bool MatchSignatures(MethodWrapper interfaceMethod, ClassFile.ConstantPoolItemMethodType samMethodType)
		{
			return interfaceMethod.ReturnType == samMethodType.GetRetType()
				&& MatchTypes(interfaceMethod.GetParameters(), samMethodType.GetArgTypes());
		}
		private static void EmitDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters,
			ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, FieldBuilder[] capturedFields)
		{
			MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final);
			if (interfaceMethod.Name != interfaceMethod.RealName)
			{
				tb.DefineMethodOverride(mb, (MethodInfo)interfaceMethod.GetMethod());
			}
			CodeEmitter ilgen = CodeEmitter.Create(mb);
			for (int i = 0; i < capturedFields.Length; i++)
			{
				ilgen.EmitLdarg(0);
				OpCode opc = OpCodes.Ldfld;
				if (i == 0 && args[0].IsGhost)
				{
					switch (implMethod.Kind)
					{
						case ClassFile.RefKind.invokeInterface:
						case ClassFile.RefKind.invokeVirtual:
						case ClassFile.RefKind.invokeSpecial:
							opc = OpCodes.Ldflda;
							break;
					}
				}
				ilgen.Emit(opc, capturedFields[i]);
			}
			for (int i = 0, count = interfaceMethod.GetParameters().Length, k = capturedFields.Length; i < count; i++)
			{
				ilgen.EmitLdarg(i + 1);
				TypeWrapper Ui = interfaceMethod.GetParameters()[i];
				TypeWrapper Ti = instantiatedMethodType.GetArgTypes()[i];
				TypeWrapper Aj = implParameters[i + k];
				if (Ui == PrimitiveTypeWrapper.BYTE)
				{
					ilgen.Emit(OpCodes.Conv_I1);
				}
				if (Ti != Ui)
				{
					if (Ti.IsGhost)
					{
						Ti.EmitConvStackTypeToSignatureType(ilgen, Ui);
					}
					else if (Ui.IsGhost)
					{
						Ui.EmitConvSignatureTypeToStackType(ilgen);
					}
					else
					{
						Ti.EmitCheckcast(ilgen);
					}
				}
				if (Ti != Aj)
				{
					if (Ti.IsPrimitive && !Aj.IsPrimitive)
					{
						Boxer.EmitBox(ilgen, Ti);
					}
					else if (!Ti.IsPrimitive && Aj.IsPrimitive)
					{
						TypeWrapper primitive = GetPrimitiveFromWrapper(Ti);
						Boxer.EmitUnbox(ilgen, primitive, false);
						if (primitive == PrimitiveTypeWrapper.BYTE)
						{
							ilgen.Emit(OpCodes.Conv_I1);
						}
					}
					else if (Aj == PrimitiveTypeWrapper.LONG)
					{
						ilgen.Emit(OpCodes.Conv_I8);
					}
					else if (Aj == PrimitiveTypeWrapper.FLOAT)
					{
						ilgen.Emit(OpCodes.Conv_R4);
					}
					else if (Aj == PrimitiveTypeWrapper.DOUBLE)
					{
						ilgen.Emit(OpCodes.Conv_R8);
					}
				}
			}
			switch (implMethod.Kind)
			{
				case ClassFile.RefKind.invokeVirtual:
				case ClassFile.RefKind.invokeInterface:
					((MethodWrapper)implMethod.Member).EmitCallvirt(ilgen);
					break;
				case ClassFile.RefKind.newInvokeSpecial:
					((MethodWrapper)implMethod.Member).EmitNewobj(ilgen);
					break;
				case ClassFile.RefKind.invokeStatic:
				case ClassFile.RefKind.invokeSpecial:
					((MethodWrapper)implMethod.Member).EmitCall(ilgen);
					break;
				default:
					throw new InvalidOperationException();
			}
			TypeWrapper Ru = interfaceMethod.ReturnType;
			TypeWrapper Ra = GetImplReturnType(implMethod);
			TypeWrapper Rt = instantiatedMethodType.GetRetType();
			if (Ra == PrimitiveTypeWrapper.BYTE)
			{
				ilgen.Emit(OpCodes.Conv_I1);
			}
			if (Ra != Ru)
			{
				if (Ru == PrimitiveTypeWrapper.VOID)
				{
					ilgen.Emit(OpCodes.Pop);
				}
				else if (Ra.IsGhost)
				{
					Ra.EmitConvSignatureTypeToStackType(ilgen);
				}
				else if (Ru.IsGhost)
				{
					Ru.EmitConvStackTypeToSignatureType(ilgen, Ra);
				}
			}
			if (Ra != Rt)
			{
				if (Rt.IsPrimitive)
				{
					if (Rt == PrimitiveTypeWrapper.VOID)
					{
						// already popped
					}
					else if (!Ra.IsPrimitive)
					{
						TypeWrapper primitive = GetPrimitiveFromWrapper(Ra);
						if (primitive != null)
						{
							Boxer.EmitUnbox(ilgen, primitive, false);
						}
						else
						{
							// If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types
							EmitConvertingUnbox(ilgen, Rt);
						}
					}
					else if (Rt == PrimitiveTypeWrapper.LONG)
					{
						ilgen.Emit(OpCodes.Conv_I8);
					}
					else if (Rt == PrimitiveTypeWrapper.FLOAT)
					{
						ilgen.Emit(OpCodes.Conv_R4);
					}
					else if (Rt == PrimitiveTypeWrapper.DOUBLE)
					{
						ilgen.Emit(OpCodes.Conv_R8);
					}
				}
				else if (Ra.IsPrimitive)
				{
					Boxer.EmitBox(ilgen, GetPrimitiveFromWrapper(Rt));
				}
				else
				{
					Rt.EmitCheckcast(ilgen);
				}
			}
			ilgen.EmitTailCallPrevention();
			ilgen.Emit(OpCodes.Ret);
			ilgen.DoEmit();
		}
			internal JsrMethodAnalyzer(MethodWrapper mw, ClassFile classFile, ClassFile.Method method, ClassLoaderWrapper classLoader, InstructionFlags[] flags)
			{
				if (method.VerifyError != null)
				{
					throw new VerifyError(method.VerifyError);
				}

				this.classFile = classFile;
				state = new InstructionState[method.Instructions.Length];
				callsites = new List<int>[method.Instructions.Length];
				returnsites = new List<int>[method.Instructions.Length];

				// because types have to have identity, the subroutine return address types are cached here
				Dictionary<int, SimpleType> returnAddressTypes = new Dictionary<int, SimpleType>();

				try
				{
					// ensure that exception blocks and handlers start and end at instruction boundaries
					for (int i = 0; i < method.ExceptionTable.Length; i++)
					{
						int start = method.ExceptionTable[i].startIndex;
						int end = method.ExceptionTable[i].endIndex;
						int handler = method.ExceptionTable[i].handlerIndex;
						if (start >= end || start == -1 || end == -1 || handler <= 0)
						{
							throw new IndexOutOfRangeException();
						}
					}
				}
				catch (IndexOutOfRangeException)
				{
					throw new ClassFormatError(string.Format("Illegal exception table (class: {0}, method: {1}, signature: {2}", classFile.Name, method.Name, method.Signature));
				}

				// start by computing the initial state, the stack is empty and the locals contain the arguments
				state[0] = new InstructionState(method.MaxLocals, method.MaxStack);
				SimpleType thisType;
				int firstNonArgLocalIndex = 0;
				if (!method.IsStatic)
				{
					thisType = SimpleType.Object;
					state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1);
				}
				else
				{
					thisType = null;
				}
				TypeWrapper[] argTypeWrappers = mw.GetParameters();
				for (int i = 0; i < argTypeWrappers.Length; i++)
				{
					TypeWrapper tw = argTypeWrappers[i];
					SimpleType type;
					if (tw.IsWidePrimitive)
					{
						type = SimpleType.WidePrimitive;
					}
					else if (tw.IsPrimitive)
					{
						type = SimpleType.Primitive;
					}
					else
					{
						type = SimpleType.Object;
					}
					state[0].SetLocalType(firstNonArgLocalIndex++, type, -1);
					if (type.IsWidePrimitive)
					{
						firstNonArgLocalIndex++;
					}
				}
				SimpleType[] argumentsByLocalIndex = new SimpleType[firstNonArgLocalIndex];
				for (int i = 0; i < argumentsByLocalIndex.Length; i++)
				{
					argumentsByLocalIndex[i] = state[0].GetLocalTypeEx(i);
				}
				InstructionState s = state[0].Copy();
				bool done = false;
				ClassFile.Method.Instruction[] instructions = method.Instructions;
				while (!done)
				{
					done = true;
					for (int i = 0; i < instructions.Length; i++)
					{
						if (state[i] != null && state[i].changed)
						{
							try
							{
								//Console.WriteLine(method.Instructions[i].PC + ": " + method.Instructions[i].OpCode.ToString());
								done = false;
								state[i].changed = false;
								// mark the exception handlers reachable from this instruction
								for (int j = 0; j < method.ExceptionTable.Length; j++)
								{
									if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex)
									{
										MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, state[i]);
									}
								}
								state[i].CopyTo(s);
								ClassFile.Method.Instruction instr = instructions[i];
								switch (instr.NormalizedOpCode)
								{
									case NormalizedByteCode.__aload:
										{
											SimpleType type = s.GetLocalType(instr.NormalizedArg1);
											if (type == SimpleType.Invalid || type.IsPrimitive)
											{
												throw new VerifyError("Object reference expected");
											}
											s.PushType(type);
											break;
										}
									case NormalizedByteCode.__astore:
										s.SetLocalType(instr.NormalizedArg1, s.PopObjectType(), i);
										break;
									case NormalizedByteCode.__aconst_null:
										s.PushObject();
										break;
									case NormalizedByteCode.__aaload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushObject();
										break;
									case NormalizedByteCode.__aastore:
										s.PopObjectType();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__baload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__bastore:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__caload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__castore:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__saload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__sastore:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__iaload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__iastore:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__laload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__lastore:
										s.PopWidePrimitive();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__daload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__dastore:
										s.PopWidePrimitive();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__faload:
										s.PopPrimitive();
										s.PopObjectType();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__fastore:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__arraylength:
										s.PopObjectType();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__iconst:
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__if_icmpeq:
									case NormalizedByteCode.__if_icmpne:
									case NormalizedByteCode.__if_icmplt:
									case NormalizedByteCode.__if_icmpge:
									case NormalizedByteCode.__if_icmpgt:
									case NormalizedByteCode.__if_icmple:
										s.PopPrimitive();
										s.PopPrimitive();
										break;
									case NormalizedByteCode.__ifeq:
									case NormalizedByteCode.__ifge:
									case NormalizedByteCode.__ifgt:
									case NormalizedByteCode.__ifle:
									case NormalizedByteCode.__iflt:
									case NormalizedByteCode.__ifne:
										s.PopPrimitive();
										break;
									case NormalizedByteCode.__ifnonnull:
									case NormalizedByteCode.__ifnull:
										s.PopObjectType();
										break;
									case NormalizedByteCode.__if_acmpeq:
									case NormalizedByteCode.__if_acmpne:
										s.PopObjectType();
										s.PopObjectType();
										break;
									case NormalizedByteCode.__getstatic:
										s.PushType(GetFieldref(instr.Arg1).Signature);
										break;
									case NormalizedByteCode.__putstatic:
										s.PopType(GetFieldref(instr.Arg1).Signature);
										break;
									case NormalizedByteCode.__getfield:
										s.PopObjectType();
										s.PushType(GetFieldref(instr.Arg1).Signature);
										break;
									case NormalizedByteCode.__putfield:
										s.PopType(GetFieldref(instr.Arg1).Signature);
										s.PopObjectType();
										break;
									case NormalizedByteCode.__ldc:
										{
											switch (GetConstantPoolConstantType(instr.Arg1))
											{
												case ClassFile.ConstantType.Double:
													s.PushWidePrimitive();
													break;
												case ClassFile.ConstantType.Float:
													s.PushPrimitive();
													break;
												case ClassFile.ConstantType.Integer:
													s.PushPrimitive();
													break;
												case ClassFile.ConstantType.Long:
													s.PushWidePrimitive();
													break;
												case ClassFile.ConstantType.String:
												case ClassFile.ConstantType.Class:
													s.PushObject();
													break;
												default:
													// NOTE this is not a VerifyError, because it cannot happen (unless we have
													// a bug in ClassFile.GetConstantPoolConstantType)
													throw new InvalidOperationException();
											}
											break;
										}
									case NormalizedByteCode.__invokevirtual:
									case NormalizedByteCode.__invokespecial:
									case NormalizedByteCode.__invokeinterface:
									case NormalizedByteCode.__invokestatic:
										{
											ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1);
											s.MultiPopAnyType(cpi.GetArgTypes().Length);
											if (instr.NormalizedOpCode != NormalizedByteCode.__invokestatic)
											{
												s.PopType();
											}
											string sig = cpi.Signature;
											sig = sig.Substring(sig.IndexOf(')') + 1);
											if (sig != "V")
											{
												s.PushType(sig);
											}
											break;
										}
									case NormalizedByteCode.__goto:
										break;
									case NormalizedByteCode.__istore:
										s.PopPrimitive();
										s.SetLocalPrimitive(instr.NormalizedArg1, i);
										break;
									case NormalizedByteCode.__iload:
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__ineg:
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__iadd:
									case NormalizedByteCode.__isub:
									case NormalizedByteCode.__imul:
									case NormalizedByteCode.__idiv:
									case NormalizedByteCode.__irem:
									case NormalizedByteCode.__iand:
									case NormalizedByteCode.__ior:
									case NormalizedByteCode.__ixor:
									case NormalizedByteCode.__ishl:
									case NormalizedByteCode.__ishr:
									case NormalizedByteCode.__iushr:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__lneg:
										s.PopWidePrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__ladd:
									case NormalizedByteCode.__lsub:
									case NormalizedByteCode.__lmul:
									case NormalizedByteCode.__ldiv:
									case NormalizedByteCode.__lrem:
									case NormalizedByteCode.__land:
									case NormalizedByteCode.__lor:
									case NormalizedByteCode.__lxor:
										s.PopWidePrimitive();
										s.PopWidePrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__lshl:
									case NormalizedByteCode.__lshr:
									case NormalizedByteCode.__lushr:
										s.PopPrimitive();
										s.PopWidePrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__fneg:
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__fadd:
									case NormalizedByteCode.__fsub:
									case NormalizedByteCode.__fmul:
									case NormalizedByteCode.__fdiv:
									case NormalizedByteCode.__frem:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__dneg:
										s.PopWidePrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__dadd:
									case NormalizedByteCode.__dsub:
									case NormalizedByteCode.__dmul:
									case NormalizedByteCode.__ddiv:
									case NormalizedByteCode.__drem:
										s.PopWidePrimitive();
										s.PopWidePrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__new:
										s.PushObject();
										break;
									case NormalizedByteCode.__multianewarray:
										{
											if (instr.Arg2 < 1)
											{
												throw new VerifyError("Illegal dimension argument");
											}
											for (int j = 0; j < instr.Arg2; j++)
											{
												s.PopPrimitive();
											}
											s.PushObject();
											break;
										}
									case NormalizedByteCode.__anewarray:
										s.PopPrimitive();
										s.PushObject();
										break;
									case NormalizedByteCode.__newarray:
										s.PopPrimitive();
										s.PushObject();
										break;
									case NormalizedByteCode.__swap:
										{
											SimpleType t1 = s.PopType();
											SimpleType t2 = s.PopType();
											s.PushType(t1);
											s.PushType(t2);
											break;
										}
									case NormalizedByteCode.__dup:
										{
											SimpleType t = s.PopType();
											s.PushType(t);
											s.PushType(t);
											break;
										}
									case NormalizedByteCode.__dup2:
										{
											SimpleType t = s.PopAnyType();
											if (t.IsWidePrimitive)
											{
												s.PushType(t);
												s.PushType(t);
											}
											else
											{
												SimpleType t2 = s.PopType();
												s.PushType(t2);
												s.PushType(t);
												s.PushType(t2);
												s.PushType(t);
											}
											break;
										}
									case NormalizedByteCode.__dup_x1:
										{
											SimpleType value1 = s.PopType();
											SimpleType value2 = s.PopType();
											s.PushType(value1);
											s.PushType(value2);
											s.PushType(value1);
											break;
										}
									case NormalizedByteCode.__dup2_x1:
										{
											SimpleType value1 = s.PopAnyType();
											if (value1.IsWidePrimitive)
											{
												SimpleType value2 = s.PopType();
												s.PushType(value1);
												s.PushType(value2);
												s.PushType(value1);
											}
											else
											{
												SimpleType value2 = s.PopType();
												SimpleType value3 = s.PopType();
												s.PushType(value2);
												s.PushType(value1);
												s.PushType(value3);
												s.PushType(value2);
												s.PushType(value1);
											}
											break;
										}
									case NormalizedByteCode.__dup_x2:
										{
											SimpleType value1 = s.PopType();
											SimpleType value2 = s.PopAnyType();
											if (value2.IsWidePrimitive)
											{
												s.PushType(value1);
												s.PushType(value2);
												s.PushType(value1);
											}
											else
											{
												SimpleType value3 = s.PopType();
												s.PushType(value1);
												s.PushType(value3);
												s.PushType(value2);
												s.PushType(value1);
											}
											break;
										}
									case NormalizedByteCode.__dup2_x2:
										{
											SimpleType value1 = s.PopAnyType();
											if (value1.IsWidePrimitive)
											{
												SimpleType value2 = s.PopAnyType();
												if (value2.IsWidePrimitive)
												{
													// Form 4
													s.PushType(value1);
													s.PushType(value2);
													s.PushType(value1);
												}
												else
												{
													// Form 2
													SimpleType value3 = s.PopType();
													s.PushType(value1);
													s.PushType(value3);
													s.PushType(value2);
													s.PushType(value1);
												}
											}
											else
											{
												SimpleType value2 = s.PopType();
												SimpleType value3 = s.PopAnyType();
												if (value3.IsWidePrimitive)
												{
													// Form 3
													s.PushType(value2);
													s.PushType(value1);
													s.PushType(value3);
													s.PushType(value2);
													s.PushType(value1);
												}
												else
												{
													// Form 4
													SimpleType value4 = s.PopType();
													s.PushType(value2);
													s.PushType(value1);
													s.PushType(value4);
													s.PushType(value3);
													s.PushType(value2);
													s.PushType(value1);
												}
											}
											break;
										}
									case NormalizedByteCode.__pop:
										s.PopType();
										break;
									case NormalizedByteCode.__pop2:
										{
											SimpleType type = s.PopAnyType();
											if (!type.IsWidePrimitive)
											{
												s.PopType();
											}
											break;
										}
									case NormalizedByteCode.__monitorenter:
									case NormalizedByteCode.__monitorexit:
										s.PopObjectType();
										break;
									case NormalizedByteCode.__return:
										break;
									case NormalizedByteCode.__areturn:
										s.PopObjectType();
										break;
									case NormalizedByteCode.__ireturn:
										s.PopPrimitive();
										break;
									case NormalizedByteCode.__lreturn:
										s.PopWidePrimitive();
										break;
									case NormalizedByteCode.__freturn:
										s.PopPrimitive();
										break;
									case NormalizedByteCode.__dreturn:
										s.PopWidePrimitive();
										break;
									case NormalizedByteCode.__fload:
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__fstore:
										s.PopPrimitive();
										s.SetLocalPrimitive(instr.NormalizedArg1, i);
										break;
									case NormalizedByteCode.__dload:
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__dstore:
										s.PopWidePrimitive();
										s.SetLocalWidePrimitive(instr.NormalizedArg1, i);
										break;
									case NormalizedByteCode.__lload:
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__lstore:
										s.PopWidePrimitive();
										s.SetLocalWidePrimitive(instr.NormalizedArg1, i);
										break;
									case NormalizedByteCode.__lconst_0:
									case NormalizedByteCode.__lconst_1:
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__fconst_0:
									case NormalizedByteCode.__fconst_1:
									case NormalizedByteCode.__fconst_2:
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__dconst_0:
									case NormalizedByteCode.__dconst_1:
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__lcmp:
										s.PopWidePrimitive();
										s.PopWidePrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__fcmpl:
									case NormalizedByteCode.__fcmpg:
										s.PopPrimitive();
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__dcmpl:
									case NormalizedByteCode.__dcmpg:
										s.PopWidePrimitive();
										s.PopWidePrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__checkcast:
										s.PopObjectType();
										s.PushObject();
										break;
									case NormalizedByteCode.__instanceof:
										s.PopObjectType();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__iinc:
										break;
									case NormalizedByteCode.__athrow:
										s.PopObjectType();
										break;
									case NormalizedByteCode.__tableswitch:
									case NormalizedByteCode.__lookupswitch:
										s.PopPrimitive();
										break;
									case NormalizedByteCode.__i2b:
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__i2c:
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__i2s:
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__i2l:
										s.PopPrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__i2f:
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__i2d:
										s.PopPrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__l2i:
										s.PopWidePrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__l2f:
										s.PopWidePrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__l2d:
										s.PopWidePrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__f2i:
										s.PopPrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__f2l:
										s.PopPrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__f2d:
										s.PopPrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__d2i:
										s.PopWidePrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__d2f:
										s.PopWidePrimitive();
										s.PushPrimitive();
										break;
									case NormalizedByteCode.__d2l:
										s.PopWidePrimitive();
										s.PushWidePrimitive();
										break;
									case NormalizedByteCode.__jsr:
										// TODO make sure we're not calling a subroutine we're already in
										break;
									case NormalizedByteCode.__ret:
										{
											// TODO if we're returning from a higher level subroutine, invalidate
											// all the intermediate return addresses
											int subroutineIndex = s.GetLocalRet(instr.Arg1);
											s.CheckSubroutineActive(subroutineIndex);
											break;
										}
									case NormalizedByteCode.__nop:
										if (i + 1 == instructions.Length)
										{
											throw new VerifyError("Falling off the end of the code");
										}
										break;
									case NormalizedByteCode.__invokedynamic:
										// it is impossible to have a valid invokedynamic in a pre-7.0 class file
										throw new VerifyError("Illegal type in constant pool");
									default:
										throw new NotImplementedException(instr.NormalizedOpCode.ToString());
								}
								if (s.GetStackHeight() > method.MaxStack)
								{
									throw new VerifyError("Stack size too large");
								}
								for (int j = 0; j < method.ExceptionTable.Length; j++)
								{
									if (method.ExceptionTable[j].endIndex == i + 1)
									{
										MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, s);
									}
								}
								try
								{
									// another big switch to handle the opcode targets
									switch (instr.NormalizedOpCode)
									{
										case NormalizedByteCode.__tableswitch:
										case NormalizedByteCode.__lookupswitch:
											for (int j = 0; j < instr.SwitchEntryCount; j++)
											{
												state[instr.GetSwitchTargetIndex(j)] += s;
											}
											state[instr.DefaultTarget] += s;
											break;
										case NormalizedByteCode.__ifeq:
										case NormalizedByteCode.__ifne:
										case NormalizedByteCode.__iflt:
										case NormalizedByteCode.__ifge:
										case NormalizedByteCode.__ifgt:
										case NormalizedByteCode.__ifle:
										case NormalizedByteCode.__if_icmpeq:
										case NormalizedByteCode.__if_icmpne:
										case NormalizedByteCode.__if_icmplt:
										case NormalizedByteCode.__if_icmpge:
										case NormalizedByteCode.__if_icmpgt:
										case NormalizedByteCode.__if_icmple:
										case NormalizedByteCode.__if_acmpeq:
										case NormalizedByteCode.__if_acmpne:
										case NormalizedByteCode.__ifnull:
										case NormalizedByteCode.__ifnonnull:
											state[i + 1] += s;
											state[instr.TargetIndex] += s;
											break;
										case NormalizedByteCode.__goto:
											state[instr.TargetIndex] += s;
											break;
										case NormalizedByteCode.__jsr:
											{
												int index = instr.TargetIndex;
												s.SetSubroutineId(index);
												SimpleType retAddressType;
												if (!returnAddressTypes.TryGetValue(index, out retAddressType))
												{
													retAddressType = SimpleType.MakeRet(index);
													returnAddressTypes[index] = retAddressType;
												}
												s.PushType(retAddressType);
												state[index] += s;
												List<int> returns = GetReturnSites(i);
												if (returns != null)
												{
													foreach (int returnIndex in returns)
													{
														state[i + 1] = InstructionState.MergeSubroutineReturn(state[i + 1], s, state[returnIndex], state[returnIndex].GetLocalsModified(index));
													}
												}
												AddCallSite(index, i);
												break;
											}
										case NormalizedByteCode.__ret:
											{
												// HACK if the ret is processed before all of the jsr instructions to this subroutine
												// we wouldn't be able to properly merge, so that is why we track the number of callsites
												// for each subroutine instruction (see Instruction.AddCallSite())
												int subroutineIndex = s.GetLocalRet(instr.Arg1);
												int[] cs = GetCallSites(subroutineIndex);
												bool[] locals_modified = s.GetLocalsModified(subroutineIndex);
												for (int j = 0; j < cs.Length; j++)
												{
													AddReturnSite(cs[j], i);
													state[cs[j] + 1] = InstructionState.MergeSubroutineReturn(state[cs[j] + 1], state[cs[j]], s, locals_modified);
												}
												break;
											}
										case NormalizedByteCode.__ireturn:
										case NormalizedByteCode.__lreturn:
										case NormalizedByteCode.__freturn:
										case NormalizedByteCode.__dreturn:
										case NormalizedByteCode.__areturn:
										case NormalizedByteCode.__return:
										case NormalizedByteCode.__athrow:
											break;
										default:
											state[i + 1] += s;
											break;
									}
								}
								catch (IndexOutOfRangeException)
								{
									// we're going to assume that this always means that we have an invalid branch target
									// NOTE because PcIndexMap returns -1 for illegal PCs (in the middle of an instruction) and
									// we always use that value as an index into the state array, any invalid PC will result
									// in an IndexOutOfRangeException
									throw new VerifyError("Illegal target of jump or branch");
								}
							}
							catch (VerifyError x)
							{
								string opcode = instructions[i].NormalizedOpCode.ToString();
								if (opcode.StartsWith("__"))
								{
									opcode = opcode.Substring(2);
								}
								throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})",
									classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x);
							}
						}
					}
				}

				// Now we do another pass to compute reachability
				done = false;
				flags[0] |= InstructionFlags.Reachable;
				while (!done)
				{
					done = true;
					bool didJsrOrRet = false;
					for (int i = 0; i < instructions.Length; i++)
					{
						if ((flags[i] & (InstructionFlags.Reachable | InstructionFlags.Processed)) == InstructionFlags.Reachable)
						{
							done = false;
							flags[i] |= InstructionFlags.Processed;
							// mark the exception handlers reachable from this instruction
							for (int j = 0; j < method.ExceptionTable.Length; j++)
							{
								if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex)
								{
									flags[method.ExceptionTable[j].handlerIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
								}
							}
							// mark the successor instructions
							switch (instructions[i].NormalizedOpCode)
							{
								case NormalizedByteCode.__tableswitch:
								case NormalizedByteCode.__lookupswitch:
									{
										bool hasbackbranch = false;
										for (int j = 0; j < instructions[i].SwitchEntryCount; j++)
										{
											hasbackbranch |= instructions[i].GetSwitchTargetIndex(j) < i;
											flags[instructions[i].GetSwitchTargetIndex(j)] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
										}
										hasbackbranch |= instructions[i].DefaultTarget < i;
										flags[instructions[i].DefaultTarget] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
										break;
									}
								case NormalizedByteCode.__goto:
									flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
									break;
								case NormalizedByteCode.__ifeq:
								case NormalizedByteCode.__ifne:
								case NormalizedByteCode.__iflt:
								case NormalizedByteCode.__ifge:
								case NormalizedByteCode.__ifgt:
								case NormalizedByteCode.__ifle:
								case NormalizedByteCode.__if_icmpeq:
								case NormalizedByteCode.__if_icmpne:
								case NormalizedByteCode.__if_icmplt:
								case NormalizedByteCode.__if_icmpge:
								case NormalizedByteCode.__if_icmpgt:
								case NormalizedByteCode.__if_icmple:
								case NormalizedByteCode.__if_acmpeq:
								case NormalizedByteCode.__if_acmpne:
								case NormalizedByteCode.__ifnull:
								case NormalizedByteCode.__ifnonnull:
									flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
									flags[i + 1] |= InstructionFlags.Reachable;
									break;
								case NormalizedByteCode.__jsr:
									flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
									// Note that we don't mark the next instruction as reachable,
									// because that depends on the corresponding ret actually being
									// reachable. We handle this in the loop below.
									didJsrOrRet = true;
									break;
								case NormalizedByteCode.__ret:
									// Note that we can't handle ret here, because we might encounter the ret
									// before having seen all the corresponding jsr instructions, so we can't
									// update all the call sites.
									// We handle ret in the loop below.
									didJsrOrRet = true;
									break;
								case NormalizedByteCode.__ireturn:
								case NormalizedByteCode.__lreturn:
								case NormalizedByteCode.__freturn:
								case NormalizedByteCode.__dreturn:
								case NormalizedByteCode.__areturn:
								case NormalizedByteCode.__return:
								case NormalizedByteCode.__athrow:
									break;
								default:
									flags[i + 1] |= InstructionFlags.Reachable;
									break;
							}
						}
					}
					if (didJsrOrRet)
					{
						for (int i = 0; i < instructions.Length; i++)
						{
							if (instructions[i].NormalizedOpCode == NormalizedByteCode.__ret
								&& (flags[i] & InstructionFlags.Reachable) != 0)
							{
								int subroutineIndex = state[i].GetLocalRet(instructions[i].Arg1);
								int[] cs = GetCallSites(subroutineIndex);
								for (int j = 0; j < cs.Length; j++)
								{
									if ((flags[cs[j]] & InstructionFlags.Reachable) != 0)
									{
										flags[cs[j] + 1] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget;
									}
								}
							}
						}
					}
				}
			}