private void Init( StackValue thisPtr, int classIndex, int functionIndex, int returnAddress, int functionBlockIndex, int callerBlockIndex, StackFrameType callerStackFrameType, StackFrameType stackFrameType, int depth, int framePointer, int blockIndex, List<StackValue> registers, int execStateSize) { Frame = new StackValue[StackFrameSize]; Frame[AbsoluteIndex.ThisPtr] = thisPtr; Frame[AbsoluteIndex.ClassIndex] = StackValue.BuildClassIndex(classIndex); Frame[AbsoluteIndex.FunctionIndex] = StackValue.BuildFunctionIndex(functionIndex); Frame[AbsoluteIndex.ReturnAddress] = StackValue.BuildInt(returnAddress); Frame[AbsoluteIndex.FunctionBlockIndex] = StackValue.BuildBlockIndex(functionBlockIndex); Frame[AbsoluteIndex.CallerBlockIndex] = StackValue.BuildBlockIndex(callerBlockIndex); Frame[AbsoluteIndex.CallerStackFrameType] = StackValue.BuildFrameType((int)callerStackFrameType); Frame[AbsoluteIndex.StackFrameType] = StackValue.BuildFrameType((int)stackFrameType); Frame[AbsoluteIndex.StackFrameDepth] = StackValue.BuildInt(depth); Frame[AbsoluteIndex.LocalVariableCount] = StackValue.BuildInt(0); Frame[AbsoluteIndex.ExecutionStates] = StackValue.BuildInt(execStateSize); Frame[AbsoluteIndex.BlockIndex] = StackValue.BuildBlockIndex(blockIndex); Frame[AbsoluteIndex.RX] = registers[0]; Frame[AbsoluteIndex.TX] = registers[1]; Frame[AbsoluteIndex.FramePointer] = StackValue.BuildInt(framePointer); }
private void Init( StackValue thisPtr, int classIndex, int functionIndex, int returnAddress, int functionBlockIndex, int callerBlockIndex, StackFrameType callerStackFrameType, StackFrameType stackFrameType, int depth, int framePointer, int blockIndex, List <StackValue> registers, int execStateSize) { Frame = new StackValue[StackFrameSize]; Frame[AbsoluteIndex.ThisPtr] = thisPtr; Frame[AbsoluteIndex.ClassIndex] = StackValue.BuildClassIndex(classIndex); Frame[AbsoluteIndex.FunctionIndex] = StackValue.BuildFunctionIndex(functionIndex); Frame[AbsoluteIndex.ReturnAddress] = StackValue.BuildInt(returnAddress); Frame[AbsoluteIndex.FunctionBlockIndex] = StackValue.BuildBlockIndex(functionBlockIndex); Frame[AbsoluteIndex.CallerBlockIndex] = StackValue.BuildBlockIndex(callerBlockIndex); Frame[AbsoluteIndex.CallerStackFrameType] = StackValue.BuildFrameType((int)callerStackFrameType); Frame[AbsoluteIndex.StackFrameType] = StackValue.BuildFrameType((int)stackFrameType); Frame[AbsoluteIndex.StackFrameDepth] = StackValue.BuildInt(depth); Frame[AbsoluteIndex.LocalVariableCount] = StackValue.BuildInt(0); Frame[AbsoluteIndex.ExecutionStates] = StackValue.BuildInt(execStateSize); Frame[AbsoluteIndex.BlockIndex] = StackValue.BuildBlockIndex(blockIndex); Frame[AbsoluteIndex.RX] = registers[0]; Frame[AbsoluteIndex.TX] = registers[1]; Frame[AbsoluteIndex.FramePointer] = StackValue.BuildInt(framePointer); }
public static SDCombinedStackFrame ToSDModel(this ClrStackFrame frame) { StackFrameType type = (frame.Kind == ClrStackFrameType.ManagedMethod) ? StackFrameType.Managed : (frame.Kind == ClrStackFrameType.Runtime) ? StackFrameType.Special : /* here be dragons */ StackFrameType.Special; string methodName; string moduleName = string.Empty; if (frame.Method == null) { methodName = frame.DisplayString; //for example GCFrame } else { methodName = frame.Method.GetFullSignature(); if (frame.Method.Type != null) { moduleName = Path.GetFileNameWithoutExtension(frame.Method.Type.Module.Name); if (string.IsNullOrEmpty(moduleName)) { moduleName = "UNKNOWN"; } } } return(new SDCombinedStackFrame(type, frame.InstructionPointer, frame.StackPointer, methodName, moduleName, frame.Method.NativeCode)); }
public SDCombinedStackFrame(StackFrameType type, ulong instructionPointer, ulong stackPointer, string methodName, string moduleName, ulong nativeCode) { Type = type; InstructionPointer = instructionPointer; StackPointer = stackPointer; MethodName = methodName; ModuleName = moduleName; // calculate IL offset with instruction pointer of frame and instruction pointer // in the target dump file of the start of the method's assembly OffsetInMethod = InstructionPointer - nativeCode; }
public SDCombinedStackFrame(StackFrameType type, string moduleName, string methodName, ulong offsetInMethod, ulong ip, ulong sp, ulong returnOffset, ulong spOffset, SDFileAndLineNumber sourceInfo) { this.Type = type; this.ModuleName = moduleName; this.MethodName = methodName; this.OffsetInMethod = offsetInMethod; this.InstructionPointer = ip; this.StackPointer = sp; this.ReturnOffset = returnOffset; this.LinkedStackFrame = null; this.StackPointerOffset = spOffset; this.SourceInfo = sourceInfo; }
public SDCombinedStackFrame(StackFrameType type, string moduleName, string methodName, ulong offsetInMethod, ulong instructionPointer, ulong stackPointer, ulong returnOffset, SDCombinedStackFrame linkedFrame) { this.Type = type; this.ModuleName = moduleName; this.MethodName = methodName; this.OffsetInMethod = offsetInMethod; this.InstructionPointer = instructionPointer; this.StackPointer = stackPointer; this.ReturnOffset = returnOffset; this.LinkedStackFrame = linkedFrame; }
public StackValue Evaluate(List <StackValue> args, StackFrame stackFrame) { // // Build the stackframe int classScopeCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kClass).opdata; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)mProcNode.runtimeIndex; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = mRunTime.runtime.Core.Rmem.FramePointer; StackValue thisPtr = StackUtils.BuildPointer(-1); // Comment Jun: the caller type is the current type in the stackframe StackFrameType callerType = (StackFrameType)stackFrame.GetAt(StackFrame.AbsoluteIndex.kStackFrameType).opdata; StackFrameType type = StackFrameType.kTypeFunction; int depth = 0; List <StackValue> registers = new List <StackValue>(); // Comment Jun: Calling convention data is stored on the TX register StackValue svCallconvention = StackUtils.BuildNode(AddressType.CallingConvention, (long)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); mRunTime.runtime.TX = svCallconvention; StackValue svBlockDecl = StackUtils.BuildNode(AddressType.BlockIndex, blockDecl); mRunTime.runtime.SX = svBlockDecl; mRunTime.runtime.SaveRegisters(registers); ProtoCore.DSASM.StackFrame newStackFrame = new StackFrame(thisPtr, classScopeCaller, 1, returnAddr, blockDecl, blockCaller, callerType, type, depth, framePointer, registers); List <List <int> > replicationGuides = new List <List <int> >(); if (mRunTime.runtime.Core.Options.IDEDebugMode && mRunTime.runtime.Core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { mRunTime.runtime.Core.DebugProps.SetUpCallrForDebug(mRunTime.runtime.Core, mRunTime.runtime, mProcNode, returnAddr - 1, false, mCallSite, args, replicationGuides, newStackFrame); } StackValue rx = mCallSite.JILDispatchViaNewInterpreter(new Runtime.Context(), args, replicationGuides, newStackFrame, mRunTime.runtime.Core); if (mRunTime.runtime.Core.Options.IDEDebugMode && mRunTime.runtime.Core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { mRunTime.runtime.Core.DebugProps.RestoreCallrForNoBreak(mRunTime.runtime.Core, mProcNode); } return(rx); }
public StackFrame(int globalOffset) { StackValue svThisPtr = ProtoCore.DSASM.StackValue.BuildPointer(Constants.kInvalidPointer); int ci = Constants.kInvalidIndex; int fi = Constants.kInvalidIndex; int returnAddr = Constants.kInvalidIndex; int blockDecl = Constants.kInvalidIndex; int blockCaller = 0; StackFrameType callerType = DSASM.StackFrameType.kTypeLanguage; StackFrameType type = DSASM.StackFrameType.kTypeLanguage; int depth = -1; int framePointer = globalOffset; Init(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, type, depth, framePointer, StackValue.BuildInvalidRegisters(), new List <bool>()); }
public StackFrame( StackValue thisPtr, int classIndex, int functionIndex, int returnAddress, int functionBlockIndex, int callerBlockIndex, StackFrameType callerStackFrameType, StackFrameType stackFrameType, int depth, int framePointer, int blockIndex, List <StackValue> registers, int executionStateSize) { Init(thisPtr, classIndex, functionIndex, returnAddress, functionBlockIndex, callerBlockIndex, callerStackFrameType, stackFrameType, depth, framePointer, blockIndex, registers, executionStateSize); }
private void Init(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int framePointer, List<StackValue> stack, List<bool> execStates) { Validity.Assert((int)StackFrame.AbsoluteIndex.kSize == kStackFrameSize); Frame = new StackValue[kStackFrameSize]; Frame[(int)AbsoluteIndex.kFramePointer] = StackValue.BuildInt(framePointer); Frame[(int)AbsoluteIndex.kStackFrameType] = StackValue.BuildFrameType((int)type); Frame[(int)AbsoluteIndex.kCallerStackFrameType] = StackValue.BuildFrameType((int)callerType); Frame[(int)AbsoluteIndex.kStackFrameDepth] = StackValue.BuildInt(depth); Frame[(int)AbsoluteIndex.kFunctionCallerBlock] = StackValue.BuildBlockIndex(functionBlockCaller); Frame[(int)AbsoluteIndex.kFunctionBlock] = StackValue.BuildBlockIndex(functionBlockDecl); Frame[(int)AbsoluteIndex.kReturnAddress] = StackValue.BuildInt(pc); Frame[(int)AbsoluteIndex.kFunction] = StackValue.BuildInt(funcIndex); Frame[(int)AbsoluteIndex.kClass] = StackValue.BuildInt(classIndex); Frame[(int)AbsoluteIndex.kThisPtr] = svThisPtr; Frame[(int)AbsoluteIndex.kRegisterAX] = stack[0]; Frame[(int)AbsoluteIndex.kRegisterBX] = stack[1]; Frame[(int)AbsoluteIndex.kRegisterCX] = stack[2]; Frame[(int)AbsoluteIndex.kRegisterDX] = stack[3]; Frame[(int)AbsoluteIndex.kRegisterEX] = stack[4]; Frame[(int)AbsoluteIndex.kRegisterFX] = stack[5]; Frame[(int)AbsoluteIndex.kRegisterLX] = stack[6]; Frame[(int)AbsoluteIndex.kRegisterRX] = stack[7]; Frame[(int)AbsoluteIndex.kRegisterSX] = stack[8]; Frame[(int)AbsoluteIndex.kRegisterTX] = stack[9]; int execStateSize = 0; if (null != execStates) { execStateSize = execStates.Count; ExecutionStates = new StackValue[execStateSize]; for (int n = 0; n < execStateSize; ++n) { ExecutionStates[n] = StackValue.BuildBoolean(execStates[n]); } } Frame[(int)AbsoluteIndex.kExecutionStates] = StackValue.BuildInt(execStateSize); Frame[(int)AbsoluteIndex.kLocalVariables] = StackValue.BuildInt(0); Validity.Assert(kStackFrameSize == Frame.Length); }
public void PushStackFrame(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int fp, List <StackValue> registers, int locsize, int executionStates) { // TODO Jun: Performance // Push frame should only require adjusting the frame index instead of pushing dummy elements PushFrame(locsize); Push(StackValue.BuildInt(fp)); PushRegisters(registers); Push(StackValue.BuildInt(executionStates)); Push(StackValue.BuildInt(0)); Push(StackValue.BuildInt(depth)); Push(StackValue.BuildFrameType((int)type)); Push(StackValue.BuildFrameType((int)callerType)); Push(StackValue.BuildBlockIndex(functionBlockCaller)); Push(StackValue.BuildBlockIndex(functionBlockDecl)); Push(StackValue.BuildInt(pc)); Push(StackValue.BuildInt(funcIndex)); Push(StackValue.BuildInt(classIndex)); Push(svThisPtr); FramePointer = Stack.Count; }
public StackFrame(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int framePointer, List<StackValue> stack, List<bool> execStates) { Init(svThisPtr, classIndex, funcIndex, pc, functionBlockDecl, functionBlockCaller, callerType, type, depth, framePointer, stack, execStates); }
private void Init(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int framePointer, List <StackValue> stack, List <bool> execStates) { Validity.Assert((int)StackFrame.AbsoluteIndex.kSize == kStackFrameSize); Frame = new StackValue[kStackFrameSize]; Frame[(int)AbsoluteIndex.kFramePointer] = StackValue.BuildInt(framePointer); Frame[(int)AbsoluteIndex.kStackFrameType] = StackValue.BuildFrameType((int)type); Frame[(int)AbsoluteIndex.kCallerStackFrameType] = StackValue.BuildFrameType((int)callerType); Frame[(int)AbsoluteIndex.kStackFrameDepth] = StackValue.BuildInt(depth); Frame[(int)AbsoluteIndex.kFunctionCallerBlock] = StackValue.BuildBlockIndex(functionBlockCaller); Frame[(int)AbsoluteIndex.kFunctionBlock] = StackValue.BuildBlockIndex(functionBlockDecl); Frame[(int)AbsoluteIndex.kReturnAddress] = StackValue.BuildInt(pc); Frame[(int)AbsoluteIndex.kFunction] = StackValue.BuildInt(funcIndex); Frame[(int)AbsoluteIndex.kClass] = StackValue.BuildInt(classIndex); Frame[(int)AbsoluteIndex.kThisPtr] = svThisPtr; Frame[(int)AbsoluteIndex.kRegisterAX] = stack[0]; Frame[(int)AbsoluteIndex.kRegisterBX] = stack[1]; Frame[(int)AbsoluteIndex.kRegisterCX] = stack[2]; Frame[(int)AbsoluteIndex.kRegisterDX] = stack[3]; Frame[(int)AbsoluteIndex.kRegisterEX] = stack[4]; Frame[(int)AbsoluteIndex.kRegisterFX] = stack[5]; Frame[(int)AbsoluteIndex.kRegisterLX] = stack[6]; Frame[(int)AbsoluteIndex.kRegisterRX] = stack[7]; Frame[(int)AbsoluteIndex.kRegisterSX] = stack[8]; Frame[(int)AbsoluteIndex.kRegisterTX] = stack[9]; int execStateSize = 0; if (null != execStates) { execStateSize = execStates.Count; ExecutionStates = new StackValue[execStateSize]; for (int n = 0; n < execStateSize; ++n) { ExecutionStates[n] = StackValue.BuildBoolean(execStates[n]); } } Frame[(int)AbsoluteIndex.kExecutionStates] = StackValue.BuildInt(execStateSize); Frame[(int)AbsoluteIndex.kLocalVariables] = StackValue.BuildInt(0); Validity.Assert(kStackFrameSize == Frame.Length); }
public void PushStackFrame(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int fp, List<StackValue> registers, int locsize, int executionStates) { // TODO Jun: Performance // Push frame should only require adjusting the frame index instead of pushing dummy elements PushFrame(locsize); Push(StackValue.BuildInt(fp)); PushRegisters(registers); Push(StackValue.BuildInt(executionStates)); Push(StackValue.BuildInt(0)); Push(StackValue.BuildInt(depth)); Push(StackValue.BuildFrameType((int)type)); Push(StackValue.BuildFrameType((int)callerType)); Push(StackValue.BuildBlockIndex(functionBlockCaller)); Push(StackValue.BuildBlockIndex(functionBlockDecl)); Push(StackValue.BuildInt(pc)); Push(StackValue.BuildInt(funcIndex)); Push(StackValue.BuildInt(classIndex)); Push(svThisPtr); FramePointer = Stack.Count; }
public StackFrame(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int framePointer, List <StackValue> stack, List <bool> execStates) { Init(svThisPtr, classIndex, funcIndex, pc, functionBlockDecl, functionBlockCaller, callerType, type, depth, framePointer, stack, execStates); }
private void Init(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int framePointer, List <StackValue> stack) { Validity.Assert((int)StackFrame.AbsoluteIndex.kSize == kStackFrameSize); Frame = new StackValue[kStackFrameSize]; Frame[(int)AbsoluteIndex.kFramePointer] = StackUtils.BuildInt(framePointer); Frame[(int)AbsoluteIndex.kStackFrameType] = StackUtils.BuildNode(AddressType.FrameType, (int)type); Frame[(int)AbsoluteIndex.kCallerStackFrameType] = StackUtils.BuildNode(AddressType.FrameType, (int)callerType); Frame[(int)AbsoluteIndex.kStackFrameDepth] = StackUtils.BuildInt(depth); Frame[(int)AbsoluteIndex.kFunctionCallerBlock] = StackUtils.BuildNode(AddressType.BlockIndex, functionBlockCaller); Frame[(int)AbsoluteIndex.kFunctionBlock] = StackUtils.BuildNode(AddressType.BlockIndex, functionBlockDecl); Frame[(int)AbsoluteIndex.kReturnAddress] = StackUtils.BuildInt(pc); Frame[(int)AbsoluteIndex.kFunction] = StackUtils.BuildInt(funcIndex); Frame[(int)AbsoluteIndex.kClass] = StackUtils.BuildInt(classIndex); Frame[(int)AbsoluteIndex.kThisPtr] = svThisPtr; Frame[(int)AbsoluteIndex.kRegisterAX] = stack[0]; Frame[(int)AbsoluteIndex.kRegisterBX] = stack[1]; Frame[(int)AbsoluteIndex.kRegisterCX] = stack[2]; Frame[(int)AbsoluteIndex.kRegisterDX] = stack[3]; Frame[(int)AbsoluteIndex.kRegisterEX] = stack[4]; Frame[(int)AbsoluteIndex.kRegisterFX] = stack[5]; Frame[(int)AbsoluteIndex.kRegisterLX] = stack[6]; Frame[(int)AbsoluteIndex.kRegisterRX] = stack[7]; Frame[(int)AbsoluteIndex.kRegisterSX] = stack[8]; Frame[(int)AbsoluteIndex.kRegisterTX] = stack[9]; Validity.Assert(kStackFrameSize == Frame.Length); }
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 = interpreter.runtime.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 = 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, 0, 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); } } }
private void Init(StackValue svThisPtr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int framePointer, List<StackValue> stack) { Validity.Assert((int)StackFrame.AbsoluteIndex.kSize == kStackFrameSize); Frame = new StackValue[kStackFrameSize]; Frame[(int)AbsoluteIndex.kFramePointer] = StackUtils.BuildInt(framePointer); Frame[(int)AbsoluteIndex.kStackFrameType] = StackUtils.BuildNode(AddressType.FrameType, (int)type); Frame[(int)AbsoluteIndex.kCallerStackFrameType] = StackUtils.BuildNode(AddressType.FrameType, (int)callerType); Frame[(int)AbsoluteIndex.kStackFrameDepth] = StackUtils.BuildInt(depth); Frame[(int)AbsoluteIndex.kFunctionCallerBlock] = StackUtils.BuildNode(AddressType.BlockIndex, functionBlockCaller); Frame[(int)AbsoluteIndex.kFunctionBlock] = StackUtils.BuildNode(AddressType.BlockIndex, functionBlockDecl); Frame[(int)AbsoluteIndex.kReturnAddress] = StackUtils.BuildInt(pc); Frame[(int)AbsoluteIndex.kFunction] = StackUtils.BuildInt(funcIndex); Frame[(int)AbsoluteIndex.kClass] = StackUtils.BuildInt(classIndex); Frame[(int)AbsoluteIndex.kThisPtr] = svThisPtr; Frame[(int)AbsoluteIndex.kRegisterAX] = stack[0]; Frame[(int)AbsoluteIndex.kRegisterBX] = stack[1]; Frame[(int)AbsoluteIndex.kRegisterCX] = stack[2]; Frame[(int)AbsoluteIndex.kRegisterDX] = stack[3]; Frame[(int)AbsoluteIndex.kRegisterEX] = stack[4]; Frame[(int)AbsoluteIndex.kRegisterFX] = stack[5]; Frame[(int)AbsoluteIndex.kRegisterLX] = stack[6]; Frame[(int)AbsoluteIndex.kRegisterRX] = stack[7]; Frame[(int)AbsoluteIndex.kRegisterSX] = stack[8]; Frame[(int)AbsoluteIndex.kRegisterTX] = stack[9]; Validity.Assert(kStackFrameSize == Frame.Length); }
public void PushStackFrame(int ptr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int fp, List <StackValue> registers, int locsize) { // TODO Jun: Performance // Push frame should only require adjusting the frame index instead of pushing dummy elements PushFrame(locsize); Push(StackUtils.BuildInt(fp)); PushRegisters(registers); Push(StackUtils.BuildNode(AddressType.Int, depth)); Push(StackUtils.BuildNode(AddressType.FrameType, (int)type)); Push(StackUtils.BuildNode(AddressType.FrameType, (int)callerType)); Push(StackUtils.BuildNode(AddressType.BlockIndex, functionBlockCaller)); Push(StackUtils.BuildNode(AddressType.BlockIndex, functionBlockDecl)); Push(StackUtils.BuildInt(pc)); Push(StackUtils.BuildInt(funcIndex)); Push(StackUtils.BuildInt(classIndex)); Push(StackUtils.BuildPointer(ptr)); FramePointer = Stack.Count; }
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 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 StackFrame( StackValue thisPtr, int classIndex, int functionIndex, int returnAddress, int functionBlockIndex, int callerBlockIndex, StackFrameType callerStackFrameType, StackFrameType stackFrameType, int depth, int framePointer, List<StackValue> registers, int executionStateSize) { Init(thisPtr, classIndex, functionIndex, returnAddress, functionBlockIndex, callerBlockIndex, callerStackFrameType, stackFrameType, depth, framePointer, registers, executionStateSize); }
public void PushStackFrame(int ptr, int classIndex, int funcIndex, int pc, int functionBlockDecl, int functionBlockCaller, StackFrameType callerType, StackFrameType type, int depth, int fp, List<StackValue> registers, int locsize) { // TODO Jun: Performance // Push frame should only require adjusting the frame index instead of pushing dummy elements PushFrame(locsize); Push(StackUtils.BuildInt(fp)); PushRegisters(registers); Push(StackUtils.BuildNode(AddressType.Int, depth)); Push(StackUtils.BuildNode(AddressType.FrameType, (int)type)); Push(StackUtils.BuildNode(AddressType.FrameType, (int)callerType)); Push(StackUtils.BuildNode(AddressType.BlockIndex, functionBlockCaller)); Push(StackUtils.BuildNode(AddressType.BlockIndex, functionBlockDecl)); Push(StackUtils.BuildInt(pc)); Push(StackUtils.BuildInt(funcIndex)); Push(StackUtils.BuildInt(classIndex)); Push(StackUtils.BuildPointer(ptr)); FramePointer = Stack.Count; }