private MethodDesc[] CreateMethodSlotsFromTypeDef(TypeDefinition typeDef) { var methods = new List <MethodDefinition>(); methods.AddRange(GetVirtualMethodDefsFromTypeDef(typeDef)); // virtual methods.AddRange(typeDef.Methods.Where(x => !x.IsVirtual && !x.IsStatic)); // non-virtual methods.AddRange(typeDef.Methods.Where(x => x.IsStatic)); // static return(methods .Select((x, i) => { var methodDesc = _classLoader.LookupMethodDescFromMethodDef(x); if (methodDesc == null) { methodDesc = new MethodDesc() { MdToken = x.MetadataToken, Name = x.FullName, Definition = x, Slot = i }; _classLoader.RegisterMethodDesc(x, methodDesc); } return methodDesc; }) .ToArray()); }
private void DoCallWork(bool virtualCall, ObjectInstance thisArg = null, MethodReference methTok = null, object callInfo = null) { var op = (methTok ?? _instructions[_instructionPtr].Operand) as MethodReference; var methDef = op.Resolve(); { if (methDef.IsInternalCall) { InvokeInternalCall(methDef); return; } } _callThisArg = thisArg; // for .ctor var totalSigArgs = 0; if (false) { } else { totalSigArgs = methDef.Parameters.Count + (methDef.HasThis ? 1 : 0); } // Note that "totalNativeArgs()" includes space for ret buff arg. var nSlots = totalSigArgs + 1; if (methDef.HasGenericParameters) { nSlots++; } if (methDef.IsVarArg()) { nSlots++; } // Make sure that the operand stack has the required number of arguments. // (Note that this is IL args, not native.) // // The total number of arguments on the IL stack. Initially we assume that all the IL arguments // the callee expects are on the stack, but may be adjusted downwards if the "this" argument // is provided by an allocation (the call is to a constructor). var totalArgsOnILStack = totalSigArgs; if (_callThisArg != null) { Debug.Assert(totalArgsOnILStack > 0); totalArgsOnILStack--; } var totalArgs = nSlots; var LOCAL_ARG_SLOTS = 8; var localArgs = new ObjectInstance[(totalArgs > LOCAL_ARG_SLOTS) ? totalArgs : LOCAL_ARG_SLOTS]; // Current on-stack argument index. var arg = 0; // FIXME: stack (mayuki) var tmpArgsStack = _opStack.ToArray(); var curArgSlot = 0; if (methDef.HasThis) { if (_callThisArg != null) { localArgs[curArgSlot] = _callThisArg; } else { localArgs[curArgSlot] = tmpArgsStack[tmpArgsStack.Length - (arg + 1)]; arg++; } curArgSlot++; } // Now we do the non-this arguments. for (; arg < totalArgsOnILStack; arg++) { localArgs[curArgSlot] = tmpArgsStack[tmpArgsStack.Length - (arg + 1)]; curArgSlot++; } if (methDef.HasThis) { if (thisArg == null) { thisArg = tmpArgsStack[0]; } else { thisArg = _callThisArg; } } ObjectInstance retVal; MethodDefinition exactMethToCall = methDef; if (methDef.DeclaringType.IsInterface) { var slot = thisArg.MethodTable.InterfaceMethodSlotMap[methDef]; exactMethToCall = thisArg.MethodTable.MethodSlots[slot].Definition; } else { if (virtualCall && methDef.IsVirtual) { var methodDesc = _classLoader.LookupMethodDescFromMethodDef(methDef); exactMethToCall = thisArg.MethodTable.MethodSlots[methodDesc.Slot].Definition; } } retVal = InterpretMethodBody(exactMethToCall, true, localArgs, null); // retval for (var i = 0; i < totalArgsOnILStack; i++) { _opStack.Pop(); } if (methDef.ReturnType.FullName != "System.Void") // TODO: should refer typevalue enum { _opStack.Push(retVal); } }