internal static SingleRunTraceData DeserialseFromData(SerializationInfo info, StreamingContext context, int objectID, string marker) { SingleRunTraceData srtd = new SingleRunTraceData(); bool hasData = info.GetBoolean(marker + objectID + "_HasData"); if (hasData) { Byte[] data = Convert.FromBase64String(info.GetString(marker + objectID + "_Data")); IFormatter formatter = new SoapFormatter(); MemoryStream s = new MemoryStream(data); srtd.Data = (ISerializable) formatter.Deserialize(s); } bool hasNestedData = info.GetBoolean(marker + objectID + "_HasNestedData"); if (hasNestedData) { int nestedDataCount = info.GetInt32(marker + objectID + "_NestedDataCount"); if (nestedDataCount > 0) srtd.NestedData = new List<SingleRunTraceData>(); for (int i = 0; i < nestedDataCount; i++) { srtd.NestedData.Add( DeserialseFromData(info, context, i, marker + objectID + "-") ); } } return srtd; }
//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; }
/// <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; } }
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; }
//Repication /// <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, ProtoCore.Runtime.Context c, List<StackValue> formalParameters, List<ReplicationInstruction> replicationInstructions, StackFrame stackFrame, Core core, FunctionGroup funcGroup, SingleRunTraceData previousTraceData, SingleRunTraceData newTraceData) { if (core.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, core, 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("Selected algorithm not supported"); } foreach (int repIndex in repIndecies) { StackValue[] subParameters = null; if (formalParameters[repIndex].IsArray) { subParameters = ArrayUtils.GetValues(formalParameters[repIndex], core); } else { subParameters = new StackValue[] { formalParameters[repIndex] }; } parameters.Add(subParameters); 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; } } 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, core, funcGroup, lastExecTrace, cleanRetTrace); retTrace.NestedData[i] = cleanRetTrace; } StackValue ret = HeapUtils.StoreArray(retSVs, null, core); GCUtils.GCRetain(ret, core); 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) { parameters = ArrayUtils.GetValues(formalParameters[cartIndex], core); 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, core, funcGroup, previousTraceData, newTraceData); } //Now iterate over each of these options for (int i = 0; i < retSize; i++) { #if __PROTOTYPE_ARRAYUPDATE_FUNCTIONCALL // Comment Jun: If the array pointer passed in was of type DS Null, // then it means this is the first time the results are being computed. bool executeAll = c.ArrayPointer.IsNull; if (executeAll || ProtoCore.AssociativeEngine.ArrayUpdate.IsIndexInElementUpdateList(i, c.IndicesIntoArgMap)) { List<List<int>> prevIndexIntoList = new List<List<int>>(); foreach (List<int> dimList in c.IndicesIntoArgMap) { prevIndexIntoList.Add(new List<int>(dimList)); } StackValue svPrevPtr = c.ArrayPointer; if (!executeAll) { c.IndicesIntoArgMap = ProtoCore.AssociativeEngine.ArrayUpdate.UpdateIndexIntoList(i, c.IndicesIntoArgMap); c.ArrayPointer = ProtoCore.Utils.ArrayUtils.GetArrayElementAt(c.ArrayPointer, i, core); } //Build the call List<StackValue> newFormalParams = new List<StackValue>(); newFormalParams.AddRange(formalParameters); if (he != null) { //It was an array pack the arg with the current value newFormalParams[cartIndex] = he.Stack[i]; } List<ReplicationInstruction> newRIs = new List<ReplicationInstruction>(); newRIs.AddRange(replicationInstructions); newRIs.RemoveAt(0); retSVs[i] = ExecWithRISlowPath(functionEndPoint, c, newFormalParams, newRIs, stackFrame, core, funcGroup); // Restore the context properties for arrays c.IndicesIntoArgMap = new List<List<int>>(prevIndexIntoList); c.ArrayPointer = svPrevPtr; } else { retSVs[i] = ProtoCore.Utils.ArrayUtils.GetArrayElementAt(c.ArrayPointer, i, core); } #else //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, core, funcGroup, lastExecTrace, cleanRetTrace); retTrace.NestedData[i] = cleanRetTrace; // retSVs[i] = ExecWithRISlowPath(functionEndPoint, c, newFormalParams, newRIs, stackFrame, core, // funcGroup, previousTraceData, newTraceData); #endif } StackValue ret = HeapUtils.StoreArray(retSVs, null, core); GCUtils.GCRetain(ret, core); return ret; } }
private StackValue Execute(List<FunctionEndPoint> functionEndPoint, ProtoCore.Runtime.Context c, List<StackValue> formalParameters, List<ReplicationInstruction> replicationInstructions, DSASM.StackFrame stackFrame, Core core, FunctionGroup funcGroup) { for (int i = 0; i < formalParameters.Count; ++i) { GCUtils.GCRetain(formalParameters[i], core); } 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 = (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, core, 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 = (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, core, funcGroup, singleRunTraceData, newTraceData); //Do a trace save here if (invokeCount < traceData.Count) traceData[invokeCount] = newTraceData; else { traceData.Add(newTraceData); } } // Explicit calls require the GC of arguments in the function return instruction if (!ret.IsExplicitCall) { for (int i = 0; i < formalParameters.Count; ++i) { GCUtils.GCRelease(formalParameters[i], core); } } invokeCount++; //We've completed this invocation if (ret.IsNull) return ret; //It didn't return a value return ret; }
//Single function call /// <summary> /// Dispatch without replication /// </summary> private StackValue ExecWithZeroRI(List<FunctionEndPoint> functionEndPoint, ProtoCore.Runtime.Context c, List<StackValue> formalParameters, StackFrame stackFrame, Core core, FunctionGroup funcGroup, SingleRunTraceData previousTraceData, SingleRunTraceData newTraceData) { //@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, core); if (functionEndPoint == null) { core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kMethodResolutionFailure, "Function dispatch could not be completed {2EB39E1B-557C-4819-94D8-CF7C9F933E8A}"); return StackValue.Null; } if (core.Options.IDEDebugMode && core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { DebugFrame debugFrame = core.DebugProps.DebugStackFrame.Peek(); debugFrame.FinalFepChosen = finalFep; } List<StackValue> coercedParameters = finalFep.CoerceParameters(formalParameters, core); // Correct block id where the function is defined. StackValue funcBlock = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); funcBlock.opdata = finalFep.BlockScope; stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock, funcBlock); //TraceCache -> TLS //Extract left most high-D pack Object traceD = previousTraceData.GetLeftMostData(); if (traceD != null) { //There was data associated with the previous execution, push this into the TLS Dictionary<string, object> dataDict = new Dictionary<string, object>(); 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, core); if (StackUtils.IsNull(ret)) { //wipe the trace cache TraceUtils.ClearTLSKey(TRACE_KEY); } //TLS -> TraceCache Dictionary<String, Object> traceRet = TraceUtils.GetObjectFromTLS(); if (traceRet.ContainsKey(TRACE_KEY)) { Object val = traceRet[TRACE_KEY]; newTraceData.Data = val; } // An explicit call requires return coercion at the return instruction if (ret.optype != AddressType.ExplicitCall) { ret = PerformReturnTypeCoerce(finalFep, core, ret); } return ret; }