/// <summary> /// Retrieves an existing instance of a callsite associated with a UID /// It creates a new callsite if non was found /// </summary> /// <param name="core"></param> /// <param name="uid"></param> /// <returns></returns> public CallSite GetCallSite(GraphNode graphNode, int classScope, string methodName, Executable executable, int runningBlock, Options options, RuntimeStatus runtimeStatus ) { Validity.Assert(null != executable.FunctionTable); CallSite csInstance = null; // TODO Jun: Currently generates a new callsite for imperative and // internally generated functions. // Fix the issues that cause the cache to go out of sync when // attempting to cache internal functions. This may require a // secondary callsite cache for internal functions so they dont // clash with the graphNode UID key var language = executable.instrStreamList[runningBlock].language; bool isImperative = language == Language.kImperative; bool isInternalFunction = CoreUtils.IsInternalFunction(methodName); if (isInternalFunction || isImperative) { csInstance = new CallSite(classScope, methodName, executable.FunctionTable, options.ExecutionMode); } else if (!CallsiteCache.TryGetValue(graphNode.CallsiteIdentifier, out csInstance)) { // Attempt to retrieve a preloaded callsite data (optional). var traceData = GetAndRemoveTraceDataForNode(graphNode.guid); csInstance = new CallSite(classScope, methodName, executable.FunctionTable, options.ExecutionMode, traceData); CallsiteCache[graphNode.CallsiteIdentifier] = csInstance; CallSiteToNodeMap[csInstance.CallSiteID] = graphNode.guid; ASTToCallSiteMap[graphNode.AstID] = csInstance; } if (graphNode != null && !CoreUtils.IsDisposeMethod(methodName)) { csInstance.UpdateCallSite(classScope, methodName); if (options.IsDeltaExecution) { runtimeStatus.ClearWarningForExpression(graphNode.exprUID); } } return csInstance; }
public void SerialisationDataLoadSave() { //Test to ensure that the first time the code is executed the wasTraced attribute is marked as false //and the secodn time it is marked as true string setupCode = @"import(""FFITarget.dll""); x = 0; mtcA = IncrementerTracedClass.IncrementerTracedClass(x); mtcAID = mtcA.ID; mtcAWasTraced = mtcA.WasCreatedWithTrace(); "; // Create 2 CBNs List <Subtree> added = new List <Subtree>(); // Simulate a new new CBN Guid guid1 = System.Guid.NewGuid(); added.Add(ProtoTestFx.TD.TestFrameWork.CreateSubTreeFromCode(guid1, setupCode)); var syncData = new GraphSyncData(null, added, null); astLiveRunner.UpdateGraph(syncData); //Get the callsite for the ctor var core = astLiveRunner.RuntimeCore; var ctorCallsites = core.RuntimeData.CallsiteCache.Values.Where(c => c.MethodName == "IncrementerTracedClass"); Assert.IsTrue(ctorCallsites.Count() == 1); ProtoCore.CallSite cs = ctorCallsites.First(); //Request serialisation string serialisationData = cs.GetTraceDataToSave(); //It shouldn't be empty Assert.IsTrue(!String.IsNullOrEmpty(serialisationData)); //Wipe the trace data cs.TraceData.Clear(); //Re-inject the data into the trace cache cs.LoadSerializedDataIntoTraceCache(serialisationData); ExecuteMoreCode("x = 1;"); // Verify that a is re-executed TestFrameWork.AssertValue("mtcAID", 0, astLiveRunner); TestFrameWork.AssertValue("mtcAWasTraced", true, astLiveRunner); }
public void EnsureSerialisationDataNonNull() { //Test to ensure that the first time the code is executed the wasTraced attribute is marked as false //and the secodn time it is marked as true string setupCode = @"import(""FFITarget.dll""); x = 0; mtcA = IncrementerTracedClass.IncrementerTracedClass(x); mtcAID = mtcA.ID; mtcAWasTraced = mtcA.WasCreatedWithTrace(); "; // Create 2 CBNs List <Subtree> added = new List <Subtree>(); // Simulate a new new CBN Guid guid1 = System.Guid.NewGuid(); added.Add(CreateSubTreeFromCode(guid1, setupCode)); var syncData = new GraphSyncData(null, added, null); astLiveRunner.UpdateGraph(syncData); //Get the callsite for the ctor var core = astLiveRunner.Core; var ctorCallsites = core.DSExecutable.RuntimeData.CallsiteCache.Values.Where(c => c.MethodName == "IncrementerTracedClass"); Assert.IsTrue(ctorCallsites.Count() == 1); ProtoCore.CallSite cs = ctorCallsites.First(); //Request serialisation string serialisationData = cs.GetTraceDataToSave(); //It shouldn't be empty Assert.IsTrue(!String.IsNullOrEmpty(serialisationData)); }
/// <summary> /// Retrieves an existing instance of a callsite associated with a UID /// It creates a new callsite if non was found /// </summary> /// <param name="core"></param> /// <param name="uid"></param> /// <returns></returns> public CallSite GetCallSite(int classScope, string methodName, Executable executable, RuntimeCore runtimeCore) { Validity.Assert(null != executable.FunctionTable); CallSite csInstance = null; var graphNode = executable.ExecutingGraphnode; var topGraphNode = graphNode; // If it is a nested function call, append all callsite ids List<string> callsiteIdentifiers = new List<string>(); foreach (var prop in runtimeCore.InterpreterProps) { if (prop != null && prop.executingGraphNode != null && graphNode != prop.executingGraphNode) { topGraphNode = prop.executingGraphNode; if (!string.IsNullOrEmpty(topGraphNode.CallsiteIdentifier)) { callsiteIdentifiers.Add(topGraphNode.CallsiteIdentifier); } } } if (graphNode != null) { callsiteIdentifiers.Add(graphNode.CallsiteIdentifier); } var callsiteID = string.Join(";", callsiteIdentifiers.ToArray()); // TODO Jun: Currently generates a new callsite for imperative and // internally generated functions. // Fix the issues that cause the cache to go out of sync when // attempting to cache internal functions. This may require a // secondary callsite cache for internal functions so they dont // clash with the graphNode UID key var language = executable.instrStreamList[runtimeCore.RunningBlock].language; bool isImperative = language == Language.Imperative; bool isInternalFunction = CoreUtils.IsInternalFunction(methodName); if (isInternalFunction || isImperative) { csInstance = new CallSite(classScope, methodName, executable.FunctionTable, runtimeCore.Options.ExecutionMode); } else if (!CallsiteCache.TryGetValue(callsiteID, out csInstance)) { // Attempt to retrieve a preloaded callsite data (optional). var traceData = GetAndRemoveTraceDataForNode(topGraphNode.guid, callsiteID); csInstance = new CallSite(classScope, methodName, executable.FunctionTable, runtimeCore.Options.ExecutionMode, traceData); CallsiteCache[callsiteID] = csInstance; CallSiteToNodeMap[csInstance.CallSiteID] = topGraphNode.guid; } if (graphNode != null && !CoreUtils.IsDisposeMethod(methodName)) { csInstance.UpdateCallSite(classScope, methodName); if (runtimeCore.Options.IsDeltaExecution) { runtimeCore.RuntimeStatus.ClearWarningForExpression(graphNode.exprUID); } } return csInstance; }
public void SetUpCallrForDebug(RuntimeCore runtimeCore, DSASM.Executive exec, ProcedureNode fNode, int pc, bool isBaseCall = false, CallSite callsite = null, List<StackValue> arguments = null, List<List<ReplicationGuide>> replicationGuides = null, StackFrame stackFrame = null, List<StackValue> dotCallDimensions = null, bool hasDebugInfo = false, bool isMember = false, StackValue? thisPtr = null) { //ProtoCore.DSASM.Executive exec = core.CurrentExecutive.CurrentDSASMExec; DebugFrame debugFrame = new DebugFrame(); debugFrame.IsBaseCall = isBaseCall; debugFrame.Arguments = arguments; debugFrame.IsMemberFunction = isMember; debugFrame.ThisPtr = thisPtr; debugFrame.HasDebugInfo = hasDebugInfo; if (CoreUtils.IsDisposeMethod(fNode.name)) { debugFrame.IsDisposeCall = true; ReturnPCFromDispose = DebugEntryPC; } if (RunMode == Runmode.StepNext) { debugFrame.FunctionStepOver = true; } bool isReplicating = false; bool isExternalFunction = false; // callsite is set to null for a base class constructor call in CALL if (callsite == null) { isReplicating = false; isExternalFunction = false; SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); return; } // Comment Jun: A dot call does not replicate and must be handled immediately if (fNode.name == Constants.kDotMethodName) { isReplicating = false; isExternalFunction = false; debugFrame.IsDotCall = true; debugFrame.DotCallDimensions = dotCallDimensions; SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); return; } List<List<ReplicationInstruction>> replicationTrials; bool willReplicate = callsite.WillCallReplicate(new Context(), arguments, replicationGuides, stackFrame, runtimeCore, out replicationTrials); // the inline conditional built-in is handled separately as 'WillCallReplicate' is always true in this case if(fNode.name.Equals(Constants.kInlineConditionalMethodName)) { // The inline conditional built-in is created only for associative blocks and needs to be handled separately as below InstructionStream istream = runtimeCore.DSExecutable.instrStreamList[CurrentBlockId]; Validity.Assert(istream.language == Language.kAssociative); { runtimeCore.DebugProps.InlineConditionOptions.isInlineConditional = true; runtimeCore.DebugProps.InlineConditionOptions.startPc = pc; runtimeCore.DebugProps.InlineConditionOptions.endPc = FindEndPCForAssocGraphNode(pc, istream, fNode, exec.Properties.executingGraphNode, runtimeCore.Options.ExecuteSSA); runtimeCore.DebugProps.InlineConditionOptions.instructionStream = runtimeCore.RunningBlock; debugFrame.IsInlineConditional = true; } // no replication case if (willReplicate && replicationTrials.Count == 1) { runtimeCore.DebugProps.InlineConditionOptions.ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); /*if (core.DebugProps.RunMode == Runmode.StepNext) { core.Breakpoints.Clear(); }*/ isReplicating = false; isExternalFunction = false; } else // an inline conditional call that replicates { #if !__DEBUG_REPLICATE // Clear all breakpoints for outermost replicated call if(!DebugStackFrameContains(StackFrameFlagOptions.IsReplicating)) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } #endif isExternalFunction = false; isReplicating = true; } SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec, 0); DebugStackFrame.Push(debugFrame); return; } // Prevent breaking inside a function that is external except for dot calls // by clearing all breakpoints from outermost external function call // This check takes precedence over the replication check else if (fNode.isExternal && fNode.name != Constants.kDotMethodName) { // Clear all breakpoints if (!DebugStackFrameContains(StackFrameFlagOptions.IsExternalFunction) && fNode.name != Constants.kFunctionRangeExpression) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } isExternalFunction = true; isReplicating = false; } // Find if function call will replicate or not and if so // prevent stepping in by removing all breakpoints from outermost replicated call else if (willReplicate) { #if !__DEBUG_REPLICATE // Clear all breakpoints for outermost replicated call if(!DebugStackFrameContains(StackFrameFlagOptions.IsReplicating)) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } #endif isReplicating = true; isExternalFunction = false; } // For all other function calls else { isReplicating = false; isExternalFunction = false; } SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); }
public void LoadSave_R2R_2() { string setupCode = @"import(""FFITarget.dll""); x = 0..2; mtcA = IncrementerTracedClass.IncrementerTracedClass(x); mtcAID = mtcA.ID; mtcAWasTraced = mtcA.WasCreatedWithTrace(); "; // Create 2 CBNs List <Subtree> added = new List <Subtree>(); // Simulate a new new CBN Guid guid1 = System.Guid.NewGuid(); added.Add(CreateSubTreeFromCode(guid1, setupCode)); var syncData = new GraphSyncData(null, added, null); astLiveRunner.UpdateGraph(syncData); TestFrameWork.AssertValue("mtcAID", new List <int>() { 0, 1, 2 }, astLiveRunner); TestFrameWork.AssertValue("mtcAWasTraced", new List <bool>() { false, false, false }, astLiveRunner); //Get the callsite for the ctor var core = astLiveRunner.Core; var ctorCallsites = core.DSExecutable.RuntimeData.CallsiteCache.Values.Where(c => c.MethodName == "IncrementerTracedClass"); Assert.IsTrue(ctorCallsites.Count() == 1); ProtoCore.CallSite cs = ctorCallsites.First(); //Request serialisation string serialisationData = cs.GetTraceDataToSave(); //It shouldn't be empty Assert.IsTrue(!String.IsNullOrEmpty(serialisationData)); //Wipe the trace data cs.TraceData.Clear(); //Re-inject the data into the trace cache cs.LoadSerializedDataIntoTraceCache(serialisationData); // Simulate a new new CBN Guid guid2 = System.Guid.NewGuid(); added = new List <Subtree>(); added.Add(CreateSubTreeFromCode(guid2, "x = 1..2;")); syncData = new GraphSyncData(null, added, null); astLiveRunner.UpdateGraph(syncData); // Verify that a is re-executed TestFrameWork.AssertValue("mtcAID", new List <int>() { 0, 1 }, astLiveRunner); TestFrameWork.AssertValue("mtcAWasTraced", new List <bool>() { true, true }, astLiveRunner); }