private async Task ProcessCalleesAsync(IEnumerable <CallInfo> calleesInfo, PropagationKind propKind) { var tasks = new List <Task>(); foreach (var calleeInfo in calleesInfo) { //TODO: Need to Refactor to get rid of this ifs! if (calleeInfo is MethodCallInfo) { // TODO: This should work in any order because the technique is flow insensitive // But actually for some reason the ordering is affecting the result // I think the problem is the conservative treatment when types(receiver).Count = 0 // (FIXED??) var task = this.DispatchCallMessageForMethodCallAsync(calleeInfo as MethodCallInfo, propKind); //await task; tasks.Add(task); } else if (calleeInfo is DelegateCallInfo) { var task = this.DispatchCallMessageForDelegateCallAsync(calleeInfo as DelegateCallInfo, propKind); //await task; tasks.Add(task); } } await Task.WhenAll(tasks); }
public async Task <PropagationEffects> PropagateAsync(PropagationKind propKind) { await StatsHelper.RegisterMsg("MethodEntityGrain::Propagate", this.GrainFactory); //if (status.Equals(EntityGrainStatus.Busy)) //{ // await Task.Delay(WAIT_TIME); // if (status.Equals(EntityGrainStatus.Busy)) // { // return new PropagationEffects(); // } //} Logger.LogVerbose(this.GetLogger(), "MethodEntityGrain", "Propagate", "Propagation for {0} ", this.methodEntity.MethodDescriptor); var sw = new Stopwatch(); sw.Start(); var propagationEffects = await this.methodEntityPropagator.PropagateAsync(propKind); sw.Stop(); propagationEffects.SiloAddress = StatsHelper.GetMyIPAddr(); Logger.LogInfo(this.GetLogger(), "MethodEntityGrain", "Propagate", "End Propagation for {0}. Time elapsed {1} Effects size: {2}", this.methodEntity.MethodDescriptor, sw.Elapsed, propagationEffects.CalleesInfo.Count); await StatsHelper.RegisterPropagationUpdates(propagationEffects.NumberOfUpdates, propagationEffects.WorkListInitialSize, this.GrainFactory); return(propagationEffects); }
public ReturnMessageInfo(MethodDescriptor caller, MethodDescriptor callee, ISet <TypeDescriptor> resultPossibleTypes, AnalysisCallNode callNode, VariableNode lhs, PropagationKind propKind) { this.Caller = caller; this.Callee = callee; this.LHS = lhs; this.ResultPossibleTypes = resultPossibleTypes; this.PropagationKind = propKind; this.CallNode = callNode; }
private Task CreateAndSendReturnMessageAsync(ReturnInfo returnInfo, PropagationKind propKind) { var returnMessageInfo = new ReturnMessageInfo(returnInfo.CallerContext.Caller, returnInfo.Callee, returnInfo.ResultPossibleTypes, returnInfo.CallerContext.CallNode, returnInfo.CallerContext.LHS, propKind); var source = new MethodEntityDescriptor(returnInfo.Callee); var calleeMessage = new CalleeMessage(source, returnMessageInfo); return(this.AnalyzeReturnAsync(returnMessageInfo.Caller, calleeMessage, propKind)); }
public async Task PropagateAndProcessAsync(PropagationKind propKind, IEnumerable <PropGraphNodeDescriptor> reWorkSet) { await StatsHelper.RegisterMsg("MethodEntityGrain::PropagateAndProcess", this.GrainFactory); var effects = await this.methodEntityPropagator.PropagateAsync(propKind, reWorkSet); // await this.PropagateAsync(propKind, reWorkSet); await StatsHelper.RegisterPropagationUpdates(effects.NumberOfUpdates, effects.WorkListInitialSize, this.GrainFactory); await ProcessEffectsAsync(effects); }
private async Task <PropagationEffects> InternalPropagateAsync(PropagationKind propKind) { //Logger.LogS("MethodEntityProp", "PropagateAsync", "Propagation for {0} ", this.methodEntity.MethodDescriptor); //Logger.Log("Propagating {0} to {1}", this.methodEntity.MethodDescriptor, propKind); // var codeProvider = await ProjectGrainWrapper.CreateProjectGrainWrapperAsync(this.methodEntity.MethodDescriptor); PropagationEffects propagationEffects = null; switch (propKind) { case PropagationKind.ADD_TYPES: propagationEffects = await this.methodEntity.PropGraph.PropagateAsync(codeProvider); break; case PropagationKind.REMOVE_TYPES: propagationEffects = await this.methodEntity.PropGraph.PropagateDeletionAsync(codeProvider); break; default: throw new Exception("Unsupported propagation kind"); } await this.PopulatePropagationEffectsInfo(propagationEffects, propKind); Logger.LogS("MethodEntityGrain", "PropagateAsync", "End Propagation for {0} ", this.methodEntity.MethodDescriptor); //this.methodEntity.Save(@"C:\Temp\"+this.methodEntity.MethodDescriptor.MethodName + @".dot"); //if (propagationEffects.CalleesInfo.Count > 100) //{ // int index = 0; // var count = propagationEffects.CalleesInfo.Count; // var callessInfo = propagationEffects.CalleesInfo.ToList(); // propagationEffects.CalleesInfo = new HashSet<CallInfo>(callessInfo.GetRange(index, count > 100 ? 100 : count)); // propagationEffects.MoreEffectsToFetch = true; // // while (count > 100) // { // count -= 100; // index += 100; // // var propEffect = new PropagationEffects(new HashSet<CallInfo>(callessInfo.GetRange(index, count > 100 ? 100 : count)), false); // // if (count > 100) // { // propEffect.MoreEffectsToFetch = true; // } // // this.propagationEffectsToSend.Enqueue(propEffect); // } //} //this.UpdateHistory.Add(this.methodEntity.PropGraph.UpdateCount); return(propagationEffects); }
internal async Task<bool> DiffPropAsync(IEnumerable<TypeDescriptor> src, PropGraphNodeDescriptor n, PropagationKind propKind) { if (propKind == PropagationKind.REMOVE_TYPES || propKind == PropagationKind.REMOVE_ASSIGNMENT) { return DiffDelProp(src, n); } else { return await DiffPropAsync(src, n); } }
public CallMessageInfo(MethodDescriptor caller, MethodDescriptor callee, TypeDescriptor receiverType, IList <ISet <TypeDescriptor> > argumentsPossibleTypes, AnalysisCallNode callNode, VariableNode lhs, PropagationKind propKind) { this.Caller = caller; this.Callee = callee; this.ArgumentsPossibleTypes = argumentsPossibleTypes; this.ReceiverType = receiverType; this.LHS = lhs; this.PropagationKind = propKind; this.CallNode = callNode; }
private async Task ProcessCalleesAsync(IEnumerable <CallInfo> calleesInfo, PropagationKind propKind) { var tasks = new List <Task>(); foreach (var calleeInfo in calleesInfo) { var task = this.DispatchCallMessageAsync(calleeInfo, propKind); //await task; tasks.Add(task); } await Task.WhenAll(tasks); }
private async Task DispatchCallMessageAsync(CallInfo callInfo, PropagationKind propKind) { var tasks = new List <Task>(); foreach (var callee in callInfo.PossibleCallees) { var task = this.CreateAndSendCallMessageAsync(callInfo, callee, propKind); //await task; tasks.Add(task); } await Task.WhenAll(tasks); }
private ISet <TypeDescriptor> GetTypes(PropGraphNodeDescriptor node, PropagationKind prop) { switch (prop) { case PropagationKind.ADD_TYPES: return(GetTypes(node)); case PropagationKind.REMOVE_TYPES: return(GetDeletedTypes(node)); default: return(GetTypes(node)); } }
public Task <PropagationEffects> PropagateAsync(PropagationKind propKind, IEnumerable <PropGraphNodeDescriptor> reWorkSet) { StatsHelper.RegisterMsg("MethodEntityGrain::PropagateWithRework", this.GrainFactory); //if (status.Equals(EntityGrainStatus.Busy)) //{ // await Task.Delay(WAIT_TIME); // if (status.Equals(EntityGrainStatus.Busy)) // { // return new PropagationEffects(); // } //} return(this.methodEntityPropagator.PropagateAsync(propKind, reWorkSet)); }
private async Task ProcessEffectsAsync(PropagationEffects effects, PropagationKind propKind = PropagationKind.ADD_TYPES) { effects.Kind = propKind; var maxCallSitesCount = Math.Min(effects.CalleesInfo.Count, 8); var maxCallersCount = Math.Min(effects.CallersInfo.Count, 8); // This is an optimization, it is not really needed if (maxCallSitesCount == 0 && maxCallersCount == 0) { return; } await this.SplitAndEnqueueEffectsAsync(effects, maxCallSitesCount, maxCallersCount, int.MaxValue); }
private Task CreateAndSendReturnMessageAsync(ReturnInfo returnInfo, PropagationKind propKind) { var returnMessageInfo = new ReturnMessageInfo(returnInfo.CallerContext.Caller, returnInfo.Callee, returnInfo.ResultPossibleTypes, returnInfo.CallerContext.CallNode, returnInfo.CallerContext.LHS, propKind); var source = new MethodEntityDescriptor(returnInfo.Callee); var calleeMessage = new CalleeMessage(source, returnMessageInfo); //await WaitQueue(QUEUE_THRESHOLD); this.messageWorkList.Enqueue(calleeMessage); //this.messageWorkList.Add(calleeMessage); return(Task.CompletedTask); //return AnalyzeReturnAsync(returnMessageInfo.Caller, calleeMessage, propKind); }
private async Task CreateAndSendReturnMessageAsync(ReturnInfo returnInfo, PropagationKind propKind) { var returnMessageInfo = new ReturnMessageInfo(returnInfo.CallerContext.Caller, returnInfo.Callee, returnInfo.ResultPossibleTypes, returnInfo.CallerContext.CallNode, returnInfo.CallerContext.LHS, propKind); var source = new MethodEntityDescriptor(returnInfo.Callee); var calleeMessage = new CalleeMessage(source, returnMessageInfo); await this.solutionManager.UpdateCounter(1); //await WaitQueue(QUEUE_THRESHOLD); this.messageWorkList.Enqueue(calleeMessage); //this.messageWorkList.Add(calleeMessage); //return TaskDone.Done; }
private async Task ProcessReturnAsync(IEnumerable <ReturnInfo> callersInfo, PropagationKind propKind) { var tasks = new List <Task>(); foreach (var callerInfo in callersInfo) { if (callerInfo.ResultPossibleTypes.Count > 0) { var task = this.DispachReturnMessageAsync(callerInfo, propKind); //await task; tasks.Add(task); } } await Task.WhenAll(tasks); }
public Task <PropagationEffects> PropagateAsync(PropagationKind propKind, IEnumerable <PropGraphNodeDescriptor> reWorkSet) { Contract.Requires(reWorkSet != null); switch (propKind) { case PropagationKind.ADD_TYPES: methodEntity.PropGraph.AddToWorkList(reWorkSet); break; case PropagationKind.REMOVE_TYPES: methodEntity.PropGraph.AddToDeletionWorkList(reWorkSet); break; default: throw new Exception("Unsupported propagation kind"); } return(PropagateAsync(propKind)); }
private async Task ProcessCalleesAsync(IEnumerable <CallInfo> calleesInfo, PropagationKind propKind) { var tasks = new List <Task>(); foreach (var calleeInfo in calleesInfo) { //TODO: Need to Refactor to get rid of this ifs! if (calleeInfo is MethodCallInfo) { var task = this.DispatchCallMessageForMethodCallAsync(calleeInfo as MethodCallInfo, propKind); //await task; tasks.Add(task); } else if (calleeInfo is DelegateCallInfo) { var task = this.DispatchCallMessageForDelegateCallAsync(calleeInfo as DelegateCallInfo, propKind); tasks.Add(task); } } await Task.WhenAll(tasks); }
public async Task EndOfPropagationEventAsync(PropagationKind propKind, bool retValueChange) { if (this.Verbose) { Logger.Instance.Log("MethodEntityProcessor", "EndOfPropagationEventAsync", this.MethodEntity.MethodDescriptor); } // Should do something more clever if (retValueChange) { await ProcessReturnNodeAsync(propKind); } }
/// <summary> /// When the method returns I should inform the computed return value to all its caller /// It may also propagate other info from out parameters and escaping objects (not implemented) /// </summary> private void ProcessReturnNode(PropagationKind propKind) { if (this.MethodEntity.ReturnVariable != null) { // Should do the same with out and escaping info foreach (var callerContex in this.MethodEntity.Callers) { DispachReturnMessage(callerContex, this.MethodEntity.ReturnVariable, propKind); } } }
private async Task PropagateFromCallersAsync(IEnumerable <ReturnInfo> callersInfo, PropagationKind propKind = PropagationKind.ADD_TYPES) { var tasks = new List <Task>(); foreach (var callerInfo in callersInfo) { var reworkSet = new HashSet <PropGraphNodeDescriptor>(); var callContext = callerInfo.CallerContext; reworkSet.Add(callContext.CallNode); var task = this.AnalyzeAsync(callContext.Caller, reworkSet, propKind); //await task; tasks.Add(task); } await Task.WhenAll(tasks); }
private async Task AnalyzeCalleeAsync(MethodDescriptor callee, CallerMessage callerMessage, PropagationKind propKind) { Logger.LogS("EffectsDispatcherManager", "AnalyzeCallee", "Analyzing: {0}", callee); //var methodEntityProc = await this.solutionManager.GetMethodEntityAsync(callee); var methodEntityProc = await this.GetMethodEntityGrainAndActivateInProject(callee); await methodEntityProc.PropagateAndProcessAsync(callerMessage.CallMessageInfo); Logger.LogS("EffectsDispatcherManager", "AnalyzeCallee", "End Analyzing call to {0} ", callee); }
internal ISet<TypeDescriptor> GetTypes(PropGraphNodeDescriptor node, PropagationKind prop) { switch (prop) { case PropagationKind.ADD_TYPES: return GetTypes(node); case PropagationKind.REMOVE_TYPES: return GetDeletedTypes(node); default: return GetTypes(node); } }
/// <summary> /// Given an invocations this method dispatch a message to every potential callee to propagate the info in the arguments /// </summary> /// <param name="callInfo"></param> /// <param name="propKind"></param> private void DispatchCallMessage(CallInfo callInfo, PropagationKind propKind) { if (!callInfo.IsStatic && callInfo.Receiver != null) { // I need to computes all the calless // In case of a deletion we can discar the deleted callee //var types = GetTypes(callNode.Receiver, propKind); var types = GetTypes(callInfo.Receiver); /// If types=={} it means that some info ins missing => we should be conservative and use the instantiated types (RTA) if (types.Count() == 0 && propKind != PropagationKind.REMOVE_TYPES) { var instantiatedTypes = new HashSet<TypeDescriptor>(); /// We get the instantiated type that are compatible with the receiver type instantiatedTypes.UnionWith( this.MethodEntity.InstantiatedTypes .Where(type => codeProvider.IsSubtype(type,callInfo.Receiver.Type))); // .Where(type => type.IsSubtype(callInfo.Receiver.Type))); foreach (var type in instantiatedTypes) { types.Add(type); } // TO-DO: SHould I fix the node in the receiver to show that is not loaded? Ideally I should use the declared type. // Here I will use the already instantiated types this.MethodEntity.PropGraph.Add(callInfo.Receiver, types); //var declaredType = callInfo.Receiver.AType; //this.PropGraph.Add(callInfo.Receiver, declaredType); } // Now we compute the potential callees we are going to send the messsages // I need to propagate the change to all potential callees, in particular the change in arguments if (types.Count() > 0) { foreach (var receiverType in types) { // Given a method m and T find the most accurate implementation wrt to T // it can be T.m or the first super class implementing m //var realCallee = callInfo.Callee.FindMethodImplementation(receiverType); var realCallee = codeProvider.FindMethodImplementation(callInfo.Callee,receiverType); CreateAndSendCallMessage( callInfo, realCallee, receiverType, propKind); } } // This is not good: One reason is that loads like b = this.f are not working // in a meth m a after call r.m() because only the value of r is passed and not all its structure else { CreateAndSendCallMessage(callInfo, callInfo.Callee, callInfo.Callee.ContainerType, propKind); } } else { CreateAndSendCallMessage(callInfo, callInfo.Callee, callInfo.Callee.ContainerType, propKind); } }
private void DispatchCallMessageForDelegate(DelegateCallInfo delegateCallInfo, PropagationKind propKind) { foreach (var callee in GetDelegateCallees(delegateCallInfo.CalleeDelegate)) { CreateAndSendCallMessage(delegateCallInfo, callee, callee.ContainerType, propKind); } }
private async Task ProcessCalleesAffectedByPropagationAsync(IEnumerable<AnalysisInvocationExpession> callInvocationInfoForCalls, PropagationKind propKind) { /// Diego: I did this for the demo because I query directly the entities instead of querying the callgraph //if (callInvocationInfoForCalls.Count() > 0) //{ // this.InvalidateCaches(); //} // I made a new list to avoid a concurrent modification exception we received in some tests var invocationsToProcess = new List<AnalysisInvocationExpession>(callInvocationInfoForCalls); var continuations = new List<Task>(); foreach (var invocationInfo in invocationsToProcess) { // Add instanciated types! /// Diego: Ben. This may not work well in parallel... /// We need a different way to update this info invocationInfo.InstatiatedTypes = this.MethodEntity.InstantiatedTypes; // I hate to do this. Need to Refactor! if (invocationInfo is CallInfo) { var t = DispatchCallMessageAsync(invocationInfo as CallInfo, propKind); await t; //continuations.Add(t); } if (invocationInfo is DelegateCallInfo) { var t = DispatchCallMessageForDelegateAsync(invocationInfo as DelegateCallInfo, propKind); await t; //continuations.Add(t); } } Contract.Assert(invocationsToProcess.Count == invocationsToProcess.Count); await Task.WhenAll(continuations); }
public Task PropagateAndProcessAsync(PropagationKind propKind) { this.SetRequestContext(); return(methodEntityGrain.PropagateAndProcessAsync(propKind)); }
public Task <PropagationEffects> PropagateAsync(PropagationKind propKind) { this.SetRequestContext(); return(methodEntityGrain.PropagateAsync(propKind)); }
/// <summary> /// This method is executed when a method finishes its analysis /// If some output info was generated it will generate return messahe /// </summary> /// <param name="propKind"></param> private void EndOfPropagationEvent(PropagationKind propKind, bool retValueChange) { // Should do something more clever ProcessReturnNode(propKind); }
private void ProcessCalleesAffectedByPropagation(IEnumerable<AnalysisInvocationExpession> callInvocationInfoForCalls, PropagationKind propKind) { /// This to to remove any information about calls that we cached /// This is for the incremental reasoning /// Diego: I did this for the demo because I query directly the entities instead of querying the callgraph if (callInvocationInfoForCalls.Count() > 0) { this.InvalidateCaches(); } /// I made a new list to avoid a concurrent modification exception we received in some tests var invocationsToProcess = new List<AnalysisInvocationExpession>(callInvocationInfoForCalls); /// Every invocation that was "touched" by a propagation is signaled to propagate the new data foreach (var invocationInfo in invocationsToProcess) { /// Add instanciated types invocationInfo.InstatiatedTypes = this.MethodEntity.InstantiatedTypes; // I hate to do this. Need to Refactor! if (invocationInfo is CallInfo) { DispatchCallMessage(invocationInfo as CallInfo, propKind); } if (invocationInfo is DelegateCallInfo) { DispatchCallMessageForDelegate(invocationInfo as DelegateCallInfo, propKind); } } }
//public bool DiffProp(IEnumerable<T> src, N n) //{ // var ts = GetTypes(n); // int c = ts.Count; // ts.UnionWith(src.Where(t => !ts.Contains(t))); // if (ts.Count > c) // { // this.workList.Add(n); // return true; // } // return false; //} internal bool DiffProp(IEnumerable <TypeDescriptor> src, PropGraphNodeDescriptor n, PropagationKind propKind) { if (propKind == PropagationKind.REMOVE_TYPES || propKind == PropagationKind.REMOVE_ASSIGNMENT) { return(DiffDelProp(src, n)); } else { return(DiffProp(src, n)); } }
public Task <PropagationEffects> PropagateAsync(PropagationKind propKind) { this.methodEntity.PropGraph.ResetUpdateCount(); return(InternalPropagateAsync(propKind)); }
internal async Task <bool> DiffPropAsync(IEnumerable <TypeDescriptor> src, PropGraphNodeDescriptor n, PropagationKind propKind) { Logger.LogS("PropagationGraph", "DiffPropAsync", "Diff({0},{1})", src, n); if (propKind == PropagationKind.REMOVE_TYPES || propKind == PropagationKind.REMOVE_ASSIGNMENT) { return(DiffDelProp(src, n)); } else { return(await DiffPropAsync(src, n)); } }
/// <summary> /// This method "replaces" the send + dispatch + processReturnMessage for calless that used the methodProcessor and dispatcher /// The idea is trying to avoid reentrant calls to grains /// We wil need to improve the code / design but this is a first approach to solve that problem /// </summary> /// <param name="caller"></param> /// <param name="calleeMessage"></param> /// <param name="propKind"></param> /// <returns></returns> private async Task AnalyzeReturnAsync(MethodDescriptor caller, CalleeMessage calleeMessage, PropagationKind propKind) { Logger.LogS("AnalysisOrchestator", "AnalyzeReturnAsync", "Analyzing return to {0} ", caller); //var methodEntityProc = await this.solutionManager.GetMethodEntityAsync(caller); var methodEntityProc = await GetMethodEntityGrainAndActivateInProject(caller); //PropagationEffects propagationEffects = null; //var ready = true; // //do //{ // propagationEffects = await methodEntityProc.PropagateAsync(calleeMessage.ReturnMessageInfo); // ready = await WaitForReady(propagationEffects, caller); //} //while (!ready); // //await this.PropagateEffectsAsync(propagationEffects, propKind, methodEntityProc); var exit = false; for (int i = 0; i < 3 && !exit; i++) { try { exit = true; var propagationEffects = await methodEntityProc.PropagateAsync(calleeMessage.ReturnMessageInfo); await this.PropagateEffectsAsync(propagationEffects, propKind, methodEntityProc); } catch //(Exception e) { exit = false; } } //var propagationEffects = await methodEntityProc.PropagateAsync(calleeMessage.ReturnMessageInfo); //await this.PropagateEffectsAsync(propagationEffects, propKind, methodEntityProc); Logger.LogS("AnalysisOrchestator", "AnalyzeReturnAsync", "End Analyzing return to {0} ", caller); }
private Task DispachReturnMessageAsync(ReturnInfo returnInfo, PropagationKind propKind) { return(this.CreateAndSendReturnMessageAsync(returnInfo, propKind)); }
private async Task CreateAndSendCallMessageAsync(AnalysisInvocationExpession callInfo, MethodDescriptor realCallee, TypeDescriptor receiverType, PropagationKind propKind) { var callMessage = await CreateCallMessageAsync(callInfo, realCallee, receiverType, propKind); var callerMessage = new CallerMessage(this.EntityDescriptor, callMessage); var destination = EntityFactory.Create(realCallee, this.dispatcher); await this.SendMessageAsync(destination, callerMessage); }
private void CreateAndSendCallMessage(AnalysisInvocationExpession callInfo, MethodDescriptor realCallee, TypeDescriptor receiverType, PropagationKind propKind) { /// Here I have all the necessary info to update the callgraph /// var callMessage = CreateCallMessage(callInfo, realCallee, receiverType, propKind); var callerMessage = new CallerMessage(this.EntityDescriptor, callMessage); var destination = EntityFactory.Create(realCallee, this.dispatcher); this.SendMessage(destination, callerMessage); }
private async Task DispatchCallMessageForDelegateAsync(DelegateCallInfo delegateCallInfo, PropagationKind propKind) { var continuations = new List<Task>(); foreach (var callee in await GetDelegateCalleesAsync(delegateCallInfo.CalleeDelegate)) { var continuation = CreateAndSendCallMessageAsync(delegateCallInfo, callee, callee.ContainerType, propKind); await continuation; //continuations.Add(continuation); } await Task.WhenAll(continuations); }
private Task CreateAndSendCallMessageAsync(CallInfo callInfo, ResolvedCallee callee, PropagationKind propKind) { var callMessageInfo = new CallMessageInfo(callInfo.Caller, callee.Method, callee.ReceiverType, callInfo.ArgumentsPossibleTypes, callInfo.CallNode, callInfo.LHS, propKind); var source = new MethodEntityDescriptor(callInfo.Caller); var callerMessage = new CallerMessage(source, callMessageInfo); return(this.AnalyzeCalleeAsync(callMessageInfo.Callee, callerMessage, propKind)); }
/// <summary> /// When the method returns I should inform the computed return value to all its caller /// It may also propagate other info from out parameters and escaping objects (not implemented) /// </summary> private async Task ProcessReturnNodeAsync(PropagationKind propKind) { if(this.Verbose) { Logger.Instance.Log("MethodEntityProcessor", "ProcessReturnNodeAsync", this.MethodEntity.MethodDescriptor); } if (this.MethodEntity.ReturnVariable != null) { // A test to try to force only one simultaneous entity // We should use a Queue instead //while (this.MethodEntity.CurrentContext == null) //{ // Logger.Instance.Log(string.Format("Waiting: {0} to start before return...", this.Method)); // Thread.Sleep(10); //} //CallConext<M, E> callContext=null; //lock(this.MethodEntity) //{ // callContext = this.MethodEntity.CurrentContext; // this.MethodEntity.CurrentContext = null; //} //var ret = this.MethodEntity.ReturnVariable; //if (callContext.Invocation != null) //{ // var task = DispachReturnMessageAsync(callContext, ret, propKind); // if (task != null) task.RunSynchronously(); //} var continuations = new List<Task>(); foreach (var callerContex in this.MethodEntity.Callers) { var ret = this.MethodEntity.ReturnVariable; var t = DispachReturnMessageAsync(callerContex, ret, propKind); await t; //continuations.Add(t); } await Task.WhenAll(continuations); } }
private async Task PopulatePropagationEffectsInfo(PropagationEffects propagationEffects, PropagationKind propKind) { await this.PopulateCalleesInfo(propagationEffects.CalleesInfo); if (this.methodEntity.ReturnVariable != null || propKind == PropagationKind.REMOVE_TYPES) { this.PopulateCallersInfo(propagationEffects.CallersInfo); } }
/// <summary> /// Async versions of DispachReturnMessage /// </summary> /// <param name="context"></param> /// <param name="returnVariable"></param> /// <param name="propKind"></param> /// <returns></returns> internal async Task DispachReturnMessageAsync(CallContext context, VariableNode returnVariable, PropagationKind propKind) { var caller = context.Caller; var lhs = context.CallLHS; var types = returnVariable != null ? GetTypes(returnVariable, propKind) : new HashSet<TypeDescriptor>(); // Diego TO-DO, different treatment for adding and removal if (propKind == PropagationKind.ADD_TYPES && types.Count() == 0 && returnVariable != null) { var instTypes = new HashSet<TypeDescriptor>(); foreach (var iType in this.MethodEntity.InstantiatedTypes) { var isSubtype = await codeProvider.IsSubtypeAsync(iType,returnVariable.Type); if (isSubtype) { instTypes.Add(iType); } } //instTypes.UnionWith( // this.MethodEntity.InstantiatedTypes // .Where(iType => codeProvider.IsSubtypeAsync(iType,returnVariable.Type).Result)); //// .Where(iType => iType.IsSubtype(returnVariable.Type))); foreach (var t in instTypes) { types.Add(t); } } // Jump to caller var destination = EntityFactory.Create(caller,this.dispatcher); var retMessageInfo = new ReturnMessageInfo( lhs, types, propKind, this.MethodEntity.InstantiatedTypes, context.Invocation); var returnMessage = new ReturnMessage(this.MethodEntity.EntityDescriptor, retMessageInfo); //if (lhs != null) { await this.SendMessageAsync(destination, returnMessage); } //else //{ // return new Task(() => { }); //} }
/// <summary> /// Async veprsion /// </summary> /// <param name="callInfo"></param> /// <param name="propKind"></param> /// <returns></returns> private async Task DispatchCallMessageAsync(CallInfo callInfo, PropagationKind propKind) { if (!callInfo.IsStatic && callInfo.Receiver != null) { // I need to computes all the calless // In case of a deletion we can discar the deleted callee //var types = GetTypes(callNode.Receiver, propKind); var types = GetTypes(callInfo.Receiver); // If types=={} it means that some info ins missing => we should be conservative and use the instantiated types (RTA) if (types.Count() == 0 && propKind != PropagationKind.REMOVE_TYPES) // && propKind==PropagationKind.ADD_TYPES) { var instTypes = new HashSet<TypeDescriptor>(); foreach (var candidateTypeDescriptor in this.MethodEntity.InstantiatedTypes) { var isSubType = await codeProvider.IsSubtypeAsync(candidateTypeDescriptor, callInfo.Receiver.Type); if (isSubType) { instTypes.Add(candidateTypeDescriptor); } } //instTypes.UnionWith(this.MethodEntity.InstantiatedTypes // .Where(candidateTypeDescriptor => codeProvider.IsSubtype(candidateTypeDescriptor,callInfo.Receiver.Type))); foreach (var t in instTypes) { types.Add(t); } // TO-DO: SHould I fix the node in the receiver to show that is not loaded. Ideally I should use the declared type. // Here I will use the already instantiated types this.MethodEntity.PropGraph.Add(callInfo.Receiver, types); //var declaredType = callInfo.Receiver.AType; //this.PropGraph.Add(callInfo.Receiver, declaredType); } if (types.Count() > 0) { var continuations = new List<Task>(); // Hack // Parallel.ForEach(types, async (receiverType) => foreach(var receiverType in types) { // Given a method m and T find the most accurate implementation wrt to T // it can be T.m or the first super class implementing m //var realCallee = callInfo.Callee.FindMethodImplementation(receiverType); var realCallee = await codeProvider.FindMethodImplementationAsync(callInfo.Callee, receiverType); var task = CreateAndSendCallMessageAsync(callInfo, realCallee, receiverType, propKind); await task; //continuations.Add(task); //CreateAndSendCallMessage(callInfo, realCallee, receiverType, propKind); };//); await Task.WhenAll(continuations); } // This is not good: One reason is that loads like b = this.f are not working // in a meth m a after call r.m() because only the value of r is passed and not all its structure else { await CreateAndSendCallMessageAsync(callInfo, callInfo.Callee, callInfo.Callee.ContainerType, propKind); } } else { await CreateAndSendCallMessageAsync(callInfo, callInfo.Callee, callInfo.Callee.ContainerType, propKind); } }
private Task CreateAndSendCallMessageAsync(CallInfo callInfo, ResolvedCallee callee, PropagationKind propKind) { var callMessageInfo = new CallMessageInfo(callInfo.Caller, callee.Method, callee.ReceiverType, callInfo.ArgumentsPossibleTypes, callInfo.CallNode, callInfo.LHS, propKind); var source = new MethodEntityDescriptor(callInfo.Caller); var callerMessage = new CallerMessage(source, callMessageInfo); //Logger.LogWarning(GrainClient.Logger, "Orchestrator", "CreateAndSendCallMsg", "Enqueuing: {0}", callee); //await WaitQueue(QUEUE_THRESHOLD); this.messageWorkList.Enqueue(callerMessage); //this.messageWorkList.Add(callerMessage); return(Task.CompletedTask); //return AnalyzeCalleeAsync(callMessageInfo.Callee, callerMessage, propKind); }
public Task PropagateAndProcessAsync(PropagationKind propKind, IEnumerable <PropGraphNodeDescriptor> reWorkSet) { this.SetRequestContext(); return(methodEntityGrain.PropagateAndProcessAsync(propKind, reWorkSet)); }
private async Task<CallMessageInfo> CreateCallMessageAsync(AnalysisInvocationExpession callInfo, MethodDescriptor actuallCallee, TypeDescriptor computedReceiverType, PropagationKind propKind) { // var calleType = (TypeDescriptor)actuallCallee.ContainerType; var calleType = computedReceiverType; ISet<TypeDescriptor> potentialReceivers = new HashSet<TypeDescriptor>(); if (callInfo.Receiver != null) { // BUG!!!! I should use simply computedReceiverType // Instead of copying all types with use the type we use to compute the callee foreach (var type in GetTypes(callInfo.Receiver, propKind)) { var isSubType = await codeProvider.IsSubtypeAsync(type, calleType); if(isSubType) { potentialReceivers.Add(type); } } //potentialReceivers.UnionWith( // GetTypes(callInfo.Receiver, propKind) // .Where(t => codeProvider.IsSubtype(t, calleType))); //.Where(t => t.IsSubtype(calleType))); // potentialReceivers.Add((AnalysisType)calleType); } var argumentValues = callInfo.Arguments .Select(a => a != null ? GetTypes(a, propKind) : new HashSet<TypeDescriptor>()); Contract.Assert(argumentValues.Count() == callInfo.Arguments.Count()); return new CallMessageInfo(callInfo.Caller, actuallCallee, callInfo.CallNode, potentialReceivers, new List<ISet<TypeDescriptor>>(argumentValues), callInfo.LHS, callInfo.InstatiatedTypes, propKind); }