public void DSObjectPropertyChanged(ProtoCore.DSASM.Executive exe, int thisptr, String propertyName, object value) { /* * Validity.Assert(thisptr != Constants.kInvalidIndex); * * // It is a naive implementation, need to optimize it later on. * // At runtime we don't have mapping between a DS pointer and a * // symbol name, so we have to go through registered symbols to * // find out if some symbol's value is equal to thisptr. * // * // The other reason to do this is there is possible that two vars * // reference to the same object, so if the property of one of them * // is modified, the other one should be notified. * foreach (var varPropertyChangedHandler in mSubscribers) * { * string symbolName = varPropertyChangedHandler.Key; * SymbolNode symbolNode = exe.GetGlobalSymbolNode(symbolName); * if (symbolNode == null) * { * continue; * } * * StackValue dsValue = exe.Core.Rmem.GetAtRelative(symbolNode); * if (dsValue.optype != AddressType.Pointer && dsValue.opdata != thisptr) * { * continue; * } * * var propertyChangedHandler = varPropertyChangedHandler.Value; * DSPropertyChangedHandler handler = null; * if (propertyChangedHandler.TryGetValue(propertyName, out handler)) * { * if (handler != null) * { * DSPropertyChangedEventArgs args = new DSPropertyChangedEventArgs(symbolName, propertyName, value); * handler(args); * } * } * } */ }
public Interpreter(RuntimeCore runtimeCore, bool isFEP = false) { runtime = runtimeCore.ExecutiveProvider.CreateExecutive(runtimeCore, isFEP); }
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 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); }
private void GCDisposeObject(ref StackValue svPtr, Executive exe) { int classIndex = (int)svPtr.metaData.type; ClassNode cn = exe.exe.classTable.ClassNodes[classIndex]; ProcedureNode pn = null; while (pn == null) { pn = cn.GetDisposeMethod(); if (pn == null && cn.baseList != null && cn.baseList.Count != 0) // search the base class { // assume multiple inheritance is not allowed // it will only has a single base class classIndex = cn.baseList[0]; cn = exe.exe.classTable.ClassNodes[cn.baseList[0]]; } else { break; } } if (pn != null) { // TODO Jun/Jiong: Use build pointer utilities exe.rmem.Push(StackUtils.BuildNode(AddressType.ArrayDim, 0)); exe.rmem.Push(StackUtils.BuildPointer(svPtr.opdata, svPtr.metaData)); exe.rmem.Push(StackUtils.BuildNode(AddressType.BlockIndex, pn.runtimeIndex)); exe.rmem.Push(StackUtils.BuildNode(AddressType.ArrayDim, 0)); exe.rmem.Push(StackUtils.BuildStaticType((int)ProtoCore.PrimitiveType.kTypeVar)); ++exe.Core.FunctionCallDepth; // TODO: Need to move isExplicitCall to DebugProps and come up with a more elegant solution for this // fix for IDE-963 - pratapa bool explicitCall = exe.isExplicitCall; bool tempFlag = explicitCall; exe.Callr(pn.procId, classIndex, 1, ref explicitCall); exe.isExplicitCall = tempFlag; --exe.Core.FunctionCallDepth; } }
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); }
public void GCRelease(StackValue[] ptrList, Executive exe) { for (int n = 0; n < ptrList.Length; ++n) { StackValue svPtr = ptrList[n]; if (svPtr.optype != AddressType.Pointer && svPtr.optype != AddressType.ArrayPointer) { continue; } int ptr = (int)svPtr.opdata; if (ptr < 0 || ptr >= Heaplist.Count) { continue; } HeapElement hs = Heaplist[ptr]; if (!hs.Active) { continue; } if (hs.Refcount > 0) { hs.Refcount--; } // TODO Jun: If its a pointer to a primitive then dont decrease its refcount, just free it // Debug.Assert(hs.refcount >= 0); if (hs.Refcount == 0) { // if it is of class type, first call its destructor before clean its members if(svPtr.optype == AddressType.Pointer) GCDisposeObject(ref svPtr, exe); hs.Active = false; GCRelease(hs.Stack, exe); #if _USE_FREE_LIST freeList.Add(ptr); #endif } } }
/// <summary> /// Bounce instantiates a new Executive /// Execution jumps to the new executive /// This iverload handles debugger properties when bouncing /// </summary> /// <param name="exeblock"></param> /// <param name="entry"></param> /// <param name="context"></param> /// <param name="stackFrame"></param> /// <param name="locals"></param> /// <param name="exec"></param> /// <param name="fepRun"></param> /// <param name="breakpoints"></param> /// <returns></returns> public StackValue Bounce(int exeblock, int entry, StackFrame stackFrame, int locals = 0, bool fepRun = false, Executive exec = null, List<Instruction> breakpoints = null) { if (stackFrame != null) { rmem.PushFrameForLocals(locals); rmem.PushStackFrame(stackFrame); runtimeCore.DebugProps.SetUpBounce(exec, stackFrame.FunctionCallerBlock, stackFrame.ReturnPC); } return runtimeCore.ExecutionInstance.Execute(exeblock, entry, fepRun, breakpoints); }
public Interpreter(Core core, bool isFEP = false) { //runtime = new Executive(core, isFEP); runtime = core.ExecutiveProvider.CreateExecutive(core, isFEP); }
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); }
/// <summary> /// If dsValue is a pointer (object), expand the size of this object and /// add references to referencedObjects; if dsValue is an array, then /// traverse recursively. /// /// Exception: ProtoCore.Exception.RunOutOfMemoryException if the engine /// fails to expand the size of object. /// </summary> /// <param name="dsValue"></param> /// <param name="referencedObjects"></param> /// <param name="exec"></param> private void SetReferenceObjects(StackValue dsValue, List<StackValue> referencedObjects, Executive exec) { if (dsValue.IsPointer) { var dsObject = exec.rmem.Heap.ToHeapObject<DSObject>(dsValue); if (dsObject != null) { int startIndex = dsObject.Count; dsObject.ExpandBySize(referencedObjects.Count); Validity.Assert(dsObject.Count >= referencedObjects.Count); for (int i = 0; i < referencedObjects.Count; i++) { dsObject.SetValueAtIndex(startIndex + i, referencedObjects[i], exec.RuntimeCore); } } } else if (dsValue.IsArray) { var dsArray = exec.rmem.Heap.ToHeapObject<DSArray>(dsValue); if (dsArray != null) { foreach (var element in dsArray.Values) { SetReferenceObjects(element, referencedObjects, exec); } } } }