Exemple #1
0
        /// <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;
            }
        }
Exemple #2
0
        //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;
        }