/// <summary> /// Recursively finds all Pointers from the stack value /// </summary> /// <param name="sv">Stack value</param> /// <param name="values">Stack values</param> private void GetPointersRecursively(DSASM.StackValue sv, List<DSASM.StackValue> values) { switch (sv.optype) { case ProtoCore.DSASM.AddressType.Pointer: values.Add(sv); break; case ProtoCore.DSASM.AddressType.ArrayPointer: List<DSASM.StackValue> stackValues = GetArrayStackValues(sv); foreach (var item in stackValues) GetPointersRecursively(item, values); break; default: break; } }
/// <summary> /// Bounce to an existing executive /// </summary> /// <param name="exeblock"></param> /// <param name="entry"></param> /// <param name="context"></param> /// <param name="stackFrame"></param> /// <param name="locals"></param> /// <param name="fepRun"></param> /// <param name="exec"></param> /// <param name="breakpoints"></param> /// <returns></returns> public StackValue BounceUsingExecutive( DSASM.Executive executive, int exeblock, int entry, StackFrame stackFrame, int locals = 0, bool fepRun = false, DSASM.Executive exec = null, List<Instruction> breakpoints = null) { if (stackFrame != null) { SetupAndPushBounceStackFrame(exeblock, entry, stackFrame, locals); runtimeCore.DebugProps.SetUpBounce(exec, stackFrame.FunctionCallerBlock, stackFrame.ReturnPC); } executive.Execute(exeblock, entry, breakpoints); return executive.RX; }
/// <summary> /// Recursively finds all Pointers from the stack value /// </summary> /// <param name="sv">Stack value</param> /// <param name="values">Stack values</param> private void GetPointersRecursively(DSASM.StackValue sv, List<DSASM.StackValue> values) { switch (sv.optype) { case ProtoCore.DSASM.AddressType.Pointer: values.Add(sv); break; case ProtoCore.DSASM.AddressType.ArrayPointer: var array = runtimeCore.Heap.ToHeapObject<DSArray>(sv); foreach (var item in array.Values) GetPointersRecursively(item, values); break; default: break; } }
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); }
private void SetUpCallr(ref DebugFrame debugFrame, bool isReplicating, bool isExternalFunc, DSASM.Executive exec, int fepRun = 1) { // There is no corresponding RETURN instruction for external functions such as FFI's and dot calls //if (procNode.name != DSDefinitions.Kw.kw_Dispose) { debugFrame.IsExternalFunction = isExternalFunc; debugFrame.IsReplicating = isReplicating; // TODO: Replace FepRun with StackFrameTypeinfo from Core.Rmem.Stack - pratapa debugFrame.FepRun = fepRun; debugFrame.IsResume = false; debugFrame.ExecutingGraphNode = exec.Properties.executingGraphNode; } }
public void SetUpBounce(DSASM.Executive exec, int exeblock, int returnAddr) { DebugFrame debugFrame = new DebugFrame(); // TODO: Replace FepRun with StackFrameTypeinfo from Core.Rmem.Stack - pratapa debugFrame.FepRun = 0; debugFrame.IsResume = false; if (exec != null) { debugFrame.ExecutingGraphNode = exec.Properties.executingGraphNode; } else debugFrame.ExecutingGraphNode = null; DebugStackFrame.Push(debugFrame); }
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; }
/// <summary> /// Find and return all graphnodes that can be reached by executingGraphNode /// </summary> /// <param name="executingGraphNode"></param> /// <param name="executive"></param> /// <param name="exprUID"></param> /// <param name="modBlkId"></param> /// <param name="isSSAAssign"></param> /// <param name="executeSSA"></param> /// <param name="languageBlockID"></param> /// <param name="propertyChanged"></param> /// <returns></returns> public static List<AssociativeGraph.GraphNode> UpdateDependencyGraph( AssociativeGraph.GraphNode executingGraphNode, DSASM.Executive executive, int exprUID, int modBlkId, bool isSSAAssign, bool executeSSA, int languageBlockID, bool recursiveSearch, bool propertyChanged = false) { AssociativeGraph.DependencyGraph dependencyGraph = executive.exe.instrStreamList[languageBlockID].dependencyGraph; List<AssociativeGraph.GraphNode> reachableGraphNodes = new List<AssociativeGraph.GraphNode>(); if (executingGraphNode == null) { return reachableGraphNodes; } int classIndex = executingGraphNode.classIndex; int procIndex = executingGraphNode.procIndex; var graph = dependencyGraph; var graphNodes = graph.GetGraphNodesAtScope(classIndex, procIndex); if (graphNodes == null) { return reachableGraphNodes; } //foreach (var graphNode in graphNodes) for (int i = 0; i < graphNodes.Count; ++i) { var graphNode = graphNodes[i]; // If the graphnode is inactive then it is no longer executed if (!graphNode.isActive) { continue; } // // Comment Jun: // This is clarifying the intention that if the graphnode is within the same SSA expression, we still allow update // bool allowUpdateWithinSSA = false; if (executeSSA) { allowUpdateWithinSSA = true; isSSAAssign = false; // Remove references to this when ssa flag is removed // Do not update if its a property change and the current graphnode is the same expression if (propertyChanged && graphNode.exprUID == executingGraphNode.exprUID) { continue; } } else { // TODO Jun: Remove this code immediatley after enabling SSA bool withinSSAStatement = graphNode.UID == executingGraphNode.UID; allowUpdateWithinSSA = !withinSSAStatement; } if (!allowUpdateWithinSSA || (propertyChanged && graphNode == executingGraphNode)) { continue; } foreach (var noderef in executingGraphNode.updateNodeRefList) { // If this dirty graphnode is an associative lang block, // then find all that nodes in that lang block and mark them dirty if (graphNode.isLanguageBlock) { List<AssociativeGraph.GraphNode> subGraphNodes = ProtoCore.AssociativeEngine.Utils.UpdateDependencyGraph( executingGraphNode, executive, exprUID, modBlkId, isSSAAssign, executeSSA, graphNode.languageBlockId, recursiveSearch); if (subGraphNodes.Count > 0) { reachableGraphNodes.Add(graphNode); } } AssociativeGraph.GraphNode matchingNode = null; if (!graphNode.DependsOn(noderef, ref matchingNode)) { continue; } // @keyu: if we are modifying an object's property, e.g., // // foo.id = 42; // // both dependent list and update list of the corresponding // graph node contains "foo" and "id", so if property "id" // is changed, this graph node will be re-executed and the // value of "id" is incorrectly set back to old value. if (propertyChanged) { var depUpdateNodeRef = graphNode.dependentList[0].updateNodeRefList[0]; if (graphNode.updateNodeRefList.Count == 1) { var updateNodeRef = graphNode.updateNodeRefList[0]; if (depUpdateNodeRef.Equals(updateNodeRef)) { continue; } } } // // Comment Jun: We dont want to cycle between such statements: // // a1.a = 1; // a1.a = 10; // Validity.Assert(null != matchingNode); bool isLHSModification = matchingNode.isLHSNode; bool isUpdateable = matchingNode.IsUpdateableBy(noderef); // isSSAAssign means this is the graphnode of the final SSA assignment // Overrride this if allowing within SSA update // TODO Jun: Remove this code when SSA is completely enabled bool allowSSADownstream = false; if (executeSSA) { // Check if we allow downstream update if (exprUID == graphNode.exprUID) { allowSSADownstream = graphNode.AstID > executingGraphNode.AstID; } } // Comment Jun: // If the triggered dependent graphnode is LHS // and... // the triggering node (executing graphnode) if (isLHSModification && !isUpdateable) { break; } // TODO Jun: Optimization - Reimplement update delta evaluation using registers //if (IsNodeModified(EX, FX)) bool isLastSSAAssignment = (exprUID == graphNode.exprUID) && graphNode.IsLastNodeInSSA && !graphNode.isReturn; if (exprUID != graphNode.exprUID && modBlkId != graphNode.modBlkUID) { UpdateModifierBlockDependencyGraph(graphNode, dependencyGraph.GraphList); } else if (allowSSADownstream || isSSAAssign || isLastSSAAssignment || (exprUID != graphNode.exprUID && modBlkId == Constants.kInvalidIndex && graphNode.modBlkUID == Constants.kInvalidIndex) ) { if (graphNode.isCyclic) { // If the graphnode is cyclic, mark it as not dirst so it wont get executed // Sets its cyclePoint graphnode to be not dirty so it also doesnt execute. // The cyclepoint is the other graphNode that the current node cycles with graphNode.isDirty = false; if (null != graphNode.cyclePoint) { graphNode.cyclePoint.isDirty = false; graphNode.cyclePoint.isCyclic = true; } } else if (!graphNode.isDirty) { graphNode.forPropertyChanged = propertyChanged; reachableGraphNodes.Add(graphNode); // On debug mode: // we want to mark all ssa statements dirty for an if the lhs pointer is a new instance. // In this case, the entire line must be re-executed // // Given: // x = 1 // p = p.f(x) // x = 2 // // To SSA: // // x = 1 // t0 = p -> we want to execute from here of member function 'f' returned a new instance of 'p' // t1 = x // t2 = t0.f(t1) // p = t2 // x = 2 if (null != executingGraphNode.lastGraphNode && executingGraphNode.lastGraphNode.reExecuteExpression) { executingGraphNode.lastGraphNode.reExecuteExpression = false; // TODO Jun: Perform reachability analysis at compile time so the first node can be determined statically at compile time var firstGraphNode = AssociativeEngine.Utils.GetFirstSSAGraphnode(i - 1, graphNodes); reachableGraphNodes.Add(firstGraphNode); } // When a graphnode is dirty, recursively search of other graphnodes that may be affected // Recursive search is only done statically if (recursiveSearch) { List<AssociativeGraph.GraphNode> subGraphNodes = ProtoCore.AssociativeEngine.Utils.UpdateDependencyGraph( graphNode, executive, graphNode.exprUID, graphNode.modBlkUID, graphNode.IsSSANode(), executeSSA, graphNode.languageBlockId, recursiveSearch); if (subGraphNodes.Count > 0) { reachableGraphNodes.AddRange(subGraphNodes); } } } } } } return reachableGraphNodes; }
public static string GetOperatorString(DSASM.Operator optr) { Validity.Assert(null != OpKeywordData.OpSymbolTable && OpKeywordData.OpSymbolTable.Count > 0); if (OpKeywordData.OpSymbolTable.ContainsKey(optr)) { return OpKeywordData.OpSymbolTable[optr]; } return string.Empty; }
/// <summary> /// Mark and sweep garbage collection. /// </summary> /// <param name="gcRootPointers"></param> /// <param name="exe"></param> public void GC(List<StackValue> gcRootPointers, DSASM.Executive exe) { Heap.GCMarkAndSweep(gcRootPointers.ToList(), exe); }
private List<StackValue> GetArrayStackValues(DSASM.StackValue sv) { return ArrayUtils.GetValues<StackValue>(sv, this.core, (DSASM.StackValue s) => s); }
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; ret = ExecWithZeroRI(functionEndPoint, c, formalParameters, stackFrame, core, funcGroup); } else { c.IsReplicating = true; ret = ExecWithRISlowPath(functionEndPoint, c, formalParameters, replicationInstructions, stackFrame, core, funcGroup); } // Explicit calls require the GC of arguments in the function return instruction if (ret.optype != AddressType.ExplicitCall) { for (int i = 0; i < formalParameters.Count; ++i) { GCUtils.GCRelease(formalParameters[i], core); } } if (ret.optype == AddressType.Null) return ret; //It didn't return a value return ret; }
internal List<IGraphicItem> GetGraphicItems(DSASM.StackValue svData, RuntimeCore runtimeCore) { Validity.Assert(svData.IsPointer); object obj = GetCLRObject(svData, runtimeCore); if (obj != null) return GetGraphicItems(obj); return null; }
internal List<IGraphicItem> GetGraphicItems(DSASM.StackValue svData, Core core) { Validity.Assert(svData.optype == AddressType.Pointer); object obj = GetCLRObject(svData, core); if (obj != null) return GetGraphicItems(obj); return null; }
public StackValue Bounce(int exeblock, int entry, ProtoCore.Runtime.Context context, List<Instruction> breakpoints, ProtoCore.DSASM.StackFrame stackFrame, int locals = 0, DSASM.Executive exec = null, DebugServices.EventSink sink = null, bool fepRun = false) { if (stackFrame != null) { StackValue svThisPtr = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr); int ci = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kClass).opdata; int fi = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunction).opdata; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock).opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; ProtoCore.DSASM.StackFrameType callerFrameType = (ProtoCore.DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; ProtoCore.DSASM.StackFrameType frameType = (ProtoCore.DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameType).opdata; Validity.Assert(frameType == StackFrameType.kTypeLanguage); int depth = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameDepth).opdata; int framePointer = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFramePointer).opdata; List<StackValue> registers = stackFrame.GetRegisters(); DebugProps.SetUpBounce(exec, blockCaller, returnAddr); Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerFrameType, frameType, depth + 1, framePointer, registers, locals, 0); } ProtoCore.Language id = DSExecutable.instrStreamList[exeblock].language; CurrentExecutive = Executives[id]; StackValue sv = Executives[id].Execute(exeblock, entry, context, breakpoints, sink, fepRun); return sv; }
public static string GetOperatorString(DSASM.Operator optr) { return Op.GetOpSymbol(optr); }
private DSASM.StackValue[] GetArrayStackValues(DSASM.StackValue sv) { return core.Rmem.GetArrayElements(sv); }