コード例 #1
0
ファイル: MethodTable.cs プロジェクト: mayuki/Inazuma
        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());
        }
コード例 #2
0
        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);
            }
        }