private void Handle(MethodCallEffect methodCall, ExecutionContext executionContext)
        {
            executionContext.MethodCallCount++;
            result.Stat.MethodCallCount++;
            if (methodCall.Signature == taintedCall)
            {
                if (!inputTaintedMode || methodCall.Parameters.Any(slot => slot.IsInput()))
                {
                    // mark returned values as tainted
                    // TODO: ref counter for tainted obj
                    Debug.Assert(methodCall.OutputSlots.Count == 1,
                                 "for current tainted call this value always 1. Need to test other cases.");
                    for (var i = 0; i < methodCall.OutputSlots.Count; i++)
                    {
                        var(id, backwardCallStack) = result.AddTaintedMethodCall(methodCall.Signature,
                                                                                 CallStack);
                        methodCall.OutputSlots[i].MarkTaint(id, backwardCallStack);
                    }
                }
                else if (inputTaintedMode)
                {
                    for (int i = 0; i < methodCall.Parameters.Length; i++)
                    {
                        var parameter = methodCall.Parameters[i];
                        parameter.AddSinkMethod(executionContext.Signature,
                                                CallStack, methodCall.OutputSlots);
                    }
                }

                result.Stat.IgnoredTargetMethodCalls++;
                return;
            }

            var isAnalyzing = IsAnalyzingNeeded(methodCall);

            AddTargetMethodIfNeeded(methodCall, isAnalyzing);
            if (!isAnalyzing)
            {
                return;
            }

            var summary = GetOrCreateSummary(methodCall);

            executionContext.Apply(summary, methodCall.Parameters, result, ReturnValueApplyingMode.Replace, Indent());
        }
        private protected override Summary Analyze(MethodCall methodCall)
        {
            Debug.Assert(methodCall.CallKind == CallKind.Concrete || methodCall.Parameters != null);
            if (methodCall.CallKind == CallKind.Concrete)
            {
                Debug.Assert(methodCall.Definition.HasBody);
                result.Stat.AnalyzedConcreteMethodCount++;
                result.Stat.AnalyzedDifferentConcreteMethods.Add(methodCall.Signature.ToString());
                result.Stat.InstructionCount += (ulong)methodCall.Definition.Body.Instructions.Count;

                var context = new ExecutionContext(
                    CallStack,
                    methodCall.Signature,
                    methodCall.Definition,
                    enableStaticFields,
                    firstExecutionContextCreating);
                if (firstExecutionContextCreating)
                {
                    firstExecutionContextCreating = false;
                }

                result.Stat.StartMethodAnalyzing(methodCall.Signature.ToString());
                BuildExecutionContext(context, methodCall);
                result.Stat.StopMethodAnalyzing(methodCall.Signature.ToString());
                return(context.ToSummary());
            }
            else
            {
                // emulate virtual call
                // TODO: optimize virtual call w/o implMethods?
                result.Stat.AnalyzedVirtualMethodCount++;
                result.Stat.AnalyzedDifferentVirtualMethods.Add(methodCall.Signature.ToString());
                var context = new ExecutionContext(
                    CallStack,
                    methodCall.Signature,
                    methodCall.Definition,
                    enableStaticFields,
                    firstExecutionContextCreating);
                if (firstExecutionContextCreating)
                {
                    firstExecutionContextCreating = false;
                }

                if (methodCall.Definition.HasReturnType)
                {
                    context.Frame.Push(
                        new SymbolicSlot(
                            new SymbolicReference(
                                new MethodReturnSource(methodCall.Definition))));
                }

                var mode = ReturnValueApplyingMode.Replace;

                // execute this one and all overriden methods that have body
                if (methodCall.Definition.HasBody)
                {
                    var summary = GetOrCreateSummary(new MethodCall(
                                                         methodCall.Signature,
                                                         methodCall.Definition,
                                                         null,
                                                         CallKind.Concrete));

                    result.Stat.EmulatedMethodCallCount++;
                    context.Apply(summary, context.Arguments.Slots, result, mode, Indent());
                    mode = ReturnValueApplyingMode.Merge;
                }

                var types           = GetRegisteredTypes(methodCall.Definition.DeclaringType.ScopeType.ToString());
                var implementations = types.Count == 0
                    ? indexDb.GetImplementations(methodCall.Signature, entryPointAssemblyName)
                    : indexDb.GetImplementations(methodCall.Signature, types);

                foreach (var methodDef in implementations)
                {
                    var summary = GetOrCreateSummary(new MethodCall(
                                                         methodDef.CreateMethodUniqueSignature(),
                                                         methodDef,
                                                         null,
                                                         CallKind.Concrete));

                    result.Stat.EmulatedMethodCallCount++;
                    context.Apply(summary, context.Arguments.Slots, result, mode, Indent());
                    mode = ReturnValueApplyingMode.Merge;
                }

                if (mode == ReturnValueApplyingMode.Replace)
                {
                    Debug.Fail("We must call Analyze() only if we have at least one implementation!");
                    return(Summary.Empty);
                }

                // emulate ret opcode
                if (methodCall.Definition.HasReturnType)
                {
                    var value = context.Frame.Pop();
                    if (!Interpreter.IsSimple(methodCall.Definition.ReturnType) &&
                        !value.IsConstAfterSimplification())
                    {
                        context.AddReturnValue(value);
                    }
                }

                return(context.ToSummary());
            }
        }