Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 35 additions & 10 deletions src/Engine/ProtoCore/AssociativeGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@ public class Utils
public static AssociativeGraph.GraphNode GetGraphNodeAtPC(int pc, List<AssociativeGraph.GraphNode> graphNodesInScope)
{
Validity.Assert(graphNodesInScope != null);
return graphNodesInScope.FirstOrDefault(g => g.isActive && g.isDirty && g.updateBlock.startpc == pc);

for (int i = 0; i < graphNodesInScope.Count; i++)
{
var g = graphNodesInScope[i];
if (g.isActive && g.isDirty && g.updateBlock.startpc == pc)
{
return g;
}
}

return null;
}

/// <summary>
Expand All @@ -29,7 +39,17 @@ public static AssociativeGraph.GraphNode GetGraphNodeAtPC(int pc, List<Associati
public static AssociativeGraph.GraphNode GetFirstDirtyGraphNodeFromPC(int pc, List<AssociativeGraph.GraphNode> graphNodesInScope)
{
Validity.Assert(graphNodesInScope != null);
return graphNodesInScope.FirstOrDefault(g => g.isActive && g.isDirty && g.updateBlock.startpc >= pc);

for (int i = 0; i < graphNodesInScope.Count; i++)
{
var g = graphNodesInScope[i];
if (g.isActive && g.isDirty && g.updateBlock.startpc >= pc)
{
return g;
}
}

return null;
}

/// <summary>
Expand Down Expand Up @@ -659,23 +679,28 @@ public static bool IsGraphNodeRedefined(AssociativeGraph.GraphNode gnode, Associ
List<AssociativeGraph.GraphNode> redefinedNodes = new List<AssociativeGraph.GraphNode>();
if (executingGraphNode != null)
{
// Remove this condition when full SSA is enabled
bool isssa = (!executingGraphNode.IsSSANode() && executingGraphNode.DependsOnTempSSA());

bool isssa;
if (runtimeCore.Options.ExecuteSSA)
{
isssa = executingGraphNode.IsSSANode();
}
else
{
// Remove this condition when full SSA is enabled
isssa = (!executingGraphNode.IsSSANode() && executingGraphNode.DependsOnTempSSA());
}

if (!isssa)
{

SymbolNode symbol = executingGraphNode.updateNodeRefList[0].nodeList[0].symbol;
bool isMember = symbol.classScope != Constants.kInvalidIndex
&& symbol.functionIndex == Constants.kInvalidIndex;

foreach (AssociativeGraph.GraphNode graphNode in nodesInScope)
{
bool allowRedefine = true;

SymbolNode symbol = executingGraphNode.updateNodeRefList[0].nodeList[0].symbol;
bool isMember = symbol.classScope != Constants.kInvalidIndex
&& symbol.functionIndex == Constants.kInvalidIndex;

if (isMember)
{
// For member vars, do not allow if not in the same scope
Expand Down Expand Up @@ -1475,7 +1500,7 @@ public bool IsSSANode()
return false;
}

var firstNode = updateNodeRefList.First().nodeList.FirstOrDefault();
var firstNode = updateNodeRefList[0].nodeList[0];
return firstNode != null && firstNode.nodeType == UpdateNodeType.Symbol && firstNode.symbol.isSSATemp;
Comment on lines +1503 to 1504
Copy link

Copilot AI Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessing updateNodeRefList[0].nodeList[0] without checking for an empty list can throw IndexOutOfRangeException. Validate both lists before indexing or revert to a safe lookup.

Suggested change
var firstNode = updateNodeRefList[0].nodeList[0];
return firstNode != null && firstNode.nodeType == UpdateNodeType.Symbol && firstNode.symbol.isSSATemp;
if (updateNodeRefList.Count > 0 && updateNodeRefList[0].nodeList.Count > 0)
{
var firstNode = updateNodeRefList[0].nodeList[0];
return firstNode != null && firstNode.nodeType == UpdateNodeType.Symbol && firstNode.symbol.isSSATemp;
}
return false;

Copilot uses AI. Check for mistakes.
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/Engine/ProtoCore/DSASM/DSObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using ProtoCore.Properties;
using ProtoCore.Runtime;

Expand All @@ -12,6 +12,12 @@ public DSObject(int size, Heap heap)
MetaData = new MetaData { type = (int)PrimitiveType.Pointer };
}

public DSObject(int size, Heap heap, MetaData metaData)
: base(size, heap)
{
MetaData = metaData;
}

public DSObject(StackValue[] values, Heap heap)
: base(values, heap)
{
Expand Down
52 changes: 43 additions & 9 deletions src/Engine/ProtoCore/DSASM/Executive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ public Executive(RuntimeCore runtimeCore, bool isFep = false)
deferedGraphNodes = new List<AssociativeGraph.GraphNode>();
}

public void Reset(bool isFep = false)
{
pc = Constants.kInvalidIndex;
executingBlock = Constants.kInvalidIndex;
RX = StackValue.BuildInvalid();
TX = StackValue.BuildInvalid();
fepRun = isFep;
terminate = false;
graphNodesInProgramScope = null;
}

/// <summary>
/// Cache the graphnodes in scope
/// </summary>
Expand Down Expand Up @@ -2308,15 +2319,35 @@ private void Execute(int exeblock, int entry, Language language = Language.NotSp
}
}

private int cacheBlockID = -1;
private int cacheClassIndex = -1;
private int cachesymbolIndex = -1;
private SymbolNode cachedSymbol = null;

protected SymbolNode GetSymbolNode(int blockId, int classIndex, int symbolIndex)
{
if (blockId == cacheBlockID && classIndex == cacheClassIndex && symbolIndex == cachesymbolIndex && cachedSymbol != null)
{
return cachedSymbol;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much is caching really going to help here? After all you're simply avoiding array/list indexing (exe.runtimeSymbols[blockId].symbolList[symbolIndex]), which I believe should just be O(1) operations, or am I missing something?

}

if (Constants.kGlobalScope == classIndex)
{
return exe.runtimeSymbols[blockId].symbolList[symbolIndex];
var symbol = exe.runtimeSymbols[blockId].symbolList[symbolIndex];
cacheBlockID = blockId;
cacheClassIndex = classIndex;
cachesymbolIndex = symbolIndex;
cachedSymbol = symbol;
return symbol;
}
else
{
return exe.classTable.ClassNodes[classIndex].Symbols.symbolList[symbolIndex];
var symbol = exe.classTable.ClassNodes[classIndex].Symbols.symbolList[symbolIndex];
cacheBlockID = blockId;
cacheClassIndex = classIndex;
cachesymbolIndex = symbolIndex;
cachedSymbol = symbol;
return symbol;
}
}

Expand Down Expand Up @@ -2438,10 +2469,11 @@ protected StackValue PopTo(int blockId, StackValue op1, StackValue op2, StackVal
case AddressType.MemVarIndex:

SymbolNode symbol = GetSymbolNode(blockId, op2.ClassIndex, op1.SymbolIndex);
opPrev = rmem.GetSymbolValue(symbol);
rmem.SetSymbolValue(symbol, opVal);
exe.UpdatedSymbols.Add(symbol);
opPrev = rmem.SetSymbolValueAndGetPreviousValue(symbol, opVal);


exe.UpdatedSymbols.Add(symbol);
#if DEBUG
if (IsDebugRun())
{
logWatchWindow(blockId, op1.SymbolIndex);
Expand All @@ -2452,23 +2484,25 @@ protected StackValue PopTo(int blockId, StackValue op1, StackValue op2, StackVal
{
logWatchWindow(blockId, op1.SymbolIndex);
}

#endif
RecordExecutedGraphNode();
break;

case AddressType.StaticMemVarIndex:
var staticMember = GetSymbolNode(blockId, Constants.kGlobalScope, op1.StaticVariableIndex);
opPrev = rmem.GetSymbolValue(staticMember);
rmem.SetSymbolValue(staticMember, opVal);
exe.UpdatedSymbols.Add(staticMember);
opPrev = rmem.SetSymbolValueAndGetPreviousValue(staticMember, opVal);


exe.UpdatedSymbols.Add(staticMember);
#if DEBUG
if (IsDebugRun())
{
logWatchWindow(blockId, op1.StaticVariableIndex);
System.Console.ReadLine();
}

logWatchWindow(blockId, op1.StaticVariableIndex);
#endif
break;
case AddressType.Register:
{
Expand Down
13 changes: 8 additions & 5 deletions src/Engine/ProtoCore/DSASM/Heap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ public enum GCMark
Black // Objects that are in use (are not candidates for garbage collection) and have had all their references traced.
}

private readonly List<int> freeList = new List<int>();
private readonly List<HeapElement> heapElements = new List<HeapElement>();
private readonly List<int> freeList = new List<int>(GC_THRESHOLD);
private readonly List<HeapElement> heapElements = new List<HeapElement>(GC_THRESHOLD);
private HashSet<int> fixedHeapElements = new HashSet<int>();
private readonly StringTable stringTable = new StringTable();
// The expected lifetime of the sweepSet is start of GC to end of GC
Expand Down Expand Up @@ -402,9 +402,7 @@ public StackValue AllocatePointer(int size, MetaData metadata)
{
try
{
int index = AllocateInternal(size, PrimitiveType.Pointer);
var hpe = heapElements[index];
hpe.MetaData = metadata;
int index = AllocatePointerInternal(size, metadata);
return StackValue.BuildPointer(index, metadata);
}
catch (OutOfMemoryException)
Expand Down Expand Up @@ -583,6 +581,11 @@ private int AllocateInternal(int size, PrimitiveType type)
return AddHeapElement(hpe);
}

private int AllocatePointerInternal(int size, MetaData metaData)
{
return AddHeapElement(new DSObject(size, this, metaData));
}

private int AllocateInternal(StackValue[] values, PrimitiveType type)
{
HeapElement hpe = null;
Expand Down
26 changes: 19 additions & 7 deletions src/Engine/ProtoCore/FFI/CLRFFIFunctionPointer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -500,9 +500,24 @@ private string ErrorString(System.Exception ex)
return string.Format(Resources.OperationFailType2, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name, msg);
}

private object[] parameters = null;
private FFIParameterInfo[] paraminfos;
private List<StackValue> referencedParameters;
private object missing = Type.Missing;

public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi, List<StackValue> s)
{
var parameters = new List<object>();
if (parameters == null)
{
parameters = new object[mArgTypes.Length];
paraminfos = ReflectionInfo.GetParameters();
referencedParameters = new List<StackValue>();
}
else
{
referencedParameters.Clear();
}

if (s == null)
s = dsi.runtime.rmem.Stack;

Expand All @@ -525,9 +540,6 @@ public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi, Lis
return null; //Can't call a method on null object.
}

FFIParameterInfo[] paraminfos = ReflectionInfo.GetParameters();
List<StackValue> referencedParameters = new List<StackValue>();

for (int i = 0; i < mArgTypes.Length; ++i)
{
var opArg = s[i];
Expand All @@ -536,7 +548,7 @@ public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi, Lis
Type paramType = paraminfos[i].Info.ParameterType;
object param = null;
if (opArg.IsDefaultArgument)
param = Type.Missing;
param = missing;
else
param = marshaller.UnMarshal(opArg, c, dsi, paramType);

Expand All @@ -559,7 +571,7 @@ public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi, Lis

}

parameters.Add(param);
parameters[i] = param;
}
catch (System.InvalidCastException ex)
{
Expand All @@ -574,7 +586,7 @@ public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi, Lis
}
}

var ret = InvokeFunctionPointerNoThrow(c, dsi, thisObject, parameters.Count > 0 ? parameters.ToArray() : null);
var ret = InvokeFunctionPointerNoThrow(c, dsi, thisObject, parameters);
if (ReflectionInfo.KeepReferenceThis && thisObject != null)
{
referencedParameters.Add(s.Last());
Expand Down
19 changes: 11 additions & 8 deletions src/Engine/ProtoCore/Lang/CallSite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using DynamoServices;
using Newtonsoft.Json;
Expand Down Expand Up @@ -1421,8 +1422,10 @@ private StackValue Execute(
}
else //replicated call
{
ReadOnlySpan<ReplicationInstruction> replicationInstructionsSpan = CollectionsMarshal.AsSpan(replicationInstructions);

c.IsReplicating = true;
ret = ExecWithRISlowPath(functionEndPoints, c, formalParameters, replicationInstructions, stackFrame, runtimeCore, singleRunTraceData, newTraceData);
ret = ExecWithRISlowPath(functionEndPoints, c, formalParameters, replicationInstructionsSpan, stackFrame, runtimeCore, singleRunTraceData, newTraceData);
}

//Do a trace save here
Expand Down Expand Up @@ -1456,7 +1459,7 @@ private StackValue ExecWithRISlowPath(
List<FunctionEndPoint> functionEndPoints,
Context c,
List<StackValue> formalParameters,
List<ReplicationInstruction> replicationInstructions,
ReadOnlySpan<ReplicationInstruction> replicationInstructions,
StackFrame stackFrame,
RuntimeCore runtimeCore,
SingleRunTraceData previousTraceData,
Expand All @@ -1467,7 +1470,7 @@ private StackValue ExecWithRISlowPath(
throw new NotImplementedException("Parallel mode disabled: {BF417AD5-9EA9-4292-ABBC-3526FC5A149E}");

//Recursion base case
if (replicationInstructions.Count == 0)
if (replicationInstructions.Length == 0)
{
return ExecWithZeroRI(functionEndPoints, c, formalParameters, stackFrame, runtimeCore, previousTraceData, newTraceData, finalFunctionEndPoint);
}
Expand All @@ -1490,7 +1493,7 @@ private StackValue ExecWithRISlowPath(
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[]>();
List<StackValue[]> parameters = new List<StackValue[]>(repIndecies.Count);

int retSize;
switch (algorithm)
Expand Down Expand Up @@ -1545,7 +1548,7 @@ private StackValue ExecWithRISlowPath(

StackValue[] retSVs = new StackValue[retSize];
SingleRunTraceData retTrace = newTraceData;
retTrace.NestedData = new List<SingleRunTraceData>(); //this will shadow the SVs as they are created
retTrace.NestedData = new List<SingleRunTraceData>(retSize); //this will shadow the SVs as they are created

//Populate out the size of the list with default values
//@TODO:Luke perf optimisation here
Expand Down Expand Up @@ -1595,7 +1598,7 @@ private StackValue ExecWithRISlowPath(
}
}

List<ReplicationInstruction> newRIs = replicationInstructions.GetRange(1, replicationInstructions.Count - 1);
ReadOnlySpan<ReplicationInstruction> newRIs = replicationInstructions[1..];

SingleRunTraceData cleanRetTrace = new SingleRunTraceData();

Expand Down Expand Up @@ -1658,7 +1661,7 @@ private StackValue ExecWithRISlowPath(

if (supressArray)
{
List<ReplicationInstruction> newRIs = replicationInstructions.GetRange(1, replicationInstructions.Count - 1);
ReadOnlySpan<ReplicationInstruction> newRIs = replicationInstructions[1..];

return ExecWithRISlowPath(functionEndPoints, c, newFormalParams, newRIs, stackFrame, runtimeCore, previousTraceData, newTraceData, finalFunctionEndPoint);
}
Expand All @@ -1669,7 +1672,7 @@ private StackValue ExecWithRISlowPath(
//It was an array pack the arg with the current value
newFormalParams[cartIndex] = array.GetValueFromIndex(i, runtimeCore);

List<ReplicationInstruction> newRIs = replicationInstructions.GetRange(1, replicationInstructions.Count - 1);
ReadOnlySpan<ReplicationInstruction> newRIs = replicationInstructions[1..];

SingleRunTraceData lastExecTrace;

Expand Down
Loading
Loading