/// <summary> /// For a given list of formal parameters, get the function end points that resolve /// </summary> /// <param name="context"></param> /// <param name="formalParams"></param> /// <param name="replicationInstructions"></param> /// <param name="stackFrame"></param> /// <param name="core"></param> /// <param name="unresolvable">The number of argument sets that couldn't be resolved</param> /// <returns>Returns true, if it can find a matching FEP for all the reduced params. Returns False otherwise.</returns> public bool CanGetExactMatchStatics( Runtime.Context context, List <List <StackValue> > reducedFormalParams, StackFrame stackFrame, RuntimeCore runtimeCore, out HashSet <FunctionEndPoint> lookup) { lookup = new HashSet <FunctionEndPoint>(); if (reducedFormalParams.Count == 0) { return(false); } foreach (List <StackValue> formalParamSet in reducedFormalParams) { List <FunctionEndPoint> feps = GetExactTypeMatches(context, formalParamSet, new List <ReplicationInstruction>(), stackFrame, runtimeCore); if (feps.Count == 0) { return(false); } foreach (FunctionEndPoint fep in feps) { lookup.Add(fep); } } return(true); }
/// <summary> /// For a given list of formal parameters, get the function end points that resolve /// </summary> /// <param name="context"></param> /// <param name="formalParams"></param> /// <param name="replicationInstructions"></param> /// <param name="stackFrame"></param> /// <param name="core"></param> /// <param name="unresolvable">The number of argument sets that couldn't be resolved</param> /// <returns></returns> public Dictionary <FunctionEndPoint, int> GetExactMatchStatistics( Runtime.Context context, List <List <StackValue> > reducedFormalParams, StackFrame stackFrame, RuntimeCore runtimeCore, out int unresolvable) { List <ReplicationInstruction> replicationInstructions = new List <ReplicationInstruction>(); //We've already done the reduction before calling this unresolvable = 0; Dictionary <FunctionEndPoint, int> ret = new Dictionary <FunctionEndPoint, int>(); foreach (List <StackValue> formalParamSet in reducedFormalParams) { List <FunctionEndPoint> feps = GetExactTypeMatches(context, formalParamSet, replicationInstructions, stackFrame, runtimeCore); if (feps.Count == 0) { //We have an arugment set that couldn't be resolved unresolvable++; } foreach (FunctionEndPoint fep in feps) { if (ret.ContainsKey(fep)) { ret[fep]++; } else { ret.Add(fep, 1); } } } return(ret); }
/// <summary> /// Returns a dictionary of the function end points that are type compatible /// with any branch of replicated parameters. /// </summary> /// <param name="context"></param> /// <param name="formalParams"></param> /// <param name="replicationInstructions"></param> /// <param name="classTable"></param> /// <param name="runtimeCore"></param> /// <returns></returns> public Dictionary <FunctionEndPoint, int> GetLooseConversionDistances( Runtime.Context context, List <StackValue> formalParams, List <ReplicationInstruction> replicationInstructions, ClassTable classTable, RuntimeCore runtimeCore) { Dictionary <FunctionEndPoint, int> ret = new Dictionary <FunctionEndPoint, int>(); var reducedParams = Replicator.ComputeAllReducedParams(formalParams, replicationInstructions, runtimeCore); foreach (FunctionEndPoint fep in FunctionEndPoints) { foreach (var reducedParam in reducedParams) { int distance = fep.GetConversionDistance(reducedParam, classTable, true, runtimeCore); if (distance != (int)ProcedureDistance.InvalidDistance) { ret.Add(fep, distance); break; } } } return(ret); }
/// <summary> /// Get a dictionary of the function end points that are type compatible /// with the costs of the associated conversions /// </summary> /// <param name="context"></param> /// <param name="formalParams"></param> /// <param name="replicationInstructions"></param> /// <returns></returns> public Dictionary <FunctionEndPoint, int> GetConversionDistances(Runtime.Context context, List <StackValue> formalParams, List <ReplicationInstruction> replicationInstructions, ClassTable classTable, RuntimeCore runtimeCore, bool allowArrayPromotion = false) { Dictionary <FunctionEndPoint, int> ret = new Dictionary <FunctionEndPoint, int>(); //@PERF: Consider parallelising this List <FunctionEndPoint> feps = FunctionEndPoints; List <StackValue> reducedParamSVs = Replicator.EstimateReducedParams(formalParams, replicationInstructions, runtimeCore); foreach (FunctionEndPoint fep in feps) { int distance = fep.GetConversionDistance(reducedParamSVs, classTable, allowArrayPromotion, runtimeCore); if (distance != (int)ProcedureDistance.InvalidDistance) { ret.Add(fep, distance); } } return(ret); }
private StackValue Execute( List<FunctionEndPoint> functionEndPoint, Context c, List<StackValue> formalParameters, List<ReplicationInstruction> replicationInstructions, StackFrame stackFrame, RuntimeCore runtimeCore, FunctionGroup funcGroup) { SingleRunTraceData singleRunTraceData = (invokeCount < traceData.Count) ? traceData[invokeCount] : new SingleRunTraceData(); SingleRunTraceData newTraceData = new SingleRunTraceData(); StackValue ret; if (replicationInstructions.Count == 0) { c.IsReplicating = false; ret = ExecWithZeroRI(functionEndPoint, c, formalParameters, stackFrame, runtimeCore, funcGroup, singleRunTraceData, newTraceData); } else //replicated call { c.IsReplicating = true; ret = ExecWithRISlowPath(functionEndPoint, c, formalParameters, replicationInstructions, stackFrame, runtimeCore, funcGroup, singleRunTraceData, newTraceData); } //Do a trace save here if (invokeCount < traceData.Count) { traceData[invokeCount] = newTraceData; } else { traceData.Add(newTraceData); } invokeCount++; //We've completed this invocation return ret; }
//Dispatch private StackValue DispatchNew( Context context, List<StackValue> arguments, List<List<ReplicationGuide>> partialReplicationGuides, List<AtLevel> atLevels, StackFrame stackFrame, RuntimeCore runtimeCore) { // Update the CallsiteExecutionState with // TODO: Replace this with the real data UpdateCallsiteExecutionState(null, runtimeCore); Stopwatch sw = new Stopwatch(); sw.Start(); StringBuilder log = new StringBuilder(); log.AppendLine("Method name: " + methodName); #region Get Function Group //@PERF: Possible optimisation point here, to deal with static dispatches that don't need replication analysis //Handle resolution Pass 1: Name -> Method Group FunctionGroup funcGroup = GetFuncGroup(runtimeCore); if (funcGroup == null) { log.AppendLine("Function group not located"); log.AppendLine("Resolution failed in: " + sw.ElapsedMilliseconds); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); return ReportFunctionGroupNotFound(runtimeCore, arguments); } //check accesibility of function group bool methodAccessible = IsFunctionGroupAccessible(runtimeCore, ref funcGroup); if (!methodAccessible) { return ReportMethodNotAccessible(runtimeCore); } //If we got here then the function group got resolved log.AppendLine("Function group resolved: " + funcGroup); #endregion arguments = GetArgumentsAtLevels(arguments, atLevels, runtimeCore).Select(a => a.Argument).ToList(); partialReplicationGuides = PerformRepGuideDemotion(arguments, partialReplicationGuides, runtimeCore); //Replication Control is an ordered list of the elements that we have to replicate over //Ordering implies containment, so element 0 is the outer most forloop, element 1 is nested within it etc. //Take the explicit replication guides and build the replication structure //Turn the replication guides into a guide -> List args data structure var partialInstructions = Replicator.BuildPartialReplicationInstructions(partialReplicationGuides); //Get the fep that are resolved List<FunctionEndPoint> resolvesFeps; List<ReplicationInstruction> replicationInstructions; arguments = PerformRepGuideForcedPromotion(arguments, partialReplicationGuides, runtimeCore); ComputeFeps(log, context, arguments, funcGroup, partialInstructions, partialReplicationGuides, stackFrame, runtimeCore, out resolvesFeps, out replicationInstructions); if (resolvesFeps.Count == 0) { log.AppendLine("Resolution Failed"); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); return ReportMethodNotFoundForArguments(runtimeCore, arguments); } arguments.ForEach(x => runtimeCore.AddCallSiteGCRoot(CallSiteID, x)); StackValue ret = Execute(resolvesFeps, context, arguments, replicationInstructions, stackFrame, runtimeCore, funcGroup); runtimeCore.RemoveCallSiteGCRoot(CallSiteID); return ret; }
public StackValue JILDispatch( List<StackValue> arguments, List<List<ReplicationGuide>> replicationGuides, List<AtLevel> atLevels, StackFrame stackFrame, RuntimeCore runtimeCore, Context context) { #if DEBUG ArgumentSanityCheck(arguments); #endif // Dispatch method return DispatchNew(context, arguments, replicationGuides, atLevels, stackFrame, runtimeCore); }
private void ComputeFeps( Context context, List<StackValue> arguments, FunctionGroup funcGroup, List<ReplicationInstruction> instructions, StackFrame stackFrame, RuntimeCore runtimeCore, out List<FunctionEndPoint> resolvesFeps, out List<ReplicationInstruction> replicationInstructions) { #region Case 1: Replication guide with exact match { FunctionEndPoint fep = GetCompleteMatchFunctionEndPoint(context, arguments, funcGroup, instructions, stackFrame, runtimeCore); if (fep != null) { resolvesFeps = new List<FunctionEndPoint>() { fep }; replicationInstructions = instructions; return; } } #endregion var replicationTrials = Replicator.BuildReplicationCombinations(instructions, arguments, runtimeCore); #region Case 2: Replication and replication guide with exact match { //Build the possible ways in which we might replicate foreach (List<ReplicationInstruction> replicationOption in replicationTrials) { List<List<StackValue>> reducedParams = Replicator.ComputeAllReducedParams(arguments, replicationOption, runtimeCore); HashSet<FunctionEndPoint> lookups; if (funcGroup.CanGetExactMatchStatics(context, reducedParams, stackFrame, runtimeCore, out lookups)) { //Otherwise we have a cluster of FEPs that can be used to dispatch the array resolvesFeps = new List<FunctionEndPoint>(lookups); replicationInstructions = replicationOption; return; } } } #endregion #region Case 3: Replciation with type conversion { FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, instructions, stackFrame, runtimeCore); if (compliantTarget != null) { resolvesFeps = new List<FunctionEndPoint>() { compliantTarget }; replicationInstructions = instructions; return; } } #endregion #region Case 4: Replication and replication guide with type conversion { if (arguments.Any(arg => arg.IsArray)) { foreach (List<ReplicationInstruction> replicationOption in replicationTrials) { FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore); if (compliantTarget != null) { resolvesFeps = new List<FunctionEndPoint>() { compliantTarget }; replicationInstructions = replicationOption; return; } } } } #endregion #region Case 5: Replication and replciation guide with type conversion and array promotion { //Add as a first attempt a no-replication, but allowing up-promoting replicationTrials.Add(new List<ReplicationInstruction>()); foreach (List<ReplicationInstruction> replicationOption in replicationTrials) { FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore, true); if (compliantTarget != null) { resolvesFeps = new List<FunctionEndPoint>() { compliantTarget }; replicationInstructions = replicationOption; return; } } } #endregion #region Case 6: Replication and replication guide with type conversion and array promotion, and OK if not all convertible { foreach (List<ReplicationInstruction> replicationOption in replicationTrials) { FunctionEndPoint compliantTarget = GetLooseCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore); if (compliantTarget != null) { resolvesFeps = new List<FunctionEndPoint>() { compliantTarget }; replicationInstructions = replicationOption; return; } } } #endregion resolvesFeps = new List<FunctionEndPoint>(); replicationInstructions = instructions; }
public void SetProperties(Options runtimeOptions, Executable executable, DebugProperties debugProps = null, ProtoCore.Runtime.Context context = null, Executable exprInterpreterExe = null) { this.Context = context; this.DSExecutable = executable; this.Options = runtimeOptions; this.DebugProps = debugProps; this.ExprInterpreterExe = exprInterpreterExe; }
private void ComputeFeps( StringBuilder log, Context context, List<StackValue> arguments, FunctionGroup funcGroup, List<ReplicationInstruction> instructions, List<List<ReplicationGuide>> partialReplicationGuides, StackFrame stackFrame, RuntimeCore runtimeCore, out List<FunctionEndPoint> resolvesFeps, out List<ReplicationInstruction> replicationInstructions) { //With replication guides only //Exact match //Match with single elements //Match with single elements with upcast //Try replication without type cast //Match with type conversion //Match with type conversion with upcast //Try replication + type casting //Try replication + type casting + Array promotion #region First Case: Replicate only according to the replication guides { log.AppendLine("Case 1: Exact Match"); FunctionEndPoint fep = Case1GetCompleteMatchFEP(context, arguments, funcGroup, instructions, stackFrame, runtimeCore, log); if (fep != null) { if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); resolvesFeps = new List<FunctionEndPoint>() { fep }; replicationInstructions = instructions; return; } } #endregion #region Case 1a: Replicate only according to the replication guides, but with a sub-typing match { log.AppendLine("Case 1a: Replication guides + auto-replication + no cases"); List<List<StackValue>> reducedParams = Replicator.ComputeAllReducedParams(arguments, instructions, runtimeCore); int resolutionFailures; Dictionary<FunctionEndPoint, int> lookups = funcGroup.GetExactMatchStatistics( context, reducedParams, stackFrame, runtimeCore, out resolutionFailures); if (resolutionFailures == 0) { log.AppendLine("Resolution succeeded against FEP Cluster"); foreach (FunctionEndPoint fep in lookups.Keys) log.AppendLine("\t - " + fep); List<FunctionEndPoint> feps = new List<FunctionEndPoint>(); feps.AddRange(lookups.Keys); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); //Otherwise we have a cluster of FEPs that can be used to dispatch the array resolvesFeps = feps; replicationInstructions = instructions; return; } } #endregion var replicationTrials = Replicator.BuildReplicationCombinations(instructions, arguments, runtimeCore); #region Case 2: Replication with no type cast { log.AppendLine("Case 2: Beginning Auto-replication, no casts"); //Build the possible ways in which we might replicate foreach (List<ReplicationInstruction> repOption in replicationTrials) { List<List<StackValue>> reducedParams = Replicator.ComputeAllReducedParams(arguments, repOption, runtimeCore); int resolutionFailures; Dictionary<FunctionEndPoint, int> lookups = funcGroup.GetExactMatchStatistics( context, reducedParams, stackFrame, runtimeCore, out resolutionFailures); if (resolutionFailures > 0) continue; log.AppendLine("Resolution succeeded against FEP Cluster"); foreach (FunctionEndPoint fep in lookups.Keys) log.AppendLine("\t - " + fep); List<FunctionEndPoint> feps = new List<FunctionEndPoint>(); feps.AddRange(lookups.Keys); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); //Otherwise we have a cluster of FEPs that can be used to dispatch the array resolvesFeps = feps; replicationInstructions = repOption; return; } } #endregion #region Case 3: Match with type conversion, but no array promotion { log.AppendLine("Case 3: Type conversion"); FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, instructions, stackFrame, runtimeCore); if (compliantTarget != null) { log.AppendLine("Resolution Succeeded: " + compliantTarget); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); resolvesFeps = new List<FunctionEndPoint>() { compliantTarget }; replicationInstructions = instructions; return; } } #endregion #region Case 4: Match with type conversion and replication log.AppendLine("Case 4: Replication + Type conversion"); { if (arguments.Any(arg => arg.IsArray)) { foreach (List<ReplicationInstruction> replicationOption in replicationTrials) { //@TODO: THis should use the proper reducer? FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore); if (compliantTarget != null) { log.AppendLine("Resolution Succeeded: " + compliantTarget); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); resolvesFeps = new List<FunctionEndPoint>() { compliantTarget }; replicationInstructions = replicationOption; return; } } } } #endregion #region Case 5: Match with type conversion, replication and array promotion log.AppendLine("Case 5: Replication + Type conversion + Array promotion"); { //Add as a first attempt a no-replication, but allowing up-promoting replicationTrials.Insert(0, new List<ReplicationInstruction>()); foreach (List<ReplicationInstruction> replicationOption in replicationTrials) { //@TODO: THis should use the proper reducer? FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore, true); if (compliantTarget != null) { log.AppendLine("Resolution Succeeded: " + compliantTarget); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); resolvesFeps = new List<FunctionEndPoint>() { compliantTarget }; replicationInstructions = replicationOption; return; } } } #endregion resolvesFeps = new List<FunctionEndPoint>(); replicationInstructions = instructions; }
/// <summary> /// Conservative guess as to whether this call will replicate or not /// This may give inaccurate answers if the node cluster doesn't actually exist /// </summary> /// <param name="context"></param> /// <param name="arguments"></param> /// <param name="stackFrame"></param> /// <param name="core"></param> /// <returns></returns> public bool WillCallReplicate(Context context, List<StackValue> arguments, List<List<ReplicationGuide>> partialReplicationGuides, StackFrame stackFrame, RuntimeCore runtimeCore, out List<List<ReplicationInstruction>> replicationTrials) { replicationTrials = new List<List<ReplicationInstruction>>(); if (partialReplicationGuides.Count > 0) { // Jun Comment: And at least one of them contains somthing for (int n = 0; n < partialReplicationGuides.Count; ++n) { if (partialReplicationGuides[n].Count > 0) { return true; } } } #region Get Function Group //@PERF: Possible optimisation point here, to deal with static dispatches that don't need replication analysis //Handle resolution Pass 1: Name -> Method Group FunctionGroup funcGroup; try { funcGroup = globalFunctionTable.GlobalFuncTable[classScope + 1][methodName]; } catch (KeyNotFoundException) { return false; } #endregion //Replication Control is an ordered list of the elements that we have to replicate over //Ordering implies containment, so element 0 is the outer most forloop, element 1 is nested within it etc. //Take the explicit replication guides and build the replication structure //Turn the replication guides into a guide -> List args data structure var instructions = Replicator.BuildPartialReplicationInstructions(partialReplicationGuides); #region First Case: Replicate only according to the replication guides { FunctionEndPoint fep = Case1GetCompleteMatchFEP(context, arguments, funcGroup, instructions, stackFrame, runtimeCore, new StringBuilder()); if (fep != null) { //found an exact match return false; } } #endregion #region Case 2: Replication with no type cast { //Build the possible ways in which we might replicate replicationTrials = Replicator.BuildReplicationCombinations(instructions, arguments, runtimeCore); foreach (List<ReplicationInstruction> replicationOption in replicationTrials) { List<List<StackValue>> reducedParams = Replicator.ComputeAllReducedParams(arguments, replicationOption, runtimeCore); int resolutionFailures; funcGroup.GetExactMatchStatistics(context, reducedParams, stackFrame, runtimeCore, out resolutionFailures); if (resolutionFailures > 0) continue; return true; //Replicates against cluster } } #endregion #region Case 3: Match with type conversion, but no array promotion { Dictionary<FunctionEndPoint, int> candidatesWithDistances = funcGroup.GetConversionDistances(context, arguments, instructions, runtimeCore.DSExecutable.classTable, runtimeCore); Dictionary<FunctionEndPoint, int> candidatesWithCastDistances = funcGroup.GetCastDistances(context, arguments, instructions, runtimeCore.DSExecutable.classTable, runtimeCore); List<FunctionEndPoint> candidateFunctions = GetCandidateFunctions(stackFrame, candidatesWithDistances); FunctionEndPoint compliantTarget = GetCompliantTarget(context, arguments, instructions, stackFrame, runtimeCore, candidatesWithCastDistances, candidateFunctions, candidatesWithDistances); if (compliantTarget != null) { return false; //Type conversion but no replication } } #endregion #region Case 5: Match with type conversion, replication and array promotion { //Build the possible ways in which we might replicate replicationTrials = Replicator.BuildReplicationCombinations(instructions, arguments, runtimeCore); //Add as a first attempt a no-replication, but allowing up-promoting replicationTrials.Insert(0, new List<ReplicationInstruction>() ); } #endregion return true; //It'll replicate if it suceeds }
private StackValue Execute(List<FunctionEndPoint> functionEndPoint, Context c, List<StackValue> formalParameters, List<ReplicationInstruction> replicationInstructions, StackFrame stackFrame, RuntimeCore runtimeCore, FunctionGroup funcGroup) { StackValue ret; if (replicationInstructions.Count == 0) { c.IsReplicating = false; SingleRunTraceData singleRunTraceData; //READ TRACE FOR NON-REPLICATED CALL //Lookup the trace data in the cache if (invokeCount < traceData.Count) { singleRunTraceData = traceData[invokeCount]; } else { //We don't have any previous stored data for the previous invoke calls, so //gen an empty packet and push it through singleRunTraceData = new SingleRunTraceData(); } SingleRunTraceData newTraceData = new SingleRunTraceData(); ret = ExecWithZeroRI(functionEndPoint, c, formalParameters, stackFrame, runtimeCore, funcGroup, singleRunTraceData, newTraceData); //newTraceData is update with the trace cache assocaite with the single shot executions if (invokeCount < traceData.Count) traceData[invokeCount] = newTraceData; else { traceData.Add(newTraceData); } } else //replicated call { //Extract the correct run data from the trace cache here //This is the thing that will get unpacked from the datastore SingleRunTraceData singleRunTraceData; SingleRunTraceData newTraceData = new SingleRunTraceData(); //Lookup the trace data in the cache if (invokeCount < traceData.Count) { singleRunTraceData = traceData[invokeCount]; } else { //We don't have any previous stored data for the previous invoke calls, so //gen an empty packet and push it through singleRunTraceData = new SingleRunTraceData(); } c.IsReplicating = true; ret = ExecWithRISlowPath(functionEndPoint, c, formalParameters, replicationInstructions, stackFrame, runtimeCore, funcGroup, singleRunTraceData, newTraceData); //Do a trace save here if (invokeCount < traceData.Count) traceData[invokeCount] = newTraceData; else { traceData.Add(newTraceData); } } invokeCount++; //We've completed this invocation if (ret.IsNull) return ret; //It didn't return a value return ret; }
//Dispatch private StackValue DispatchNew(Context context, List<StackValue> arguments, List<List<ReplicationGuide>> partialReplicationGuides, StackFrame stackFrame, RuntimeCore runtimeCore) { // Update the CallsiteExecutionState with // TODO: Replace this with the real data UpdateCallsiteExecutionState(null, runtimeCore); Stopwatch sw = new Stopwatch(); sw.Start(); StringBuilder log = new StringBuilder(); log.AppendLine("Method name: " + methodName); #region Get Function Group //@PERF: Possible optimisation point here, to deal with static dispatches that don't need replication analysis //Handle resolution Pass 1: Name -> Method Group FunctionGroup funcGroup = GetFuncGroup(runtimeCore); if (funcGroup == null) { log.AppendLine("Function group not located"); log.AppendLine("Resolution failed in: " + sw.ElapsedMilliseconds); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); return ReportFunctionGroupNotFound(runtimeCore); } //// Now that a function group is resolved, the callsite guid can be cached //if (null != funcGroup.CallsiteInstance) //{ // // Sanity check, if the callsite exists, then it mean the guid is identical to the cached guid // Validity.Assert(funcGroup.CallsiteInstance.callsiteID == this.callsiteID); //} //else //{ // funcGroup.CallsiteInstance = this; //} //check accesibility of function group bool methodAccessible = IsFunctionGroupAccessible(runtimeCore, ref funcGroup); if (!methodAccessible) return ReportMethodNotAccessible(runtimeCore); //If we got here then the function group got resolved log.AppendLine("Function group resolved: " + funcGroup); #endregion partialReplicationGuides = PerformRepGuideDemotion(arguments, partialReplicationGuides, runtimeCore); //Replication Control is an ordered list of the elements that we have to replicate over //Ordering implies containment, so element 0 is the outer most forloop, element 1 is nested within it etc. //Take the explicit replication guides and build the replication structure //Turn the replication guides into a guide -> List args data structure ReplicationControl replicationControl = Replicator.Old_ConvertGuidesToInstructions(partialReplicationGuides); log.AppendLine("Replication guides processed to: " + replicationControl); //Get the fep that are resolved List<FunctionEndPoint> resolvesFeps; List<ReplicationInstruction> replicationInstructions; arguments = PerformRepGuideForcedPromotion(arguments, partialReplicationGuides, runtimeCore); ComputeFeps(log, context, arguments, funcGroup, replicationControl, partialReplicationGuides, stackFrame, runtimeCore, out resolvesFeps, out replicationInstructions); if (resolvesFeps.Count == 0) { log.AppendLine("Resolution Failed"); if (runtimeCore.Options.DumpFunctionResolverLogic) runtimeCore.DSExecutable.EventSink.PrintMessage(log.ToString()); return ReportMethodNotFoundForArguments(runtimeCore, arguments); } StackValue ret = Execute(resolvesFeps, context, arguments, replicationInstructions, stackFrame, runtimeCore, funcGroup); return ret; }
/// <summary> /// Returns complete match attempts to locate a function endpoint where 1 FEP matches all of the requirements for dispatch /// </summary> /// <param name="context"></param> /// <param name="arguments"></param> /// <param name="funcGroup"></param> /// <param name="replicationControl"></param> /// <param name="stackFrame"></param> /// <param name="core"></param> /// <param name="log"></param> /// <returns></returns> private FunctionEndPoint GetCompleteMatchFunctionEndPoint( Context context, List<StackValue> arguments, FunctionGroup funcGroup, List<ReplicationInstruction> replicationInstructions, StackFrame stackFrame, RuntimeCore runtimeCore) { //Exact match var exactTypeMatchingCandindates = funcGroup.GetExactTypeMatches(context, arguments, replicationInstructions, stackFrame, runtimeCore); if (exactTypeMatchingCandindates.Count == 0) { return null; } FunctionEndPoint fep = null; if (exactTypeMatchingCandindates.Count == 1) { //Exact match fep = exactTypeMatchingCandindates[0]; } else { //Exact match with upcast fep = SelectFEPFromMultiple(stackFrame, runtimeCore, exactTypeMatchingCandindates, arguments); } return fep; }
/// <summary> /// Excecute an arbitrary depth replication using the full slow path algorithm /// </summary> /// <param name="functionEndPoint"> </param> /// <param name="c"></param> /// <param name="formalParameters"></param> /// <param name="replicationInstructions"></param> /// <param name="stackFrame"></param> /// <param name="core"></param> /// <returns></returns> private StackValue ExecWithRISlowPath( List<FunctionEndPoint> functionEndPoint, Context c, List<StackValue> formalParameters, List<ReplicationInstruction> replicationInstructions, StackFrame stackFrame, RuntimeCore runtimeCore, FunctionGroup funcGroup, SingleRunTraceData previousTraceData, SingleRunTraceData newTraceData) { if (runtimeCore.Options.ExecutionMode == ExecutionMode.Parallel) throw new NotImplementedException("Parallel mode disabled: {BF417AD5-9EA9-4292-ABBC-3526FC5A149E}"); //Recursion base case if (replicationInstructions.Count == 0) { return ExecWithZeroRI(functionEndPoint, c, formalParameters, stackFrame, runtimeCore, funcGroup, previousTraceData, newTraceData); } //Get the replication instruction that this call will deal with ReplicationInstruction ri = replicationInstructions[0]; if (ri.Zipped) { ZipAlgorithm algorithm = ri.ZipAlgorithm; //For each item in this plane, an array of the length of the minimum will be constructed //The size of the array will be the minimum size of the passed arrays List<int> repIndecies = ri.ZipIndecies; //this will hold the heap elements for all the arrays that are going to be replicated over List<StackValue[]> parameters = new List<StackValue[]>(); int retSize; switch (algorithm) { case ZipAlgorithm.Shortest: retSize = Int32.MaxValue; //Search to find the smallest break; case ZipAlgorithm.Longest: retSize = Int32.MinValue; //Search to find the largest break; default: throw new ReplicationCaseNotCurrentlySupported(Resources.AlgorithmNotSupported); } bool hasEmptyArg = false; foreach (int repIndex in repIndecies) { StackValue[] subParameters = null; if (formalParameters[repIndex].IsArray) { subParameters = runtimeCore.Heap.ToHeapObject<DSArray>(formalParameters[repIndex]).Values.ToArray(); } else { subParameters = new StackValue[] { formalParameters[repIndex] }; } parameters.Add(subParameters); if (subParameters.Length == 0) hasEmptyArg = true; switch (algorithm) { case ZipAlgorithm.Shortest: retSize = Math.Min(retSize, subParameters.Length); //We need the smallest array break; case ZipAlgorithm.Longest: retSize = Math.Max(retSize, subParameters.Length); //We need the longest array break; } } // If we're being asked to replicate across an empty list // then it's always going to be zero, as there will never be any // data to pass to that parameter. if (hasEmptyArg) retSize = 0; StackValue[] retSVs = new StackValue[retSize]; SingleRunTraceData retTrace = newTraceData; retTrace.NestedData = new List<SingleRunTraceData>(); //this will shadow the SVs as they are created //Populate out the size of the list with default values //@TODO:Luke perf optimisation here for (int i = 0; i < retSize; i++) retTrace.NestedData.Add(new SingleRunTraceData()); for (int i = 0; i < retSize; i++) { SingleRunTraceData lastExecTrace = new SingleRunTraceData(); if (previousTraceData.HasNestedData && i < previousTraceData.NestedData.Count) { //There was previous data that needs loading into the cache lastExecTrace = previousTraceData.NestedData[i]; } else { //We're off the edge of the previous trace window //So just pass in an empty block lastExecTrace = new SingleRunTraceData(); } //Build the call List<StackValue> newFormalParams = new List<StackValue>(); newFormalParams.AddRange(formalParameters); for (int repIi = 0; repIi < repIndecies.Count; repIi++) { switch (algorithm) { case ZipAlgorithm.Shortest: //If the shortest algorithm is selected this would newFormalParams[repIndecies[repIi]] = parameters[repIi][i]; break; case ZipAlgorithm.Longest: int length = parameters[repIi].Length; if (i < length) { newFormalParams[repIndecies[repIi]] = parameters[repIi][i]; } else { newFormalParams[repIndecies[repIi]] = parameters[repIi].Last(); } break; } } List<ReplicationInstruction> newRIs = new List<ReplicationInstruction>(); newRIs.AddRange(replicationInstructions); newRIs.RemoveAt(0); SingleRunTraceData cleanRetTrace = new SingleRunTraceData(); retSVs[i] = ExecWithRISlowPath(functionEndPoint, c, newFormalParams, newRIs, stackFrame, runtimeCore, funcGroup, lastExecTrace, cleanRetTrace); runtimeCore.AddCallSiteGCRoot(CallSiteID, retSVs[i]); retTrace.NestedData[i] = cleanRetTrace; } StackValue ret = runtimeCore.RuntimeMemory.Heap.AllocateArray(retSVs); return ret; } else { //With a cartesian product over an array, we are going to create an array of n //where the n is the product of the next item //We will call the subsequent reductions n times int cartIndex = ri.CartesianIndex; //this will hold the heap elements for all the arrays that are going to be replicated over bool supressArray = false; int retSize; StackValue[] parameters = null; if (formalParameters[cartIndex].IsArray) { DSArray array = runtimeCore.Heap.ToHeapObject<DSArray>(formalParameters[cartIndex]); parameters = array.Values.ToArray(); retSize = parameters.Length; } else { retSize = 1; supressArray = true; } StackValue[] retSVs = new StackValue[retSize]; SingleRunTraceData retTrace = newTraceData; retTrace.NestedData = new List<SingleRunTraceData>(); //this will shadow the SVs as they are created //Populate out the size of the list with default values //@TODO:Luke perf optimisation here for (int i = 0; i < retSize; i++) { retTrace.NestedData.Add(new SingleRunTraceData()); } if (supressArray) { List<ReplicationInstruction> newRIs = new List<ReplicationInstruction>(); newRIs.AddRange(replicationInstructions); newRIs.RemoveAt(0); List<StackValue> newFormalParams = new List<StackValue>(); newFormalParams.AddRange(formalParameters); return ExecWithRISlowPath(functionEndPoint, c, newFormalParams, newRIs, stackFrame, runtimeCore, funcGroup, previousTraceData, newTraceData); } //Now iterate over each of these options for (int i = 0; i < retSize; i++) { //Build the call List<StackValue> newFormalParams = new List<StackValue>(); newFormalParams.AddRange(formalParameters); if (parameters != null) { //It was an array pack the arg with the current value newFormalParams[cartIndex] = parameters[i]; } List<ReplicationInstruction> newRIs = new List<ReplicationInstruction>(); newRIs.AddRange(replicationInstructions); newRIs.RemoveAt(0); SingleRunTraceData lastExecTrace; if (previousTraceData.HasNestedData && i < previousTraceData.NestedData.Count) { //There was previous data that needs loading into the cache lastExecTrace = previousTraceData.NestedData[i]; } else if (previousTraceData.HasData && i == 0) { //We've moved up one dimension, and there was a previous run lastExecTrace = new SingleRunTraceData(); lastExecTrace.Data = previousTraceData.GetLeftMostData(); } else { //We're off the edge of the previous trace window //So just pass in an empty block lastExecTrace = new SingleRunTraceData(); } //previousTraceData = lastExecTrace; SingleRunTraceData cleanRetTrace = new SingleRunTraceData(); retSVs[i] = ExecWithRISlowPath(functionEndPoint, c, newFormalParams, newRIs, stackFrame, runtimeCore, funcGroup, lastExecTrace, cleanRetTrace); runtimeCore.AddCallSiteGCRoot(CallSiteID, retSVs[i]); retTrace.NestedData[i] = cleanRetTrace; } StackValue ret = runtimeCore.RuntimeMemory.Heap.AllocateArray(retSVs); return ret; } }
public static bool CompareFromDifferentCore(DSArray array1, DSArray array2, RuntimeCore rtCore1, RuntimeCore rtCore2, Context context = null) { if (array1.Count != array2.Count) { return false; } for (int i = 0; i < array1.Count; i++) { if (!StackUtils.CompareStackValues(array1.GetValueAt(i), array2.GetValueAt(i), rtCore1, rtCore2, context)) { return false; } } foreach (var key in array1.Dict.Keys) { StackValue value1 = array1.Dict[key]; StackValue value2 = StackValue.Null; if (!array2.Dict.TryGetValue(key, out value2)) { return false; } if (!StackUtils.CompareStackValues(value1, value2, rtCore1, rtCore2)) { return false; } } return true; }
//Single function call /// <summary> /// Dispatch without replication /// </summary> private StackValue ExecWithZeroRI(List<FunctionEndPoint> functionEndPoint, Context c, List<StackValue> formalParameters, StackFrame stackFrame, RuntimeCore runtimeCore, FunctionGroup funcGroup, SingleRunTraceData previousTraceData, SingleRunTraceData newTraceData) { if (runtimeCore.CancellationPending) { throw new ExecutionCancelledException(); } //@PERF: Todo add a fast path here for the case where we have a homogenious array so we can directly dispatch FunctionEndPoint finalFep = SelectFinalFep(c, functionEndPoint, formalParameters, stackFrame, runtimeCore); if (functionEndPoint == null) { runtimeCore.RuntimeStatus.LogWarning(WarningID.kMethodResolutionFailure, string.Format(Resources.FunctionDispatchFailed, "{2EB39E1B-557C-4819-94D8-CF7C9F933E8A}")); return StackValue.Null; } if (runtimeCore.Options.IDEDebugMode && runtimeCore.Options.RunMode != InterpreterMode.kExpressionInterpreter) { DebugFrame debugFrame = runtimeCore.DebugProps.DebugStackFrame.Peek(); debugFrame.FinalFepChosen = finalFep; } List<StackValue> coercedParameters = finalFep.CoerceParameters(formalParameters, runtimeCore); // Correct block id where the function is defined. stackFrame.FunctionBlock = finalFep.BlockScope; //TraceCache -> TLS //Extract left most high-D pack ISerializable traceD = previousTraceData.GetLeftMostData(); if (traceD != null) { //There was data associated with the previous execution, push this into the TLS Dictionary<string, ISerializable> dataDict = new Dictionary<string, ISerializable>(); dataDict.Add(TRACE_KEY, traceD); TraceUtils.SetObjectToTLS(dataDict); } else { //There was no trace data for this run TraceUtils.ClearAllKnownTLSKeys(); } //EXECUTE StackValue ret = finalFep.Execute(c, coercedParameters, stackFrame, runtimeCore); if (ret.IsNull) { //wipe the trace cache TraceUtils.ClearTLSKey(TRACE_KEY); } //TLS -> TraceCache Dictionary<string, ISerializable> traceRet = TraceUtils.GetObjectFromTLS(); if (traceRet.ContainsKey(TRACE_KEY)) { var val = traceRet[TRACE_KEY]; newTraceData.Data = val; } // An explicit call requires return coercion at the return instruction if (!ret.IsExplicitCall) { ret = PerformReturnTypeCoerce(finalFep, runtimeCore, ret); } return ret; }
private FunctionEndPoint GetCompliantTarget(Context context, List<StackValue> formalParams, List<ReplicationInstruction> replicationControl, StackFrame stackFrame, RuntimeCore runtimeCore, Dictionary<FunctionEndPoint, int> candidatesWithCastDistances, List<FunctionEndPoint> candidateFunctions, Dictionary<FunctionEndPoint, int> candidatesWithDistances) { FunctionEndPoint compliantTarget = null; //Produce an ordered list of the graph costs Dictionary<int, List<FunctionEndPoint>> conversionCostList = new Dictionary<int, List<FunctionEndPoint>>(); foreach (FunctionEndPoint fep in candidateFunctions) { int cost = candidatesWithDistances[fep]; if (conversionCostList.ContainsKey(cost)) conversionCostList[cost].Add(fep); else conversionCostList.Add(cost, new List<FunctionEndPoint> {fep}); } List<int> conversionCosts = new List<int>(conversionCostList.Keys); conversionCosts.Sort(); List<FunctionEndPoint> fepsToSplit = new List<FunctionEndPoint>(); foreach (int cost in conversionCosts) { foreach (FunctionEndPoint funcFep in conversionCostList[cost]) { if (funcFep.DoesPredicateMatch(context, formalParams, replicationControl)) { compliantTarget = funcFep; fepsToSplit.Add(funcFep); } } if (compliantTarget != null) break; } if (fepsToSplit.Count > 1) { int lowestCost = candidatesWithCastDistances[fepsToSplit[0]]; compliantTarget = fepsToSplit[0]; List<FunctionEndPoint> lowestCostFeps = new List<FunctionEndPoint>(); foreach (FunctionEndPoint fep in fepsToSplit) { if (candidatesWithCastDistances[fep] < lowestCost) { lowestCost = candidatesWithCastDistances[fep]; compliantTarget = fep; lowestCostFeps = new List<FunctionEndPoint>() { fep }; } else if (candidatesWithCastDistances[fep] == lowestCost) { lowestCostFeps.Add(fep); } } //We have multiple feps, e.g. form overriding if (lowestCostFeps.Count > 0) compliantTarget = SelectFEPFromMultiple(stackFrame, runtimeCore, lowestCostFeps, formalParams); } return compliantTarget; }
private FunctionEndPoint GetCompliantFEP( Context context, List<StackValue> arguments, FunctionGroup funcGroup, List<ReplicationInstruction> replicationInstructions, StackFrame stackFrame, RuntimeCore runtimeCore, bool allowArrayPromotion = false) { Dictionary<FunctionEndPoint, int> candidatesWithDistances = funcGroup.GetConversionDistances( context, arguments, replicationInstructions, runtimeCore.DSExecutable.classTable, runtimeCore, allowArrayPromotion); Dictionary<FunctionEndPoint, int> candidatesWithCastDistances = funcGroup.GetCastDistances( context, arguments, replicationInstructions, runtimeCore.DSExecutable.classTable, runtimeCore); List<FunctionEndPoint> candidateFunctions = GetCandidateFunctions(stackFrame, candidatesWithDistances); FunctionEndPoint compliantTarget = GetCompliantTarget( context, arguments, replicationInstructions, stackFrame, runtimeCore, candidatesWithCastDistances, candidateFunctions, candidatesWithDistances); return compliantTarget; }
private FunctionEndPoint SelectFinalFep(Context context, List<FunctionEndPoint> functionEndPoint, List<StackValue> formalParameters, StackFrame stackFrame, RuntimeCore runtimeCore) { List<ReplicationInstruction> replicationControl = new List<ReplicationInstruction>(); //We're never going to replicate so create an empty structure to allow us to use //the existing utility methods //Filter for exact matches List<FunctionEndPoint> exactTypeMatchingCandindates = new List<FunctionEndPoint>(); foreach (FunctionEndPoint possibleFep in functionEndPoint) { if (possibleFep.DoesTypeDeepMatch(formalParameters, runtimeCore)) { exactTypeMatchingCandindates.Add(possibleFep); } } //There was an exact match, so dispath to it if (exactTypeMatchingCandindates.Count > 0) { FunctionEndPoint fep = null; if (exactTypeMatchingCandindates.Count == 1) { fep = exactTypeMatchingCandindates[0]; } else { fep = SelectFEPFromMultiple(stackFrame, runtimeCore, exactTypeMatchingCandindates, formalParameters); } return fep; } else { Dictionary<FunctionEndPoint, int> candidatesWithDistances = new Dictionary<FunctionEndPoint, int>(); Dictionary<FunctionEndPoint, int> candidatesWithCastDistances = new Dictionary<FunctionEndPoint, int>(); foreach (FunctionEndPoint fep in functionEndPoint) { //@TODO(Luke): Is this value for allow array promotion correct? int distance = fep.ComputeTypeDistance(formalParameters, runtimeCore.DSExecutable.classTable, runtimeCore, false); if (distance != (int) ProcedureDistance.kInvalidDistance) candidatesWithDistances.Add(fep, distance); } foreach (FunctionEndPoint fep in functionEndPoint) { int dist = fep.ComputeCastDistance(formalParameters, runtimeCore.DSExecutable.classTable, runtimeCore); candidatesWithCastDistances.Add(fep, dist); } List<FunctionEndPoint> candidateFunctions = GetCandidateFunctions(stackFrame, candidatesWithDistances); if (candidateFunctions.Count == 0) { runtimeCore.RuntimeStatus.LogWarning(WarningID.kAmbiguousMethodDispatch, Resources.kAmbigousMethodDispatch); return null; } FunctionEndPoint compliantTarget = GetCompliantTarget(context, formalParameters, replicationControl, stackFrame, runtimeCore, candidatesWithCastDistances, candidateFunctions, candidatesWithDistances); return compliantTarget; } }
/// <summary> /// Get complete match attempts to locate a function endpoint where 1 FEP matches all of the requirements for dispatch /// </summary> /// <param name="context"></param> /// <param name="arguments"></param> /// <param name="funcGroup"></param> /// <param name="replicationControl"></param> /// <param name="stackFrame"></param> /// <param name="core"></param> /// <param name="log"></param> /// <returns></returns> private FunctionEndPoint Case1GetCompleteMatchFEP(Context context, List<StackValue> arguments, FunctionGroup funcGroup, List<ReplicationInstruction> replicationInstructions, StackFrame stackFrame, RuntimeCore runtimeCore, StringBuilder log) { //Exact match List<FunctionEndPoint> exactTypeMatchingCandindates = funcGroup.GetExactTypeMatches(context, arguments, replicationInstructions, stackFrame, runtimeCore); FunctionEndPoint fep = null; if (exactTypeMatchingCandindates.Count > 0) { if (exactTypeMatchingCandindates.Count == 1) { //Exact match fep = exactTypeMatchingCandindates[0]; log.AppendLine("1 exact match found - FEP selected" + fep); } else { //Exact match with upcast fep = SelectFEPFromMultiple(stackFrame, runtimeCore, exactTypeMatchingCandindates, arguments); log.AppendLine(exactTypeMatchingCandindates.Count + "exact matches found - FEP selected" + fep); } } return fep; }
//Inbound methods public StackValue JILDispatchViaNewInterpreter( Context context, List<StackValue> arguments, List<List<ReplicationGuide>> replicationGuides, List<AtLevel> atLevels, StackFrame stackFrame, RuntimeCore runtimeCore) { #if DEBUG ArgumentSanityCheck(arguments); #endif // Dispatch method context.IsImplicitCall = true; return DispatchNew(context, arguments, replicationGuides, atLevels, stackFrame, runtimeCore); }
/// <summary> /// Reset an existing value and re-execute the vm /// </summary> /// <param name="varName"></param> /// <param name="value"></param> public void SetValueAndExecute(string varName, int? value) { core.Options.IsDeltaExecution = true; int nodesMarkedDirty = 0; bool wasSet = SetValue(varName, value, out nodesMarkedDirty); if (wasSet && nodesMarkedDirty > 0) { try { foreach (ProtoCore.DSASM.CodeBlock codeblock in core.CodeBlockList) { ProtoCore.Runtime.Context context = new ProtoCore.Runtime.Context(); ProtoCore.DSASM.StackFrame stackFrame = new ProtoCore.DSASM.StackFrame(core.GlobOffset); int locals = 0; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackUtils.BuildNode(AddressType.CallingConvention, (long)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); stackFrame.SetAt(ProtoCore.DSASM.StackFrame.AbsoluteIndex.kRegisterTX, svCallConvention); core.Bounce(codeblock.codeBlockId, codeblock.instrStream.entrypoint, context, stackFrame, locals, new ProtoCore.DebugServices.ConsoleEventSink()); } } catch { throw; } } }
public RuntimeCore(Options runtimeOptions, Executable executable, ProtoCore.Runtime.Context context) { this.context = context; this.executable = executable; this.runtimeOptions = runtimeOptions; }