private void PushCall(VMModule module, int functionIndex, byte[] argumentData) { // TODO: Need either better documentation about how bound functions must not re-retrieve arguments from // the original argumentSource after a Call Continuation, or we need to use unique argument buffers for each // bound function call (with pooling of course). I'd opt for the former, it's super easy to just grab your // arguments as soon as you enter the bound function, and is the cleanest as well. GetFunctionStackSizes(module, functionIndex, out int _, out int argumentMemorySize, out int stackSize); if (argumentData.Length != argumentMemorySize) { throw new ArgumentOutOfRangeException(nameof(argumentData), "Function argument size differs."); } // Function input + space for function index _argumentBuffer.Recreate(stackSize + sizeof(int)); for (int i = 0, ilen = argumentData.Length; i < ilen; ++i) { _argumentBuffer.PushVal(argumentData[i]); } _argumentBuffer.PushValInt(functionIndex); PushCall(module, _argumentBuffer); }
private void GetFunctionStackSizes( VMModule module, int functionIndex, out int returnValueSize, out int argumentMemorySize, out int stackSize) { int definedFunctionCount = module.ILModule.DefinedFunctions.Length; if (functionIndex >= definedFunctionCount) { VMFunction function = module.VMFunctions[functionIndex]; returnValueSize = function.ReturnValueSize; argumentMemorySize = function.ArgumentMemorySize; stackSize = returnValueSize + argumentMemorySize; //frame = AcquireFrame(function.ArgumentMemorySize); //frame.BindingEnumerator = function.Delegate(this, new ArgumentSource(frame.Memory, 0)); } else { ILFunction function = module.ILModule.DefinedFunctions[functionIndex]; returnValueSize = function.ReturnValueSize; argumentMemorySize = function.ArgumentMemorySize; stackSize = function.MaxStackSize; //frame = AcquireFrame(function.MaxStackSize); } }
public bool Call( VMModule module, string functionName, byte[] argumentData, Action <bool>?finished = null) { if (IsRunning) { throw new InvalidOperationException("Cannot call function while running"); } int functionIndex = LookupFunction(module.ILModule, functionName); if (functionIndex == -1) { return(false); } int argumentsSize; if (functionIndex < module.ILModule.DefinedFunctions.Length) { argumentsSize = module.ILModule.DefinedFunctions[functionIndex].ArgumentMemorySize; } else { argumentsSize = module.VMFunctions[functionIndex].ArgumentMemorySize; } if (argumentData.Length != argumentsSize) { // TODO: Should this be an exception? At the very least we need a result code to determine why it failed. return(false); } if (finished == null) { finished = success => { }; } IsRunning = true; _finishedCallback = finished; _cycleCount = 0; PushCall(module, functionIndex, argumentData); if (_isStepping) { Break(); } else { Continue(); } return(true); }
public static Continuation Call(VMModule module, int functionIndex, IReadOnlyList <int> arguments) { return(new Continuation { Action = ContinuationAction.CALL, Module = module, FunctionIndex = functionIndex, Arguments = arguments }); }
public static Continuation Call(VMModule module, string functionName, IReadOnlyList <int> arguments) { int index = VirtualMachine.LookupFunction(module.ILModule, functionName); if (index == -1) { throw new ArgumentException($"Function {functionName} not found in given module", nameof(functionName)); } return(Call(module, index, arguments)); }
private void PushCall(VMModule module, StackFrameMemory sourceStack) { int functionIndex = sourceStack.PopValInt(); GetFunctionStackSizes(module, functionIndex, out int returnValueSize, out int argumentMemorySize, out int stackSize); StackFrame frame = AcquireFrame(stackSize); frame.Module = module; frame.Function = functionIndex; frame.Memory.CopyFrom(sourceStack, sourceStack.StackPointer - argumentMemorySize, returnValueSize, argumentMemorySize); sourceStack.Discard(argumentMemorySize); PushCallStack(frame); // TODO: PERF: Try to optimize out calls to HandleModuleAdded when we can deduce that the module has already // been seen. // For calls pushed by the CALL instruction, we know that the module will be the same and that we don't need // to call this function. _debugger?.HandleModuleAdded(module); }