/// <summary> /// Execute the data stored in core /// This is the entry point of all DS code to be executed /// </summary> /// <param name="core"></param> /// <returns></returns> public ProtoCore.RuntimeCore ExecuteVM(ProtoCore.Core core) { ProtoCore.RuntimeCore runtimeCore = CreateRuntimeCore(core); runtimeCore.StartTimer(); try { foreach (ProtoCore.DSASM.CodeBlock codeblock in core.CodeBlockList) { // Comment Jun: // On first bounce, the stackframe depth is initialized to -1 in the Stackfame constructor. // Passing it to bounce() increments it so the first depth is always 0 ProtoCore.DSASM.StackFrame stackFrame = new ProtoCore.DSASM.StackFrame(core.GlobOffset); stackFrame.FramePointer = runtimeCore.RuntimeMemory.FramePointer; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.Implicit); stackFrame.TX = svCallConvention; // Initialize the entry point interpreter int locals = 0; // This is the global scope, there are no locals ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore); runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; runtimeCore.CurrentExecutive.CurrentDSASMExec.Bounce(codeblock.codeBlockId, codeblock.instrStream.entrypoint, stackFrame, locals); } runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.ExecutionEnd); } catch { runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.ExecutionEnd); throw; } return(runtimeCore); }
internal object GetCLRObject(StackValue svData, Core core) { if (null == core.DSExecutable.classTable) { return(null); } IList <ClassNode> classNodes = core.DSExecutable.classTable.ClassNodes; if (null == classNodes || (classNodes.Count <= 0)) { return(null); } ClassNode classnode = core.DSExecutable.classTable.ClassNodes[(int)svData.metaData.type]; if (!classnode.IsImportedClass) //TODO: look at properties to see if it contains any FFI objects. { return(null); } try { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, false); var helper = ProtoFFI.DLLFFIHandler.GetModuleHelper(ProtoFFI.FFILanguage.CSharp); var marshaler = helper.GetMarshaller(core); return(marshaler.UnMarshal(svData, null, interpreter, typeof(object))); } catch (System.Exception) { return(null); } }
private ExecutionMirror Execute(int programCounterToExecuteFrom, List <Instruction> breakpoints, bool fepRun = false) { runtimeCore.Breakpoints = breakpoints; resumeBlockID = runtimeCore.RunningBlock; if (runtimeCore.DebugProps.FirstStackFrame != null) { runtimeCore.DebugProps.FirstStackFrame.FramePointer = core.GlobOffset; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); runtimeCore.DebugProps.FirstStackFrame.TX = svCallConvention; } // Initialize the entry point interpreter int locals = 0; // This is the global scope, there are no locals ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore); runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; runtimeCore.CurrentExecutive.CurrentDSASMExec.Bounce( resumeBlockID, programCounterToExecuteFrom, runtimeCore.DebugProps.FirstStackFrame, locals, fepRun, null, breakpoints); return(new ExecutionMirror(runtimeCore.CurrentExecutive.CurrentDSASMExec, runtimeCore)); }
public override StackValue Execute(int codeblock, int entry, ProtoCore.Runtime.Context callContext, System.Collections.Generic.List <Instruction> breakpoints, ProtoCore.DebugServices.EventSink sink = null, bool fepRun = false) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, fepRun); CurrentDSASMExec = interpreter.runtime; StackValue sv = interpreter.Run(breakpoints, codeblock, entry, Language.kAssociative); return(sv); }
public override object Execute(ProtoCore.Runtime.Context context, ProtoCore.DSASM.Interpreter dsi) { int paramCount = mArgTypes.Count; int envSize = IsDNI ? 2 : 0; int totalParamCount = paramCount + envSize; List <Object> parameters = new List <object>(); List <StackValue> s = dsi.runtime.rmem.Stack; if (IsDNI) { parameters.Add(DLLFFIHandler.Env); parameters.Add((Int64)0); } for (int i = 0; i < mArgTypes.Count; ++i) { // Comment Jun: FFI function stack frames do not contain locals int locals = 0; int relative = 0 - ProtoCore.DSASM.StackFrame.kStackFrameSize - locals - i - 1; StackValue o = dsi.runtime.rmem.GetAtRelative(relative); if (o.optype == ProtoCore.DSASM.AddressType.Int) { if (mArgTypes[i].Name == "double") { // if the function expects a double and we have passed an int // in an int then promote it to be a double! // parameters.Add(o.opdata_d); } else { parameters.Add(o.opdata); } } else if (o.optype == ProtoCore.DSASM.AddressType.Double) { parameters.Add(o.opdata_d); } else if (o.optype == ProtoCore.DSASM.AddressType.ArrayPointer) { int size = 0; object array = GetArray(o, dsi, out size); parameters.Add(array); parameters.Add(size); } else { throw new NotSupportedException(); } } //object ret = mFunction.Invoke(parameters); object ret = mFunction.Execute(parameters.ToArray()); return(ConvertReturnValue(ret, context, dsi)); }
private object ConvertCSArrayToDSArray(double[] csArray, ProtoCore.DSASM.Interpreter dsi) { var runtimeCore = dsi.runtime.RuntimeCore; object retVal = null; var values = csArray.Select(x => StackValue.BuildDouble(x)).ToArray(); retVal = runtimeCore.RuntimeMemory.Heap.AllocateArray(values); return(retVal); }
public override StackValue Execute(int codeblock, int entry, ProtoCore.Runtime.Context callContext, ProtoCore.DebugServices.EventSink sink) { if (!core.Options.CompileToLib) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core); CurrentDSASMExec = interpreter.runtime; StackValue sv = interpreter.Run(codeblock, entry, Language.kAssociative); return(sv); } else { return(StackValue.Null); } }
public override StackValue Execute(int codeblock, int entry, ProtoCore.Runtime.Context callContext, ProtoCore.DebugServices.EventSink sink) { if (!core.Options.CompileToLib) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core); CurrentDSASMExec = interpreter.runtime; var sv = interpreter.Run(codeblock, entry, ProtoCore.Language.kImperative); return sv; } else { return StackValue.Null; } }
public FunctionPointerEvaluator(StackValue pointer, Interpreter dsi) { Validity.Assert(pointer.optype == AddressType.FunctionPointer); mRunTime = dsi; Core core = dsi.runtime.Core; int fptr = (int)pointer.opdata; ProtoCore.DSASM.FunctionPointerNode fptrNode; if (core.FunctionPointerTable.functionPointerDictionary.TryGetByFirst(fptr, out fptrNode)) { int blockId = fptrNode.blockId; int procId = fptrNode.procId; mProcNode = dsi.runtime.exe.procedureTable[blockId].procList[procId]; } mCallSite = new ProtoCore.CallSite(ProtoCore.DSASM.Constants.kGlobalScope, Name, core.FunctionTable, core.Options.ExecutionMode); }
private object ConvertCSArrayToDSArray(double[] csArray, ProtoCore.DSASM.Interpreter dsi) { var runtimeCore = dsi.runtime.RuntimeCore; object retVal = null; var values = csArray.Select(x => StackValue.BuildDouble(x)).ToArray(); try { retVal = runtimeCore.RuntimeMemory.Heap.AllocateArray(values); return(retVal); } catch (RunOutOfMemoryException) { dsi.runtime.RuntimeCore.RuntimeStatus.LogWarning(ProtoCore.Runtime.WarningID.RunOutOfMemory, ProtoCore.Properties.Resources.RunOutOfMemory); return(StackValue.Null); } }
/// <summary> /// ExecuteLive is called by the liverunner where a persistent RuntimeCore is provided /// ExecuteLive assumes only a single global scope /// </summary> /// <param name="core"></param> /// <param name="runtimeCore"></param> /// <param name="runningBlock"></param> /// <param name="staticContext"></param> /// <param name="runtimeContext"></param> /// <returns></returns> public ProtoCore.RuntimeCore ExecuteLive(ProtoCore.Core core, ProtoCore.RuntimeCore runtimeCore) { try { Executable exe = runtimeCore.DSExecutable; Validity.Assert(exe.CodeBlocks.Count == 1); CodeBlock codeBlock = runtimeCore.DSExecutable.CodeBlocks[0]; int codeBlockID = codeBlock.codeBlockId; // Comment Jun: // On first bounce, the stackframe depth is initialized to -1 in the Stackfame constructor. // Passing it to bounce() increments it so the first depth is always 0 ProtoCore.DSASM.StackFrame stackFrame = new ProtoCore.DSASM.StackFrame(core.GlobOffset); stackFrame.FramePointer = runtimeCore.RuntimeMemory.FramePointer; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.Implicit); stackFrame.TX = svCallConvention; // Initialize the entry point interpreter int locals = 0; // This is the global scope, there are no locals if (runtimeCore.CurrentExecutive.CurrentDSASMExec == null) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore); runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; } runtimeCore.CurrentExecutive.CurrentDSASMExec.BounceUsingExecutive( runtimeCore.CurrentExecutive.CurrentDSASMExec, codeBlock.codeBlockId, runtimeCore.StartPC, stackFrame, locals); runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.ExecutionEnd); } catch { runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.ExecutionEnd); throw; } return(runtimeCore); }
private object ConvertCSArrayToDSArray(double[] csArray, ProtoCore.DSASM.Interpreter dsi) { var core = dsi.runtime.Core; object retVal = null; lock (core.Heap.cslock) { var numElems = csArray.Length; int ptr = core.Heap.Allocate(numElems); for (int n = numElems - 1; n >= 0; --n) { core.Heap.Heaplist[ptr].Stack[n] = StackValue.BuildDouble(csArray[n]); } retVal = StackValue.BuildArrayPointer(ptr); //dsi.runtime.rmem.Push(StackValue.BuildArrayPointer(ptr)); } return(retVal); }
/// <summary> /// Execute the data stored in core /// This is the entry point of all DS code to be executed /// </summary> /// <param name="core"></param> /// <param name="runningBlock"></param> /// <param name="staticContext"></param> /// <param name="runtimeContext"></param> public ProtoCore.RuntimeCore Execute( ProtoCore.Core core, int runningBlock, ProtoCore.CompileTime.Context staticContext, ProtoCore.Runtime.Context runtimeContext) { //========================Generate runtimecore here===============================// ProtoCore.RuntimeCore runtimeCore = core.__TempCoreHostForRefactoring; // Move these core setup to runtime core runtimeCore.RuntimeMemory.PushFrameForGlobals(core.GlobOffset); runtimeCore.RunningBlock = runningBlock; runtimeCore.RuntimeStatus.MessageHandler = core.BuildStatus.MessageHandler; try { runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionBegin); foreach (ProtoCore.DSASM.CodeBlock codeblock in core.CodeBlockList) { // Comment Jun: // On first bounce, the stackframe depth is initialized to -1 in the Stackfame constructor. // Passing it to bounce() increments it so the first depth is always 0 ProtoCore.DSASM.StackFrame stackFrame = new ProtoCore.DSASM.StackFrame(core.GlobOffset); stackFrame.FramePointer = runtimeCore.RuntimeMemory.FramePointer; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); stackFrame.TX = svCallConvention; // Initialize the entry point interpreter int locals = 0; // This is the global scope, there are no locals ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore); runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; runtimeCore.CurrentExecutive.CurrentDSASMExec.Bounce(codeblock.codeBlockId, codeblock.instrStream.entrypoint, runtimeContext, stackFrame, locals); } runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd); } catch { runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd); throw; } return(runtimeCore); }
public FunctionPointerEvaluator(StackValue pointer, Interpreter dsi) { Validity.Assert(pointer.IsFunctionPointer); interpreter = dsi; RuntimeCore runtimeCore = dsi.runtime.RuntimeCore; int fptr = (int)pointer.opdata; FunctionPointerNode fptrNode; int classScope = Constants.kGlobalScope; if (runtimeCore.DSExecutable.FuncPointerTable.functionPointerDictionary.TryGetByFirst(fptr, out fptrNode)) { int blockId = fptrNode.blockId; int procId = fptrNode.procId; classScope = fptrNode.classScope; procNode = dsi.runtime.GetProcedureNode(blockId, classScope, procId); } callsite = new ProtoCore.CallSite(classScope, Name, interpreter.runtime.exe.FunctionTable, runtimeCore.Options.ExecutionMode); }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { Object retVal = base.Execute(c, dsi); if (retVal == null) { return null; } StackValue propValue = (StackValue)retVal; StackValue thisObject = dsi.runtime.rmem.Stack.Last(); if (StackUtils.IsValidPointer(thisObject) && StackUtils.IsReferenceType(propValue)) { int classIndex = (int)thisObject.metaData.type; if (classIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { var core = dsi.runtime.Core; int thisptr = (int)thisObject.opdata; int idx = core.DSExecutable.classTable.ClassNodes[classIndex].symbols.IndexOf(PropertyName); StackValue oldValue = core.Heap.Heaplist[(int)thisObject.opdata].GetValue(idx, core); if (!StackUtils.Equals(oldValue, propValue)) { GCUtils.GCRetain(propValue, core); core.Heap.Heaplist[thisptr].SetValue(idx, propValue); } } } return retVal; }
private object GetArray(StackValue o, ProtoCore.DSASM.Interpreter dsi, out int size) { size = 0; var array = dsi.runtime.rmem.Heap.ToHeapObject <DSArray>(o); if (!array.VisibleItems.Any()) { return(null); } IList elements = null; var opType = array.GetValueFromIndex(0, dsi.runtime.RuntimeCore).optype; if (opType == AddressType.Boolean) { elements = new List <bool>(); } else if (opType == AddressType.Double) { elements = new List <double>(); } else if (opType == AddressType.Int) { elements = new List <int>(); } else if (opType == AddressType.ArrayPointer) { throw new ArgumentException("FFI does not support nested arrays"); } else { throw new ArgumentException(string.Format("Argument of type {0} is not supported for FFI Marshalling", opType.ToString())); } foreach (var op in array.VisibleItems) { if (opType == AddressType.Double) { elements.Add(op.RawDoubleValue); } else if (opType == AddressType.Int) { elements.Add(op.RawIntValue); } else if (opType == AddressType.Boolean) { elements.Add(op.RawIntValue == 0 ? true : false); } } // now based on the type of element in ds-array // create a new array and return it // if (opType == AddressType.Double) { double[] arr = new double[size]; elements.CopyTo(arr, 0); return(arr); } else if (opType == AddressType.Int) { int[] arr = new int[size]; elements.CopyTo(arr, 0); return(arr); } else if (opType == AddressType.Boolean) { bool[] arr = new bool[size]; elements.CopyTo(arr, 0); return(arr); } else { size = 0; return(null); } }
public StackValue Execute(int codeblock, int entry, ProtoCore.Runtime.Context callContext, bool fepRun = false, System.Collections.Generic.List <Instruction> breakpoints = null) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, fepRun); CurrentDSASMExec = interpreter.runtime; return(interpreter.Run(codeblock, entry, CurrentDSASMExec.executingLanguage, breakpoints)); }
public static string GetMethodName(StackValue pointer, Interpreter dsi) { Validity.Assert(pointer.optype == AddressType.FunctionPointer); return dsi.runtime.exe.procedureTable[0].procList[(int)pointer.opdata].name; }
/// <summary> /// Execute the data stored in core /// This is the entry point of all DS code to be executed /// </summary> /// <param name="core"></param> /// <returns></returns> public ProtoCore.RuntimeCore ExecuteVM(ProtoCore.Core core) { ProtoCore.RuntimeCore runtimeCore = CreateRuntimeCore(core); runtimeCore.StartTimer(); try { foreach (ProtoCore.DSASM.CodeBlock codeblock in core.CodeBlockList) { // Comment Jun: // On first bounce, the stackframe depth is initialized to -1 in the Stackfame constructor. // Passing it to bounce() increments it so the first depth is always 0 ProtoCore.DSASM.StackFrame stackFrame = new ProtoCore.DSASM.StackFrame(core.GlobOffset); stackFrame.FramePointer = runtimeCore.RuntimeMemory.FramePointer; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); stackFrame.TX = svCallConvention; // Initialize the entry point interpreter int locals = 0; // This is the global scope, there are no locals ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore); runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; runtimeCore.CurrentExecutive.CurrentDSASMExec.Bounce(codeblock.codeBlockId, codeblock.instrStream.entrypoint, stackFrame, locals); } runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd); } catch { runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd); throw; } return runtimeCore; }
public override StackValue Execute(ProtoCore.Runtime.Context c, List <StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { // ensure there is no data race, function resolution and execution happens in parallel // but for FFI we want it to be serial cause the code we are calling into may not cope // with parallelism. // // we are always looking and putting our function pointers in handler with each lang // so better lock for FFIHandler (being static) it will be good object to lock // lock (FFIHandlers) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); StackValue svThisPtr = stackFrame.GetAt(StackFrame.AbsoluteIndex.kThisPtr); StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.JILRecord.classIndex; int fi = activation.JILRecord.funcIndex; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)svBlockDecl.opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = core.Rmem.FramePointer; int locals = activation.JILRecord.locals; FFIHandler handler = FFIHandlers[activation.ModuleType]; FFIActivationRecord r = activation; string className = ""; if (activation.JILRecord.classIndex > 0) { className = core.DSExecutable.classTable.ClassNodes[activation.JILRecord.classIndex].name; } bool gcThisPtr = false; List <ProtoCore.Type> argTypes = new List <Type>(r.ParameterTypes); ProcedureNode fNode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != ci) { fNode = interpreter.runtime.exe.classTable.ClassNodes[ci].vtable.procList[fi]; } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != fNode && fNode.isAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = svThisPtr.IsPointer && Constants.kInvalidPointer == (int)svThisPtr.opdata; if (isStaticCall) { thisPtrIndex = formalParameters.Count - 1; } argTypes.RemoveAt(thisPtrIndex); // Comment Jun: Execute() can handle a null this pointer. // But since we dont even need to to reach there if we dont have a valid this pointer, then just return null if (formalParameters[thisPtrIndex].IsNull) { core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kDereferencingNonPointer, ProtoCore.RuntimeData.WarningMessage.kDeferencingNonPointer); return(StackValue.Null); } // These are the op types allowed. Validity.Assert(formalParameters[thisPtrIndex].IsPointer || formalParameters[thisPtrIndex].IsDefaultArgument); svThisPtr = formalParameters[thisPtrIndex]; gcThisPtr = true; formalParameters.RemoveAt(thisPtrIndex); } FFIFunctionPointer functionPointer = handler.GetFunctionPointer(r.ModuleName, className, r.FunctionName, argTypes, r.ReturnType); mFunctionPointer = Validate(functionPointer) ? functionPointer : null; mFunctionPointer.IsDNI = activation.IsDNI; if (mFunctionPointer == null) { return(ProtoCore.DSASM.StackValue.Null); } List <object> ps = new List <object>(); //obsolete { interpreter.runtime.executingBlock = core.RunningBlock; activation.JILRecord.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } List <StackValue> registers = new List <DSASM.StackValue>(); interpreter.runtime.SaveRegisters(registers); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = 0; StackFrameType callerType = (StackFrameType)stackFrame.GetAt(StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; // FFI calls do not have execution states core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, ProtoCore.DSASM.StackFrameType.kTypeFunction, depth, framePointer, registers, locals, 0); //is there a way the current stack be passed across and back into the managed runtime by FFI calling back into the language? //e.g. DCEnv* carrying all the stack information? look at how vmkit does this. // = jilMain.Run(ActivationRecord.JILRecord.pc, null, true); //double[] tempArray = GetUnderlyingArray<double>(jilMain.runtime.rmem.stack); Object ret = mFunctionPointer.Execute(c, interpreter); StackValue op; if (ret == null) { op = StackValue.Null; } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = StackValue.BuildInt((Int64)ret); } else if (ret is double) { op = StackValue.BuildDouble((double)ret); } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } // gc the parameters if (gcThisPtr)// && core.Options.EnableThisPointerFunctionOverload) { // thisptr is sent as parameter, so need to gc it. // but when running in expression interpreter mode, do not GC because in DSASM.Executive.DecRefCounter() related GC functions, // the reference count will not be changed in expression interpreter mode. if (core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { interpreter.runtime.Core.Rmem.Heap.GCRelease(new StackValue[] { svThisPtr }, interpreter.runtime); } } interpreter.runtime.Core.Rmem.Heap.GCRelease(formalParameters.ToArray(), interpreter.runtime); // increment the reference counter of the return value interpreter.runtime.GCRetain(op); // Clear the FFI stack frame // FFI stack frames have no local variables interpreter.runtime.rmem.FramePointer = (int)interpreter.runtime.rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; interpreter.runtime.rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + formalParameters.Count); return(op); //DSASM.Mirror.ExecutionMirror.Unpack(op, core.heap, core); } } }
public static string GetMethodName(StackValue pointer, Interpreter dsi) { Validity.Assert(pointer.IsFunctionPointer); return dsi.runtime.exe.procedureTable[0].Procedures[(int)pointer.opdata].Name; }
public override StackValue Execute(ProtoCore.Runtime.Context c, List <StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); ProtoCore.DSASM.Executive oldDSASMExec = null; if (core.CurrentExecutive != null) { oldDSASMExec = core.CurrentExecutive.CurrentDSASMExec; core.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; } // Assert for the block type activation.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // Push Execution states int execStateSize = 0; if (null != stackFrame.ExecutionStates) { execStateSize = stackFrame.ExecutionStates.Length; // ExecutionStates are in lexical order // Push them in reverse order (similar to args) so they can be retrieved in sequence // Retrieveing the executing states occur on function return for (int n = execStateSize - 1; n >= 0; --n) { StackValue svState = stackFrame.ExecutionStates[n]; Validity.Assert(svState.IsBoolean); interpreter.Push(svState); } } // Push Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } StackValue svThisPtr = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr); StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); // Jun: Make sure we have no empty or unaligned frame data Validity.Assert(DSASM.StackFrame.kStackFrameSize == stackFrame.Frame.Length); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.classIndex; int fi = activation.funcIndex; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)svBlockDecl.opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = core.Rmem.FramePointer; int locals = activation.locals; // Update the running block to tell the execution engine which set of instruction to execute // TODO(Jun/Jiong): Considering store the orig block id to stack frame int origRunningBlock = core.RunningBlock; core.RunningBlock = (int)svBlockDecl.opdata; // Set SX register interpreter.runtime.SX = svBlockDecl; DSASM.StackFrameType callerType = (DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; List <StackValue> registers = new List <DSASM.StackValue>(); StackValue svCallConvention; bool isDispose = CoreUtils.IsDisposeMethod(procedureNode.name); bool explicitCall = !c.IsReplicating && !c.IsImplicitCall && !isDispose; if (explicitCall) { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kExplicit); } else { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kImplicit); } stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kRegisterTX, svCallConvention); interpreter.runtime.TX = svCallConvention; // Set SX register stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kRegisterSX, svBlockDecl); interpreter.runtime.SX = svBlockDecl; // TODO Jun: // The stackframe carries the current set of registers // Determine if this can be done even for the non explicit call implementation registers.AddRange(stackFrame.GetRegisters()); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameDepth).opdata; DSASM.StackFrameType type = (DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameType).opdata; Validity.Assert(depth == 0); Validity.Assert(type == DSASM.StackFrameType.kTypeFunction); core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, type, depth, framePointer, registers, locals, execStateSize); StackValue svRet; if (explicitCall) { svRet = ProtoCore.DSASM.StackValue.BuildExplicitCall(activation.pc); } else { if (core.ExecMode != DSASM.InterpreterMode.kExpressionInterpreter && core.Options.IDEDebugMode) { svRet = interpreter.Run(core.Breakpoints, core.RunningBlock, activation.pc, Language.kInvalid); } else { svRet = interpreter.Run(core.RunningBlock, activation.pc, Language.kInvalid); } core.RunningBlock = origRunningBlock; } if (core.CurrentExecutive != null) { core.CurrentExecutive.CurrentDSASMExec = oldDSASMExec; } return(svRet); //DSASM.Mirror.ExecutionMirror.Unpack(svRet, core.heap, core); }
protected object InvokeFunctionPointerNoThrow(ProtoCore.Runtime.Context c, Interpreter dsi, object thisObject, object[] parameters) { object ret = null; StackValue dsRetValue = StackValue.Null; try { FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.RuntimeCore); ret = InvokeFunctionPointer(thisObject, parameters); //Reduce to singleton if the attribute is specified. ret = ReflectionInfo.ReduceReturnedCollectionToSingleton(ret); dsRetValue = marshaller.Marshal(ret, c, dsi, mReturnType); } catch (DllNotFoundException ex) { if (ex.InnerException != null) { dsi.LogSemanticError(ex.InnerException.Message); } dsi.LogSemanticError(ex.Message); } catch (System.Reflection.TargetException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.Reflection.TargetInvocationException ex) { if (ex.InnerException != null) { System.Exception exc = ex.InnerException; var exception = exc as ArgumentNullException; if (exception != null) { var innerMessage = string.Format(Resources.ArgumentNullException, exception.ParamName); var msg = string.Format(Resources.OperationFailType2, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name, innerMessage); dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, msg); } else if (exc is System.ArgumentException) dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, ErrorString(exc)); else if (exc is System.NullReferenceException) dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ErrorString(null)); else dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ErrorString(exc)); } else dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ErrorString(ex)); } catch (System.Reflection.TargetParameterCountException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.MethodAccessException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.InvalidOperationException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.NotSupportedException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (ArgumentNullException ex) { var innerMessage = string.Format(Resources.ArgumentNullException, ex.ParamName); var msg = string.Format(Resources.OperationFailType2, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name, innerMessage); dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, msg); } catch (System.ArgumentException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, ErrorString(ex.InnerException)); } else dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, ErrorString(ex)); } catch (Exception ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kDefault, ErrorString(ex.InnerException)); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kDefault, ErrorString(ex)); } return dsRetValue; }
internal object GetCLRObject(StackValue svData, Core core) { if (null == core.DSExecutable.classTable) return null; IList<ClassNode> classNodes = core.DSExecutable.classTable.ClassNodes; if (null == classNodes || (classNodes.Count <= 0)) return null; ClassNode classnode = core.DSExecutable.classTable.ClassNodes[(int)svData.metaData.type]; if (!classnode.IsImportedClass) //TODO: look at properties to see if it contains any FFI objects. return null; try { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, false); var helper = ProtoFFI.DLLFFIHandler.GetModuleHelper(ProtoFFI.FFILanguage.CSharp); var marshaler = helper.GetMarshaller(core); return marshaler.UnMarshal(svData, null, interpreter, typeof(object)); } catch (System.Exception) { return null; } }
public override StackValue Execute(ProtoCore.Runtime.Context c, List<StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { // ensure there is no data race, function resolution and execution happens in parallel // but for FFI we want it to be serial cause the code we are calling into may not cope // with parallelism. // // we are always looking and putting our function pointers in handler with each lang // so better lock for FFIHandler (being static) it will be good object to lock // lock (FFIHandlers) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); StackValue svThisPtr = stackFrame.GetAt(StackFrame.AbsoluteIndex.kThisPtr); StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.JILRecord.classIndex; int fi = activation.JILRecord.funcIndex; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)svBlockDecl.opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = core.Rmem.FramePointer; int locals = activation.JILRecord.locals; FFIHandler handler = FFIHandlers[activation.ModuleType]; FFIActivationRecord r = activation; string className = ""; if (activation.JILRecord.classIndex > 0) { className = core.DSExecutable.classTable.ClassNodes[activation.JILRecord.classIndex].name; } bool gcThisPtr = false; List<ProtoCore.Type> argTypes = new List<Type>(r.ParameterTypes); ProcedureNode fNode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != ci) { fNode = interpreter.runtime.exe.classTable.ClassNodes[ci].vtable.procList[fi]; } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != fNode && fNode.isAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = svThisPtr.IsPointer && Constants.kInvalidPointer == (int)svThisPtr.opdata; if (isStaticCall) { thisPtrIndex = formalParameters.Count - 1; } argTypes.RemoveAt(thisPtrIndex); // Comment Jun: Execute() can handle a null this pointer. // But since we dont even need to to reach there if we dont have a valid this pointer, then just return null if (formalParameters[thisPtrIndex].IsNull) { core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kDereferencingNonPointer, ProtoCore.RuntimeData.WarningMessage.kDeferencingNonPointer); return StackValue.Null; } // These are the op types allowed. Validity.Assert(formalParameters[thisPtrIndex].IsPointer || formalParameters[thisPtrIndex].IsDefaultArgument); svThisPtr = formalParameters[thisPtrIndex]; gcThisPtr = true; formalParameters.RemoveAt(thisPtrIndex); } FFIFunctionPointer functionPointer = handler.GetFunctionPointer(r.ModuleName, className, r.FunctionName, argTypes, r.ReturnType); mFunctionPointer = Validate(functionPointer) ? functionPointer : null; mFunctionPointer.IsDNI = activation.IsDNI; if (mFunctionPointer == null) { return ProtoCore.DSASM.StackValue.Null; } { interpreter.runtime.executingBlock = core.RunningBlock; activation.JILRecord.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } List<StackValue> registers = new List<DSASM.StackValue>(); interpreter.runtime.SaveRegisters(registers); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = 0; StackFrameType callerType = (StackFrameType)stackFrame.GetAt(StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; // FFI calls do not have execution states core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, ProtoCore.DSASM.StackFrameType.kTypeFunction, depth, framePointer, registers, locals, 0); //is there a way the current stack be passed across and back into the managed runtime by FFI calling back into the language? //e.g. DCEnv* carrying all the stack information? look at how vmkit does this. // = jilMain.Run(ActivationRecord.JILRecord.pc, null, true); //double[] tempArray = GetUnderlyingArray<double>(jilMain.runtime.rmem.stack); Object ret = mFunctionPointer.Execute(c, interpreter); StackValue op; if (ret == null) { op = StackValue.Null; } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = StackValue.BuildInt((Int64)ret); } else if (ret is double) { op = StackValue.BuildDouble((double)ret); } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } // gc the parameters if (gcThisPtr)// && core.Options.EnableThisPointerFunctionOverload) { // thisptr is sent as parameter, so need to gc it. // but when running in expression interpreter mode, do not GC because in DSASM.Executive.DecRefCounter() related GC functions, // the reference count will not be changed in expression interpreter mode. if (core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { interpreter.runtime.Core.Rmem.Heap.GCRelease(new StackValue[] { svThisPtr }, interpreter.runtime); } } interpreter.runtime.Core.Rmem.Heap.GCRelease(formalParameters.ToArray(), interpreter.runtime); // increment the reference counter of the return value interpreter.runtime.GCRetain(op); // Clear the FFI stack frame // FFI stack frames have no local variables interpreter.runtime.rmem.FramePointer = (int)interpreter.runtime.rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; interpreter.runtime.rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + formalParameters.Count); return op; //DSASM.Mirror.ExecutionMirror.Unpack(op, core.heap, core); } } }
public override StackValue Execute(int codeblock, int entry, ProtoCore.Runtime.Context callContext, List <Instruction> breakpoints, ProtoCore.DebugServices.EventSink sink, bool fepRun = false) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core); CurrentDSASMExec = interpreter.runtime; return(interpreter.Run(breakpoints, codeblock, entry, ProtoCore.Language.kImperative)); }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { int nParamCount = mArgTypes.Length; int paramCount = mArgTypes.Length; int envSize = IsDNI ? 2 : 0; int totalParamCount = paramCount + envSize; List<Object> parameters = new List<object>(); List<ProtoCore.DSASM.StackValue> s = dsi.runtime.rmem.Stack; Object thisObject = null; FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.Core); if (!ReflectionInfo.IsStatic) { try { thisObject = marshaller.UnMarshal(s.Last(), c, dsi, ReflectionInfo.DeclaringType); } catch (InvalidOperationException) { string message = String.Format(ProtoCore.RuntimeData.WarningMessage.kFFIFailedToObtainThisObject, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, message); return null; } if (thisObject == null) return null; //Can't call a method on null object. } ParameterInfo[] paraminfos = ReflectionInfo.GetParameters(); for (int i = 0; i < mArgTypes.Length; ++i) { // Comment Jun: FFI function stack frames do not contain locals int locals = 0; int relative = 0 - ProtoCore.DSASM.StackFrame.kStackFrameSize - locals - i - 1; ProtoCore.DSASM.StackValue opArg = dsi.runtime.rmem.GetAtRelative(relative); try { Type paramType = paraminfos[i].ParameterType; object param = marshaller.UnMarshal(opArg, c, dsi, paramType); //null is passed for a value type, so we must return null //rather than interpreting any value from null. fix defect 1462014 if (!paramType.IsGenericType && paramType.IsValueType && param == null) throw new System.InvalidCastException(string.Format("Null value cannot be cast to {0}", paraminfos[i].ParameterType.Name)); parameters.Add(param); } catch (System.InvalidCastException ex) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); return null; } catch (InvalidOperationException) { string message = String.Format(ProtoCore.RuntimeData.WarningMessage.kFFIFailedToObtainObject, paraminfos[i].ParameterType.Name, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, message); return null; } } object ret = null; StackValue dsRetValue = StackUtils.BuildNull(); try { ret = InvokeFunctionPointer(thisObject, parameters.Count > 0 ? parameters.ToArray() : null); //Reduce to singleton if the attribute is specified. ret = ReflectionInfo.ReduceReturnedCollectionToSingleton(ret); dsRetValue = marshaller.Marshal(ret, c, dsi, mReturnType); } catch (DllNotFoundException ex) { if (ex.InnerException != null) { dsi.LogSemanticError(ex.InnerException.Message); } dsi.LogSemanticError(ex.Message); } catch (System.Reflection.TargetException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.Reflection.TargetInvocationException ex) { if (ex.InnerException != null) { System.Exception exc = ex.InnerException; if (exc is System.ArgumentException) dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kInvalidArguments, ErrorString(exc)); else if (exc is System.NullReferenceException) dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ErrorString(null)); else dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ErrorString(exc)); } else dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ErrorString(ex)); } catch (System.Reflection.TargetParameterCountException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.MethodAccessException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.InvalidOperationException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.NotSupportedException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.ArgumentException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kInvalidArguments, ErrorString(ex.InnerException)); } else dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kInvalidArguments, ErrorString(ex)); } catch (Exception ex) { if (ex.InnerException != null) { dsi.LogSemanticError(ErrorString(ex.InnerException)); } dsi.LogSemanticError(ErrorString(ex)); } return dsRetValue; }
private ExecutionMirror Execute(int programCounterToExecuteFrom, List<Instruction> breakpoints, bool fepRun = false) { runtimeCore.Breakpoints = breakpoints; resumeBlockID = runtimeCore.RunningBlock; if (runtimeCore.DebugProps.FirstStackFrame != null) { runtimeCore.DebugProps.FirstStackFrame.FramePointer = core.GlobOffset; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); runtimeCore.DebugProps.FirstStackFrame.TX = svCallConvention; } // Initialize the entry point interpreter int locals = 0; // This is the global scope, there are no locals ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore); runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; runtimeCore.CurrentExecutive.CurrentDSASMExec.Bounce( resumeBlockID, programCounterToExecuteFrom, runtimeCore.DebugProps.FirstStackFrame, locals, fepRun, null, breakpoints); return new ExecutionMirror(runtimeCore.CurrentExecutive.CurrentDSASMExec, runtimeCore); }
public override StackValue Execute(ProtoCore.Runtime.Context c, List<StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); ProtoCore.DSASM.Executive oldDSASMExec = null; if (core.CurrentExecutive != null) { oldDSASMExec = core.CurrentExecutive.CurrentDSASMExec; core.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; } // Assert for the block type activation.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // Push Execution states int execStateSize = 0; if (null != stackFrame.ExecutionStates) { execStateSize = stackFrame.ExecutionStates.Length; // ExecutionStates are in lexical order // Push them in reverse order (similar to args) so they can be retrieved in sequence // Retrieveing the executing states occur on function return for (int n = execStateSize - 1; n >= 0 ; --n) { StackValue svState = stackFrame.ExecutionStates[n]; Validity.Assert(svState.optype == DSASM.AddressType.Boolean); interpreter.Push(svState); } } // Push Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } StackValue svThisPtr = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr); StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); // Jun: Make sure we have no empty or unaligned frame data Validity.Assert(DSASM.StackFrame.kStackFrameSize == stackFrame.Frame.Length); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.classIndex; int fi = activation.funcIndex; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)svBlockDecl.opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = core.Rmem.FramePointer; int locals = activation.locals; // Update the running block to tell the execution engine which set of instruction to execute // TODO(Jun/Jiong): Considering store the orig block id to stack frame int origRunningBlock = core.RunningBlock; core.RunningBlock = (int)svBlockDecl.opdata; // Set SX register interpreter.runtime.SX = svBlockDecl; DSASM.StackFrameType callerType = (DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; List<StackValue> registers = new List<DSASM.StackValue>(); StackValue svCallConvention; bool isDispose = CoreUtils.IsDisposeMethod(procedureNode.name); bool explicitCall = !c.IsReplicating && !c.IsImplicitCall && !isDispose; if (explicitCall) { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kExplicit); } else { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kImplicit); } stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kRegisterTX, svCallConvention); interpreter.runtime.TX = svCallConvention; // Set SX register stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kRegisterSX, svBlockDecl); interpreter.runtime.SX = svBlockDecl; // TODO Jun: // The stackframe carries the current set of registers // Determine if this can be done even for the non explicit call implementation registers.AddRange(stackFrame.GetRegisters()); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameDepth).opdata; DSASM.StackFrameType type = (DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameType).opdata; Validity.Assert(depth == 0); Validity.Assert(type == DSASM.StackFrameType.kTypeFunction); core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, type, depth, framePointer, registers, locals, execStateSize); StackValue svRet; if (explicitCall) { svRet = ProtoCore.DSASM.StackValue.BuildExplicitCall(activation.pc); } else { if (core.ExecMode != DSASM.InterpreterMode.kExpressionInterpreter && core.Options.IDEDebugMode) { svRet = interpreter.Run(core.Breakpoints, core.RunningBlock, activation.pc, Language.kInvalid); } else { svRet = interpreter.Run(core.RunningBlock, activation.pc, Language.kInvalid); } core.RunningBlock = origRunningBlock; } if (core.CurrentExecutive != null) { core.CurrentExecutive.CurrentDSASMExec = oldDSASMExec; } return svRet; //DSASM.Mirror.ExecutionMirror.Unpack(svRet, core.heap, core); }
public override StackValue Execute(ProtoCore.Runtime.Context c, List<StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, RuntimeCore runtimeCore) { // ensure there is no data race, function resolution and execution happens in parallel // but for FFI we want it to be serial cause the code we are calling into may not cope // with parallelism. // // we are always looking and putting our function pointers in handler with each lang // so better lock for FFIHandler (being static) it will be good object to lock // lock (FFIHandlers) { Interpreter interpreter = new Interpreter(runtimeCore, true); // Setup the stack frame data StackValue svThisPtr = stackFrame.ThisPtr; int ci = activation.JILRecord.classIndex; int fi = activation.JILRecord.funcIndex; int returnAddr = stackFrame.ReturnPC; int blockDecl = stackFrame.FunctionBlock; int blockCaller = stackFrame.FunctionCallerBlock; int framePointer = runtimeCore.RuntimeMemory.FramePointer; int locals = activation.JILRecord.locals; FFIHandler handler = FFIHandlers[activation.ModuleType]; FFIActivationRecord r = activation; string className = ""; if (activation.JILRecord.classIndex > 0) { className = runtimeCore.DSExecutable.classTable.ClassNodes[activation.JILRecord.classIndex].Name; } List<ProtoCore.Type> argTypes = new List<Type>(r.ParameterTypes); ProcedureNode fNode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != ci) { fNode = interpreter.runtime.exe.classTable.ClassNodes[ci].ProcTable.Procedures[fi]; } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != fNode && fNode.IsAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = svThisPtr.IsPointer && Constants.kInvalidPointer == svThisPtr.Pointer; if (isStaticCall) { stackFrame.ThisPtr = formalParameters[thisPtrIndex]; } argTypes.RemoveAt(thisPtrIndex); // Comment Jun: Execute() can handle a null this pointer. // But since we dont even need to to reach there if we dont have a valid this pointer, then just return null if (formalParameters[thisPtrIndex].IsNull) { runtimeCore.RuntimeStatus.LogWarning(ProtoCore.Runtime.WarningID.DereferencingNonPointer, Resources.kDeferencingNonPointer); return StackValue.Null; } // These are the op types allowed. Validity.Assert(formalParameters[thisPtrIndex].IsPointer || formalParameters[thisPtrIndex].IsDefaultArgument); svThisPtr = formalParameters[thisPtrIndex]; formalParameters.RemoveAt(thisPtrIndex); } FFIFunctionPointer functionPointer = handler.GetFunctionPointer(r.ModuleName, className, r.FunctionName, argTypes, r.ReturnType); mFunctionPointer = Validate(functionPointer) ? functionPointer : null; mFunctionPointer.IsDNI = activation.IsDNI; if (mFunctionPointer == null) { return ProtoCore.DSASM.StackValue.Null; } { interpreter.runtime.executingBlock = runtimeCore.RunningBlock; activation.JILRecord.globs = runtimeCore.DSExecutable.runtimeSymbols[runtimeCore.RunningBlock].GetGlobalSize(); // Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } List<StackValue> registers = new List<DSASM.StackValue>(); interpreter.runtime.SaveRegisters(registers); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = 0; StackFrameType callerType = stackFrame.CallerStackFrameType; // FFI calls do not have execution states runtimeCore.RuntimeMemory.PushFrameForLocals(locals); StackFrame newStackFrame = new StackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, StackFrameType.Function, depth, framePointer, registers, 0); runtimeCore.RuntimeMemory.PushStackFrame(newStackFrame); //is there a way the current stack be passed across and back into the managed runtime by FFI calling back into the language? //e.g. DCEnv* carrying all the stack information? look at how vmkit does this. // = jilMain.Run(ActivationRecord.JILRecord.pc, null, true); //double[] tempArray = GetUnderlyingArray<double>(jilMain.runtime.rmem.stack); Object ret = mFunctionPointer.Execute(c, interpreter); StackValue op; if (ret == null) { op = StackValue.Null; } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = StackValue.BuildInt((Int64)ret); } else if (ret is double) { op = StackValue.BuildDouble((double)ret); } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } // Clear the FFI stack frame // FFI stack frames have no local variables interpreter.runtime.rmem.FramePointer = (int)interpreter.runtime.rmem.GetAtRelative(StackFrame.FrameIndexFramePointer).IntegerValue; interpreter.runtime.rmem.PopFrame(StackFrame.StackFrameSize + formalParameters.Count); return op; } } }
public abstract Object Execute(ProtoCore.Runtime.Context c, ProtoCore.DSASM.Interpreter dsi);
/// <summary> /// ExecuteLive is called by the liverunner where a persistent RuntimeCore is provided /// ExecuteLive assumes only a single global scope /// </summary> /// <param name="core"></param> /// <param name="runtimeCore"></param> /// <param name="runningBlock"></param> /// <param name="staticContext"></param> /// <param name="runtimeContext"></param> /// <returns></returns> public ProtoCore.RuntimeCore ExecuteLive(ProtoCore.Core core, ProtoCore.RuntimeCore runtimeCore) { try { Executable exe = runtimeCore.DSExecutable; Validity.Assert(exe.CodeBlocks.Count == 1); CodeBlock codeBlock = runtimeCore.DSExecutable.CodeBlocks[0]; int codeBlockID = codeBlock.codeBlockId; // Comment Jun: // On first bounce, the stackframe depth is initialized to -1 in the Stackfame constructor. // Passing it to bounce() increments it so the first depth is always 0 ProtoCore.DSASM.StackFrame stackFrame = new ProtoCore.DSASM.StackFrame(core.GlobOffset); stackFrame.FramePointer = runtimeCore.RuntimeMemory.FramePointer; // Comment Jun: Tell the new bounce stackframe that this is an implicit bounce // Register TX is used for this. StackValue svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); stackFrame.TX = svCallConvention; // Initialize the entry point interpreter int locals = 0; // This is the global scope, there are no locals if (runtimeCore.CurrentExecutive.CurrentDSASMExec == null) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore); runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; } runtimeCore.CurrentExecutive.CurrentDSASMExec.BounceUsingExecutive( runtimeCore.CurrentExecutive.CurrentDSASMExec, codeBlock.codeBlockId, runtimeCore.StartPC, stackFrame, locals); runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd); } catch { runtimeCore.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd); throw; } return runtimeCore; }
public override StackValue Execute(ProtoCore.Runtime.Context c, List<StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, RuntimeCore runtimeCore) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore, true); ProtoCore.DSASM.Executive oldDSASMExec = null; if (runtimeCore.CurrentExecutive != null) { oldDSASMExec = runtimeCore.CurrentExecutive.CurrentDSASMExec; runtimeCore.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; } // Assert for the block type activation.globs = runtimeCore.DSExecutable.runtimeSymbols[runtimeCore.RunningBlock].GetGlobalSize(); // // Comment Jun: // Storing execution states is relevant only if the current scope is a function, // as this mechanism is used to keep track of maintining execution states of recursive calls // This mechanism should also be ignored if the function call is non-recursive as it does not need to maintains state in that case int execStateSize = procedureNode.GraphNodeList.Count; stackFrame.ExecutionStateSize = execStateSize; for (int n = execStateSize - 1; n >= 0; --n) { AssociativeGraph.GraphNode gnode = procedureNode.GraphNodeList[n]; interpreter.Push(StackValue.BuildBoolean(gnode.isDirty)); } // Push Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } StackValue svThisPtr = stackFrame.ThisPtr; StackValue svBlockDecl = StackValue.BuildBlockIndex(stackFrame.FunctionBlock); // Jun: Make sure we have no empty or unaligned frame data Validity.Assert(DSASM.StackFrame.kStackFrameSize == stackFrame.Frame.Length); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.classIndex; int fi = activation.funcIndex; int returnAddr = stackFrame.ReturnPC; int blockDecl = stackFrame.FunctionBlock; int blockCaller = stackFrame.FunctionCallerBlock; int framePointer = runtimeCore.RuntimeMemory.FramePointer; int locals = activation.locals; // Update the running block to tell the execution engine which set of instruction to execute // TODO(Jun/Jiong): Considering store the orig block id to stack frame int origRunningBlock = runtimeCore.RunningBlock; runtimeCore.RunningBlock = (int)svBlockDecl.opdata; // Set SX register interpreter.runtime.SX = svBlockDecl; StackFrameType callerType = stackFrame.CallerStackFrameType; List<StackValue> registers = new List<DSASM.StackValue>(); StackValue svCallConvention; bool isDispose = CoreUtils.IsDisposeMethod(procedureNode.Name); bool explicitCall = !c.IsReplicating && !c.IsImplicitCall && !isDispose; if (explicitCall) { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kExplicit); } else { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kImplicit); } stackFrame.TX = svCallConvention; interpreter.runtime.TX = svCallConvention; // Set SX register stackFrame.SX = svBlockDecl; interpreter.runtime.SX = svBlockDecl; // TODO Jun: // The stackframe carries the current set of registers // Determine if this can be done even for the non explicit call implementation registers.AddRange(stackFrame.GetRegisters()); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = stackFrame.Depth; DSASM.StackFrameType type = stackFrame.StackFrameType; Validity.Assert(depth == 0); Validity.Assert(type == DSASM.StackFrameType.kTypeFunction); runtimeCore.RuntimeMemory.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, type, depth, framePointer, registers, locals, execStateSize); StackValue svRet; if (explicitCall) { svRet = ProtoCore.DSASM.StackValue.BuildExplicitCall(activation.pc); } else { svRet = interpreter.Run(runtimeCore.RunningBlock, activation.pc, Language.kInvalid, runtimeCore.Breakpoints); runtimeCore.RunningBlock = origRunningBlock; } if (runtimeCore.CurrentExecutive != null) { runtimeCore.CurrentExecutive.CurrentDSASMExec = oldDSASMExec; } return svRet; //DSASM.Mirror.ExecutionMirror.Unpack(svRet, core.heap, core); }
public override StackValue Execute(int codeblock, int entry, ProtoCore.Runtime.Context callContext, List<Instruction> breakpoints, ProtoCore.DebugServices.EventSink sink, bool fepRun = false) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core); CurrentDSASMExec = interpreter.runtime; return interpreter.Run(breakpoints, codeblock, entry, ProtoCore.Language.kImperative); }
private object GetArray(StackValue o, ProtoCore.DSASM.Interpreter dsi, out int size) { size = 0; int ptr = (int)o.opdata; HeapElement hs = dsi.runtime.rmem.Heap.Heaplist[ptr]; size = hs.VisibleSize; if (size == 0) { return(null); } IList elements = null; var opType = hs.Stack[0].optype; if (opType == AddressType.Boolean) { elements = new List <bool>(); } else if (opType == AddressType.Double) { elements = new List <double>(); } else if (opType == AddressType.Int) { elements = new List <int>(); } else if (opType == AddressType.ArrayPointer) { throw new ArgumentException("FFI does not support nested arrays"); } else { throw new ArgumentException(string.Format("Argument of type {0} is not supported for FFI Marshalling", opType.ToString())); } for (int idx = 0; idx < size; ++idx) { var op = hs.Stack[idx]; if (opType == AddressType.Double) { elements.Add(op.opdata_d); } else if (opType == AddressType.Int) { elements.Add((int)op.opdata); } else if (opType == AddressType.Boolean) { elements.Add(op.opdata == 0 ? true : false); } } // now based on the type of element in ds-array // create a new array and return it // if (opType == AddressType.Double) { double[] arr = new double[size]; elements.CopyTo(arr, 0); return(arr); } else if (opType == AddressType.Int) { int[] arr = new int[size]; elements.CopyTo(arr, 0); return(arr); } else if (opType == AddressType.Boolean) { bool[] arr = new bool[size]; elements.CopyTo(arr, 0); return(arr); } else { size = 0; return(null); } }
public abstract Object Execute(ProtoCore.Runtime.Context c, ProtoCore.DSASM.Interpreter dsi, List <StackValue> stack);
public override StackValue Execute(int codeblock, int entry, ProtoCore.Runtime.Context callContext, System.Collections.Generic.List<Instruction> breakpoints, ProtoCore.DebugServices.EventSink sink = null, bool fepRun = false) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, fepRun); CurrentDSASMExec = interpreter.runtime; StackValue sv = interpreter.Run(breakpoints, codeblock, entry, Language.kAssociative); return sv; }
public StackValue Execute(int codeblock, int entry, bool fepRun = false, System.Collections.Generic.List<Instruction> breakpoints = null) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(runtimeCore, fepRun); CurrentDSASMExec = interpreter.runtime; return interpreter.Run(codeblock, entry, CurrentDSASMExec.executingLanguage, breakpoints); }
private object ConvertReturnValue(object retVal, ProtoCore.Runtime.Context context, ProtoCore.DSASM.Interpreter dsi) { object returnValue = retVal; // these are arrays! if (mReturnType.IsIndexable) { // we have already asserted that these can be of rank 1 only, for now // IntPtr arrPtr = (IntPtr)retVal; if (arrPtr == IntPtr.Zero) { return(StackValue.Null); } _Array arr = (_Array)Marshal.PtrToStructure(arrPtr, typeof(_Array)); if (mReturnType.Name == "double") { double[] elements = new double[arr.numElems]; Marshal.Copy(arr.elements, elements, 0, arr.numElems); // free up the memory Marshal.FreeCoTaskMem(arr.elements); Marshal.FreeCoTaskMem(arrPtr); returnValue = ConvertCSArrayToDSArray(elements, dsi); } else if (mReturnType.Name == "int") { int[] elements = new int[arr.numElems]; Marshal.Copy(arr.elements, elements, 0, arr.numElems); return(elements); } else { throw new ArgumentException(string.Format("FFI: unknown type {0} to marshall", mReturnType.Name)); } } return(returnValue); }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { List<Object> parameters = new List<object>(); List<StackValue> s = dsi.runtime.rmem.Stack; Object thisObject = null; FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.RuntimeCore); if (!ReflectionInfo.IsStatic) { try { thisObject = marshaller.UnMarshal(s.Last(), c, dsi, ReflectionInfo.DeclaringType); } catch (InvalidOperationException) { string message = String.Format(Resources.kFFIFailedToObtainThisObject, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, message); return null; } if (thisObject == null) return null; //Can't call a method on null object. } ParameterInfo[] paraminfos = ReflectionInfo.GetParameters(); for (int i = 0; i < mArgTypes.Length; ++i) { // Comment Jun: FFI function stack frames do not contain locals int locals = 0; int relative = 0 - ProtoCore.DSASM.StackFrame.kStackFrameSize - locals - i - 1; StackValue opArg = dsi.runtime.rmem.GetAtRelative(relative); try { Type paramType = paraminfos[i].ParameterType; object param = null; if (opArg.IsDefaultArgument) param = Type.Missing; else param = marshaller.UnMarshal(opArg, c, dsi, paramType); //null is passed for a value type, so we must return null //rather than interpreting any value from null. fix defect 1462014 if (!paramType.IsGenericType && paramType.IsValueType && param == null) { //This is going to cause a cast exception. This is a very frequently called problem, so we want to short-cut the execution dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, string.Format(Resources.FailedToCastFromNull, paraminfos[i].ParameterType.Name)); return null; //throw new System.InvalidCastException(string.Format("Null value cannot be cast to {0}", paraminfos[i].ParameterType.Name)); } parameters.Add(param); } catch (System.InvalidCastException ex) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); return null; } catch (InvalidOperationException) { string message = String.Format(Resources.kFFIFailedToObtainObject, paraminfos[i].ParameterType.Name, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, message); return null; } } return InvokeFunctionPointerNoThrow(c, dsi, thisObject, parameters.Count > 0 ? parameters.ToArray() : null); }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { Object retVal = base.Execute(c, dsi); List<ProtoCore.DSASM.StackValue> s = dsi.runtime.rmem.Stack; FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.Core); marshaller.OnDispose(s.Last(), c, dsi); //Notify marshler for dispose. return retVal; }
public override StackValue Execute(ProtoCore.Runtime.Context c, List <StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); ProtoCore.DSASM.Executive oldDSASMExec = null; if (core.CurrentExecutive != null) { oldDSASMExec = core.CurrentExecutive.CurrentDSASMExec; core.CurrentExecutive.CurrentDSASMExec = interpreter.runtime; } // Assert for the block type activation.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // // Comment Jun: // Storing execution states is relevant only if the current scope is a function, // as this mechanism is used to keep track of maintining execution states of recursive calls // This mechanism should also be ignored if the function call is non-recursive as it does not need to maintains state in that case int execStateSize = procedureNode.GraphNodeList.Count; stackFrame.ExecutionStateSize = execStateSize; for (int n = execStateSize - 1; n >= 0; --n) { AssociativeGraph.GraphNode gnode = procedureNode.GraphNodeList[n]; interpreter.Push(StackValue.BuildBoolean(gnode.isDirty)); } // Push Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } StackValue svThisPtr = stackFrame.ThisPtr; StackValue svBlockDecl = StackValue.BuildBlockIndex(stackFrame.FunctionBlock); // Jun: Make sure we have no empty or unaligned frame data Validity.Assert(DSASM.StackFrame.kStackFrameSize == stackFrame.Frame.Length); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.classIndex; int fi = activation.funcIndex; int returnAddr = stackFrame.ReturnPC; int blockDecl = stackFrame.FunctionBlock; int blockCaller = stackFrame.FunctionCallerBlock; int framePointer = core.Rmem.FramePointer; int locals = activation.locals; // Update the running block to tell the execution engine which set of instruction to execute // TODO(Jun/Jiong): Considering store the orig block id to stack frame int origRunningBlock = core.RunningBlock; core.RunningBlock = (int)svBlockDecl.opdata; // Set SX register interpreter.runtime.SX = svBlockDecl; StackFrameType callerType = stackFrame.CallerStackFrameType; List <StackValue> registers = new List <DSASM.StackValue>(); StackValue svCallConvention; bool isDispose = CoreUtils.IsDisposeMethod(procedureNode.name); bool explicitCall = !c.IsReplicating && !c.IsImplicitCall && !isDispose; if (explicitCall) { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kExplicit); } else { svCallConvention = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.CallType.kImplicit); } stackFrame.TX = svCallConvention; interpreter.runtime.TX = svCallConvention; // Set SX register stackFrame.SX = svBlockDecl; interpreter.runtime.SX = svBlockDecl; // TODO Jun: // The stackframe carries the current set of registers // Determine if this can be done even for the non explicit call implementation registers.AddRange(stackFrame.GetRegisters()); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = stackFrame.Depth; DSASM.StackFrameType type = stackFrame.StackFrameType; Validity.Assert(depth == 0); Validity.Assert(type == DSASM.StackFrameType.kTypeFunction); core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, type, depth, framePointer, registers, locals, execStateSize); StackValue svRet; if (explicitCall) { svRet = ProtoCore.DSASM.StackValue.BuildExplicitCall(activation.pc); } else { svRet = interpreter.Run(core.RunningBlock, activation.pc, Language.kInvalid, core.Breakpoints); core.RunningBlock = origRunningBlock; } if (core.CurrentExecutive != null) { core.CurrentExecutive.CurrentDSASMExec = oldDSASMExec; } return(svRet); //DSASM.Mirror.ExecutionMirror.Unpack(svRet, core.heap, core); }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { List<StackValue> s = dsi.runtime.rmem.Stack; FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.RuntimeCore); var thisObject = marshaller.UnMarshal(s.Last(), c, dsi, ReflectionInfo.DeclaringType); //Notify marshler for dispose. marshaller.OnDispose(s.Last(), c, dsi); Object retVal = null; if (ReflectionInfo.IsWrapperOf(CLRModuleType.DisposeMethod)) { // For those FFI objects that are disposable but don't provide // Dispose() method in their classes, they will share a same // Dispose() method from CLRModuleType.DisposeMethod. We need // to manually dispose them. if (thisObject != null && thisObject is IDisposable) { var disposable = thisObject as IDisposable; disposable.Dispose(); } } else { retVal = InvokeFunctionPointerNoThrow(c, dsi, thisObject, null); } return retVal; }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { Object retVal = base.Execute(c, dsi); if (retVal == null) { return null; } StackValue propValue = (StackValue)retVal; StackValue thisObject = dsi.runtime.rmem.Stack.Last(); bool isValidPointer = thisObject.IsPointer && thisObject.opdata != Constants.kInvalidIndex; if (isValidPointer && propValue.IsReferenceType) { int classIndex = thisObject.metaData.type; if (classIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { var runtimeCore = dsi.runtime.RuntimeCore; int idx = runtimeCore.DSExecutable.classTable.ClassNodes[classIndex].symbols.IndexOf(PropertyName); var obj = runtimeCore.Heap.ToHeapObject<DSObject>(thisObject); StackValue oldValue = obj.GetValueFromIndex(idx, runtimeCore); if (!StackUtils.Equals(oldValue, propValue)) { obj.SetValueAtIndex(idx, propValue, runtimeCore); } } } return retVal; }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { List<Object> parameters = new List<object>(); List<StackValue> s = dsi.runtime.rmem.Stack; Object thisObject = null; FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.RuntimeCore); if (!ReflectionInfo.IsStatic) { try { thisObject = marshaller.UnMarshal(s.Last(), c, dsi, ReflectionInfo.DeclaringType); } catch (InvalidOperationException) { string message = String.Format(Resources.kFFIFailedToObtainThisObject, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.Runtime.WarningID.AccessViolation, message); return null; } if (thisObject == null) 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) { // Comment Jun: FFI function stack frames do not contain locals int locals = 0; int relative = 0 - ProtoCore.DSASM.StackFrame.StackFrameSize - locals - i - 1; StackValue opArg = dsi.runtime.rmem.GetAtRelative(relative); try { Type paramType = paraminfos[i].Info.ParameterType; object param = null; if (opArg.IsDefaultArgument) param = Type.Missing; else param = marshaller.UnMarshal(opArg, c, dsi, paramType); if (paraminfos[i].KeepReference && opArg.IsReferenceType) { referencedParameters.Add(opArg); } //null is passed for a value type, so we must return null //rather than interpreting any value from null. fix defect 1462014 if (!paramType.IsGenericType && paramType.IsValueType && param == null) { //This is going to cause a cast exception. This is a very frequently called problem, so we want to short-cut the execution dsi.LogWarning(ProtoCore.Runtime.WarningID.AccessViolation, string.Format(Resources.FailedToCastFromNull, paraminfos[i].Info.ParameterType.Name)); return null; //throw new System.InvalidCastException(string.Format("Null value cannot be cast to {0}", paraminfos[i].ParameterType.Name)); } parameters.Add(param); } catch (System.InvalidCastException ex) { dsi.LogWarning(ProtoCore.Runtime.WarningID.AccessViolation, ex.Message); return null; } catch (InvalidOperationException) { string message = String.Format(Resources.kFFIFailedToObtainObject, paraminfos[i].Info.ParameterType.Name, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.Runtime.WarningID.AccessViolation, message); return null; } } var ret = InvokeFunctionPointerNoThrow(c, dsi, thisObject, parameters.Count > 0 ? parameters.ToArray() : null); if (ReflectionInfo.KeepReferenceThis && thisObject != null) { referencedParameters.Add(s.Last()); } int count = referencedParameters.Count; if (count > 0 && (ret is StackValue)) { // If there is a parameter who has attribute [KeepReference], // it means this parameter will cross the DesignScript boundary // and be referenced by C# object. Therefore, when its DS // wrapper object is out of scope, we shouldn't dispose it; // otherwise that C# object will reference to an invalid object. // // Similarly, if the method has attribute [KeepReferenceThis], // it means the return object will reference to this object // internally, so we shouldn't dispose this object. // // The hack here is to treat them like properties in the return // object. Note all DS wrapper objects are dummy objects who // haven't any members. By allocating extra space on the heap, // we store the reference in the return object so that the // parameter will have the same lifecycle as the return object. // // One case need to consider about is the type of return value. // If the return value is an array, we have to recursively go // into the array and expand the element, instead of setting // these hidden information directly on the array. try { SetReferenceObjects((StackValue)ret, referencedParameters, dsi.runtime); } catch (RunOutOfMemoryException) { dsi.runtime.RuntimeCore.RuntimeStatus.LogWarning(ProtoCore.Runtime.WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return StackValue.Null; } } return ret; }