Exemplo n.º 1
0
        private void InjectTailCall()
        {
            for (var i = 0; i < IL.Index; i++)
            {
                var instr = IL[i];
                BufferedILInstruction call = null;

                if (instr.IsInstruction == OpCodes.Ret)
                {
                    int callIx = -1;

                    for (var j = i - 1; j >= 0; j--)
                    {
                        var atJ = IL[j];

                        if (atJ.MarksLabel != null)
                        {
                            break;
                        }

                        if (atJ.IsInstruction.HasValue)
                        {
                            if (ExtensionMethods.IsTailableCall(atJ.IsInstruction.Value))
                            {
                                callIx = j;
                                call   = atJ;
                            }

                            break;
                        }
                    }

                    if (callIx == -1)
                    {
                        continue;
                    }
                    if (call.TakesManagedPointer())
                    {
                        continue;
                    }
#if !COREFX // see https://github.com/dotnet/corefx/issues/4543 item 4
                    if (call.TakesTypedReference())
                    {
                        continue;
                    }
#endif
                    if (call.TakesByRefArgs())
                    {
                        continue;
                    }

                    InsertInstruction(callIx, OpCodes.Tailcall);
                    i++;
                }
            }
        }
Exemplo n.º 2
0
        private void InjectTailCall()
        {
            for (var i = 0; i < IL.Index; i++)
            {
                var instr = IL[i];
                BufferedILInstruction call = null;

                if (instr.IsInstruction == OpCodes.Ret)
                {
                    int callIx = -1;

                    for (var j = i - 1; j >= 0; j--)
                    {
                        var atJ = IL[j];

                        if (atJ.MarksLabel != null)
                        {
                            break;
                        }

                        if (atJ.IsInstruction.HasValue)
                        {
                            if (ExtensionMethods.IsTailableCall(atJ.IsInstruction.Value))
                            {
                                callIx = j;
                                call   = atJ;
                            }

                            break;
                        }
                    }

                    if (callIx == -1)
                    {
                        continue;
                    }
                    if (call.TakesManagedPointer())
                    {
                        continue;
                    }
                    // TODO: see https://github.com/dotnet/corefx/issues/4543 item 4
#if !NETSTANDARD
                    if (call.TakesTypedReference())
                    {
                        continue;
                    }
#endif
                    if (call.TakesByRefArgs())
                    {
                        continue;
                    }

                    var callReturns     = call.MethodReturnType;
                    var delegateReturns = ReturnType.Type;

                    // the method's return types not matching
                    //   means we can't just turn the call into a jump
                    //   since _something_ has to preceed or survive the call to
                    //   make the ret legal
                    if (!ExtensionMethods.IsAssignableFrom(delegateReturns, callReturns))
                    {
                        continue;
                    }

                    // there's one case not being handled explicitly here,
                    //   which is the call must consume the _entire_ stack.
                    // we don't have to asset it because the return type
                    //   comparison is sufficient:
                    //     - if the types match, the stack must be empty
                    //         or the following ret will fail to verify (since
                    //         there's an extra item of the corret type on the stack)
                    //     - if the types _don't_ match, we've already bailed on the
                    //         tail injection

                    InsertInstruction(callIx, OpCodes.Tailcall);
                    i++;
                }
            }
        }