예제 #1
0
        public void Execute(ProtoCore.Core core, ProtoCore.Runtime.Context context)
        {
            try
            {
                core.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionBegin);
                foreach (ProtoCore.DSASM.CodeBlock codeblock in core.CodeBlockList)
                {
                    //ProtoCore.Runtime.Context context = new ProtoCore.Runtime.Context();

                    int locals = 0;


                    // 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);

                    // 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.SetAt(ProtoCore.DSASM.StackFrame.AbsoluteIndex.kRegisterTX, svCallConvention);

                    core.Bounce(codeblock.codeBlockId, codeblock.instrStream.entrypoint, context, stackFrame, locals, EventSink);
                }
                core.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd);
            }
            catch
            {
                core.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd);
                throw;
            }
        }
예제 #2
0
        public StackValue Callr(int functionIndex, int classIndex, int depth, ref bool explicitCall, bool isDynamicCall = false, bool hasDebugInfo = false)
        {
            isGlobScope = false;
            ProcedureNode fNode = null;

            // Comment Jun: this is curently unused but required for stack alignment
            if (!isDynamicCall)
            {
                StackValue svType = rmem.Pop();
                runtimeVerify(AddressType.StaticType == svType.optype);
                int lhsStaticType = (int)svType.metaData.type;
            }


            // Pop off number of dimensions indexed into this function call
            // f()[0][1] -> 2 dimensions
            StackValue svDim = rmem.Pop();
            runtimeVerify(AddressType.ArrayDim == svDim.optype);
            int fCallDimensions = (int)svDim.opdata;


            // Jun Comment: The block where the function was declared in
            StackValue svBlockDeclaration = rmem.Pop();
            runtimeVerify(AddressType.BlockIndex == svBlockDeclaration.optype);
            int blockDeclId = (int)svBlockDeclaration.opdata;

            // Jun Comment: The block where the function is called from
            Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != core.RunningBlock);
            StackValue svBlockCaller = StackValue.BuildBlockIndex(core.RunningBlock);


            bool isMember = ProtoCore.DSASM.Constants.kInvalidIndex != classIndex;
            if (isMember)
            {
                // Constructor or member function
                fNode = exe.classTable.ClassNodes[classIndex].vtable.procList[functionIndex];

                if (depth > 0)
                {
                    if (fNode.isConstructor)
                    {
                        string message = String.Format(ProtoCore.RuntimeData.WarningMessage.KCallingConstructorOnInstance, fNode.name);
                        core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kCallingConstructorOnInstance, message);
                        isGlobScope = true;
                        StackValue nullSv = StackValue.Null;
                        return nullSv;
                    }
                }
            }
            else
            {
                // Global function
                fNode = exe.procedureTable[blockDeclId].procList[functionIndex];
            }

            // Build the arg values list
            List<StackValue> arguments = new List<StackValue>();
            List<ProtoCore.ReplicationGuide> replicationGuideList = null;
            List<List<ProtoCore.ReplicationGuide>> replicationGuides = new List<List<ProtoCore.ReplicationGuide>>();

            // Retrive the param values from the stack
            int stackindex = rmem.Stack.Count - 1;

            int argtype_i = fNode.argTypeList.Count - 1;
            int argFrameSize = 0;


            List<StackValue> dotCallDimensions = new List<StackValue>();
            if (fNode.name == ProtoCore.DSASM.Constants.kDotMethodName)
            {
                int firstDotArgIndex = stackindex - (ProtoCore.DSASM.Constants.kDotCallArgCount - 1);
                StackValue svLHS = rmem.Stack[firstDotArgIndex];

                arguments.Add(svLHS);
                argFrameSize = ProtoCore.DSASM.Constants.kDotArgCount;

                int functionArgsIndex = stackindex - (ProtoCore.DSASM.Constants.kDotCallArgCount - ProtoCore.DSASM.Constants.kDotArgIndexArgCount - 1);
                StackValue svArrayPtrFunctionArgs = rmem.Stack[functionArgsIndex];
                GCRetain(svArrayPtrFunctionArgs);


                // Retrieve the indexed dimensions into the dot call
                int arrayDimIndex = stackindex - (ProtoCore.DSASM.Constants.kDotCallArgCount - ProtoCore.DSASM.Constants.kDotArgIndexArrayIndex - 1);
                StackValue svArrayPtrDimesions = rmem.Stack[arrayDimIndex];
                Validity.Assert(svArrayPtrDimesions.optype == AddressType.ArrayPointer);

                int arrayCountIndex = stackindex - (ProtoCore.DSASM.Constants.kDotCallArgCount - ProtoCore.DSASM.Constants.kDotArgIndexDimCount - 1);
                StackValue svDimensionCount = rmem.Stack[arrayCountIndex];
                Validity.Assert(svDimensionCount.optype == AddressType.Int);


                // If array dimension were provided then retrive the final pointer 
                if (svDimensionCount.opdata > 0)
                {
                    HeapElement he = rmem.Heap.Heaplist[(int)svArrayPtrDimesions.opdata];
                    Validity.Assert(he.VisibleSize == svDimensionCount.opdata);
                    for (int n = 0; n < he.VisibleSize; ++n)
                    {
                        dotCallDimensions.Add(he.Stack[n] /*(int)he.Stack[n].opdata*/);
                    }
                }
            }
            else
            {
                for (int p = 0; p < fNode.argTypeList.Count; ++p)
                {
                    // Must iterate through the args in the stack in reverse as its unknown how many replication guides were pushed
                    StackValue value = rmem.Stack[stackindex--];
                    ++argFrameSize;
                    arguments.Add(value);

                    if (fNode.name != ProtoCore.DSASM.Constants.kDotArgMethodName)
                    {
                        bool hasGuide = (AddressType.ReplicationGuide == rmem.Stack[stackindex].optype);
                        if (hasGuide)
                        {
                            replicationGuideList = new List<ProtoCore.ReplicationGuide>();

                            // Retrieve replication guides
                            value = rmem.Stack[stackindex--];
                            ++argFrameSize;
                            runtimeVerify(AddressType.ReplicationGuide == value.optype);

                            int guides = (int)value.opdata;
                            if (guides > 0)
                            {
                                for (int i = 0; i < guides; ++i)
                                {
                                    // Get the replicationguide number from the stack
                                    value = rmem.Stack[stackindex--];
                                    Validity.Assert(value.optype == AddressType.Int);
                                    int guideNumber = (int)value.opdata;

                                    // Get the replication guide property from the stack
                                    value = rmem.Stack[stackindex--];
                                    Validity.Assert(value.optype == AddressType.Boolean);
                                    bool isLongest = (int)value.opdata == 1 ? true : false;

                                    ProtoCore.ReplicationGuide guide = new ReplicationGuide(guideNumber, isLongest);
                                    replicationGuideList.Add(guide);
                                    ++argFrameSize;
                                }
                            }
                            replicationGuideList.Reverse();
                            replicationGuides.Add(replicationGuideList);
                        }
                    }
                }

                // Pop off frame information 
                rmem.Pop(argFrameSize);
            }

            replicationGuides.Reverse();
            arguments.Reverse();

            Runtime.Context runtimeContext = new Runtime.Context();

#if __PROTOTYPE_ARRAYUPDATE_FUNCTIONCALL

            //
            // Comment Jun: Retrieve the indices used to index in an argument

            //
            //  List<List<int>> indexIntoList
            //  foreach arg in functionNode.args
            //      
            //      Iterate over the symbols in the executing graph node
	        //      foreach symbol in executingGraphNode.dependents
            //          List<int> argIndexInto = GetSymbolIndexedIntoList(symbol)
            //          indexIntoList.push(argIndexInto)
            //      end            
            //      context.indexlist = indexIntoList
            //      sv = JILDispatch.callsite(function, args, context, ...)
            //  end
            //

            if (null != Properties.executingGraphNode 
                && null != Properties.executingGraphNode.dependentList 
                && Properties.executingGraphNode.dependentList.Count > 0 )
            {
                // Save the LHS of this graphnode
                runtimeContext.ArrayPointer = Properties.executingGraphNode.ArrayPointer;

                // Iterate over the symbols in the executing graph node
                for (int n = 0; n < Properties.executingGraphNode.dependentList.Count; n++)
                {
                    List<int> indexIntoList = new List<int>();
                    {
                        // Check if the current dependent was indexed into
                        ProtoCore.DSASM.SymbolNode argSymbol = Properties.executingGraphNode.dependentList[n].updateNodeRefList[0].nodeList[0].symbol;
                        if (symbolArrayIndexMap.ContainsKey(argSymbol.name))
                        {
                            indexIntoList = symbolArrayIndexMap[argSymbol.name];
                        }
                    }
                    runtimeContext.IndicesIntoArgMap.Add(indexIntoList);
                }
            }
#endif

            // Comment Jun: These function do not require replication guides
            // TODO Jun: Move these conditions or refactor JIL code emission so these checks dont reside here (Post R1)
            if (ProtoCore.DSASM.Constants.kDotMethodName != fNode.name
                && ProtoCore.DSASM.Constants.kDotArgMethodName != fNode.name
                && ProtoCore.DSASM.Constants.kFunctionRangeExpression != fNode.name)
            {
                // Comment Jun: If this is a non-dotarg call, cache the guides first and retrieve them on the actual function call
                // TODO Jun: Ideally, cache the replication guides in the dynamic function node
                replicationGuides = GetCachedReplicationGuides(core, arguments.Count);
            }

            bool isCallingDotArgCall = fNode.name == ProtoCore.DSASM.Constants.kDotArgMethodName;
            if (isCallingDotArgCall)
            {
                // Comment Jun: (Sept 8 2012) Check with Yuke what the intention of this is to the dotarg arguments
                for (int i = 0; i < arguments.Count; ++i)
                {
                    GCRetain(arguments[i]);
                }
            }


            // if is dynamic call, the final pointer has been resovled in the ProcessDynamicFunction function
            StackValue svThisPtr = StackValue.Null;

            if (depth > 0)
            {
                // locals are not yet in the stack so there is no need to account for that in this stack frame

                if (isDynamicCall)
                {
                    svThisPtr = rmem.Pop();
                }
                else
                {
                    svThisPtr = GetFinalPointer(depth);
                }

                // 
                if (svThisPtr.optype != AddressType.Pointer)
                {
                    string message = String.Format(ProtoCore.RuntimeData.WarningMessage.kInvokeMethodOnInvalidObject, fNode.name);
                    core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kDereferencingNonPointer, message);
                    isGlobScope = true;
                    return StackValue.Null;
                }
            }
            else
            {
                // There is no depth but check if the function is a member function
                // If its a member function, the this pointer is required by the core to pass on to the FEP call
                if (isMember && !fNode.isConstructor && !fNode.isStatic)
                {
                    // A member function
                    // Get the this pointer as this class instance would have already been cosntructed
                    svThisPtr = rmem.GetAtRelative(rmem.GetStackIndex(ProtoCore.DSASM.StackFrame.kFrameIndexThisPtr));

                }
                else
                {
                    // Global
                    svThisPtr = ProtoCore.DSASM.StackValue.BuildPointer(ProtoCore.DSASM.Constants.kInvalidPointer);
                }
            }

            if (svThisPtr.optype == AddressType.Pointer &&
                svThisPtr.opdata != Constants.kInvalidIndex &&
                svThisPtr.metaData.type != Constants.kInvalidIndex)
            {
                int runtimeClassIndex = (int)svThisPtr.metaData.type;
                ClassNode runtimeClass = core.ClassTable.ClassNodes[runtimeClassIndex];
                if (runtimeClass.IsMyBase(classIndex))
                {
                    classIndex = runtimeClassIndex;
                }
            }

            // Build the stackframe
            //int thisPtr = (int)svThisPtr.opdata;
            int ci = classIndex; // ProtoCore.DSASM.Constants.kInvalidIndex;   // Handled at FEP
            int fi = ProtoCore.DSASM.Constants.kInvalidIndex;   // Handled at FEP

            int returnAddr = pc + 1;

            int blockDecl = (int)svBlockDeclaration.opdata;
            int blockCaller = (int)svBlockCaller.opdata;
            int framePointer = ProtoCore.DSASM.Constants.kInvalidIndex;
            framePointer = rmem.FramePointer;


            bool isInDotArgCall = false;
            int currentClassIndex = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata;
            int currentFunctionIndex = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunction).opdata;
            bool isGlobalScope = ProtoCore.DSASM.Constants.kGlobalScope == currentClassIndex && ProtoCore.DSASM.Constants.kGlobalScope == currentFunctionIndex;
            if (core.ExecMode != InterpreterMode.kExpressionInterpreter)
            {
                if (ProtoCore.DSASM.Constants.kGlobalScope != currentFunctionIndex)
                {
                    int currentFunctionDeclBlock = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunctionBlock).opdata;
                    ProcedureNode currentProcCall = GetProcedureNode(currentFunctionDeclBlock, currentClassIndex, currentFunctionIndex);
                    isInDotArgCall = currentProcCall.name == ProtoCore.DSASM.Constants.kDotArgMethodName;
                }
            }

            if (isGlobalScope || !isInDotArgCall)
            {
                if (null != Properties.executingGraphNode)
                {
                    core.ExecutingGraphnode = Properties.executingGraphNode;
                }
            }

            // Get the cached callsite, creates a new one for a first-time call
            ProtoCore.CallSite callsite = core.GetCallSite(core.ExecutingGraphnode, classIndex, fNode.name);
            Validity.Assert(null != callsite);



            StackFrameType type = StackFrameType.kTypeFunction;
            int blockDepth = 0;

            List<StackValue> registers = new List<StackValue>();
            SaveRegisters(registers);

            // Comment Jun: the caller type is the current type in the stackframe
            StackFrameType callerType = (fepRun) ? StackFrameType.kTypeFunction : StackFrameType.kTypeLanguage;

            // Get the execution states of the current stackframe
            int currentScopeClass = ProtoCore.DSASM.Constants.kInvalidIndex;
            int currentScopeFunction = ProtoCore.DSASM.Constants.kInvalidIndex;
            GetCallerInformation(out currentScopeClass, out currentScopeFunction);

            List<bool> execStates = new List<bool>();

            //
            // 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
            //
            if (currentScopeFunction != ProtoCore.DSASM.Constants.kGlobalScope)
            {
                // Get the instruction stream where the current function resides in
                StackValue svCurrentFunctionBlockDecl = rmem.GetAtRelative(rmem.GetStackIndex(ProtoCore.DSASM.StackFrame.kFrameIndexFunctionBlock));
                Validity.Assert(svCurrentFunctionBlockDecl.optype == AddressType.BlockIndex);
                AssociativeGraph.DependencyGraph depgraph = exe.instrStreamList[(int)svCurrentFunctionBlockDecl.opdata].dependencyGraph;

                // Allow only if this is a recursive call
                // It is recursive if the current function scope is equal to the function to call
                bool isRecursive = fNode.classScope == currentScopeClass && fNode.procId == currentScopeFunction;
                if (isRecursive)
                {
                    // Get the graphnodes of the function from the instruction stream and retrive the execution states
                    execStates = depgraph.GetExecutionStatesAtScope(currentScopeClass, currentScopeFunction);
                }
            }
            

            // Build the stackfram for the functioncall
            ProtoCore.DSASM.StackFrame stackFrame = new StackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, type, blockDepth, framePointer, registers, execStates);

            FunctionCounter counter = FindCounter(functionIndex, classIndex, fNode.name);
            StackValue sv = StackValue.Null;


            if (core.Options.RecursionChecking)
            {
                //Do the recursion check before call
                if (counter.times < ProtoCore.DSASM.Constants.kRecursionTheshold) //&& counter.sharedCounter < ProtoCore.DSASM.Constants.kRepetationTheshold)
                {

                    // Build a context object in JILDispatch and call the Dispatch
                    if (counter.times == 0)
                    {
                        counter.times++;
                        core.calledInFunction = true;
                    }

                    else if (counter.times >= 1)
                    {
                        if (fNode.name.ToCharArray()[0] != '%' && fNode.name.ToCharArray()[0] != '_' && !fNode.name.Equals(ProtoCore.DSASM.Constants.kDotMethodName) && core.calledInFunction)
                        {
                            counter.times++;
                        }
                    }


                    if (core.Options.IDEDebugMode && core.ExecMode != InterpreterMode.kExpressionInterpreter)
                    {
                        bool isBaseCall = false;
                        core.DebugProps.SetUpCallrForDebug(core, this, fNode, pc, isBaseCall, callsite, arguments, replicationGuides, stackFrame, dotCallDimensions, hasDebugInfo);
                    }

                    sv = callsite.JILDispatch(arguments, replicationGuides, stackFrame, core, runtimeContext);
                }
                else
                {
                    FindRecursivePoints();
                    string message = String.Format(ProtoCore.RuntimeData.WarningMessage.kMethodStackOverflow, core.recursivePoint[0].name);
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kInvalidRecursion, message);

                    core.recursivePoint = new List<FunctionCounter>();
                    core.funcCounterTable = new List<FunctionCounter>();
                    sv = StackValue.Null;
                }
            }
            else
            {
                if (core.Options.IDEDebugMode && core.ExecMode != InterpreterMode.kExpressionInterpreter)
                {
                    bool isBaseCall = false;
                    if (core.ContinuationStruct.IsFirstCall)
                    {
                        core.DebugProps.SetUpCallrForDebug(core, this, fNode, pc, isBaseCall, callsite, arguments, replicationGuides, stackFrame, dotCallDimensions, hasDebugInfo);
                    }
                    else
                    {
                        core.DebugProps.SetUpCallrForDebug(core, this, fNode, pc, isBaseCall, callsite, core.ContinuationStruct.InitialArguments, replicationGuides, stackFrame,
                        core.ContinuationStruct.InitialDotCallDimensions, hasDebugInfo);
                    }
                }

                SX = svBlockDeclaration;
                stackFrame.SetAt(StackFrame.AbsoluteIndex.kRegisterSX, svBlockDeclaration);

                //Dispatch without recursion tracking 
                explicitCall = false;
                isExplicitCall = explicitCall;

#if __DEBUG_REPLICATE
                // TODO: This if block is currently executed only for a replicating function call in Debug Mode (including each of its continuations) 
                // This condition will no longer be required once the same Dispatch function can decide whether to perform a fast dispatch (parallel mode)
                // OR a Serial/Debug mode dispatch, in which case this same block should work for Serial mode execution w/o the Debug mode check - pratapa
                if (core.Options.IDEDebugMode)
                {
                    DebugFrame debugFrame = core.DebugProps.DebugStackFrame.Peek();

                    //if (debugFrame.IsReplicating || core.ContinuationStruct.IsContinuation)
                    if (debugFrame.IsReplicating)
                    {
                        FunctionEndPoint fep = null;
                        ContinuationStructure cs = core.ContinuationStruct;

                        if (core.Options.ExecutionMode == ProtoCore.ExecutionMode.Serial || core.Options.IDEDebugMode)
                        {
                            // This needs to be done only for the initial argument arrays (ie before the first replicating call) - pratapa
                            if(core.ContinuationStruct.IsFirstCall)
                            {
                                core.ContinuationStruct.InitialDepth = depth;
                                core.ContinuationStruct.InitialPC = pc;
                                core.ContinuationStruct.InitialArguments = arguments;
                                core.ContinuationStruct.InitialDotCallDimensions = dotCallDimensions;

                                for (int i = 0; i < arguments.Count; ++i)
                                {
                                    GCUtils.GCRetain(arguments[i], core);
                                }

                                // Hardcoded
                                core.ContinuationStruct.NextDispatchArgs.Add(StackValue.BuildInt(1));
                            }

                            // The Resolve function is currently hard-coded as a place holder to test debugging replication - pratapa
                            fep = callsite.ResolveForReplication(new ProtoCore.Runtime.Context(), arguments, replicationGuides, stackFrame, core, cs);
                            
                            // TODO: Refactor following steps into new function (ExecWithZeroRI + JILFep.Execute) to be called from here - pratapa
                            // Get final FEP by calling SelectFinalFep()
                            // Update DebugProps with final FEP
                            // Call finalFEP.CoerceParameters()
                            // Setup stackframe
                            // Push Stackframe
                            sv = callsite.ExecuteContinuation(fep, stackFrame, core);

                            core.ContinuationStruct = cs;
                            core.ContinuationStruct.IsFirstCall = true;

                        }
                    }
                    else
                        sv = callsite.JILDispatch(arguments, replicationGuides, stackFrame, core);
                }
                else
#endif
                sv = callsite.JILDispatch(arguments, replicationGuides, stackFrame, core, runtimeContext);

                if (sv.optype == AddressType.ExplicitCall)
                {
                    //
                    // Set the interpreter properties for function calls
                    // These are used when performing GC on return 
                    // The GC occurs: 
                    //      1. In this instruction for implicit calls
                    //      2. In the return instruction
                    //
                    Properties.functionCallArguments = arguments;

                    Properties.functionCallDotCallDimensions = dotCallDimensions;

                    explicitCall = true;
                    isExplicitCall = explicitCall;
                    int entryPC = (int)sv.opdata;

                    CallExplicit(entryPC);
                }
#if __PROTOTYPE_ARRAYUPDATE_FUNCTIONCALL
                else
                {
                    if (null != Properties.executingGraphNode)
                    {
                        Properties.executingGraphNode.ArrayPointer = sv;
                    }
                }
#endif
            }

            // If the function was called implicitly, The code below assumes this and must be executed
            if (!explicitCall)
            {
                // Restore debug properties after returning from a CALL/CALLR
                if (core.Options.IDEDebugMode && core.ExecMode != InterpreterMode.kExpressionInterpreter)
                {
                    core.DebugProps.RestoreCallrForNoBreak(core, fNode);
                }

                GCDotMethods(fNode.name, ref sv, dotCallDimensions, arguments);

                DecRefCounter(sv);
                if (sv.optype == AddressType.ArrayPointer)
                {
                    // GCReleasePool.Add(sv);
                }

                isGlobScope = true;
                if (fNode.name.ToCharArray()[0] != '%' && fNode.name.ToCharArray()[0] != '_')
                {
                    core.calledInFunction = false;
                    //@TODO(Gemeng, Luke): Remove me
                    //Console.WriteLine("flag changed \t" + core.calledInFunction);
                }
            }
            return sv;
        }
예제 #3
0
        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);
        }
예제 #4
0
파일: CallSite.cs 프로젝트: heegwon/Dynamo
        //Single function call

        /// <summary>
        /// Dispatch without replication
        /// </summary>
        private StackValue ExecWithZeroRI(List<FunctionEndPoint> functionEndPoint, ProtoCore.Runtime.Context c,
                                          List<StackValue> formalParameters, StackFrame stackFrame, Core core,
                                          FunctionGroup funcGroup, SingleRunTraceData previousTraceData, SingleRunTraceData newTraceData)
        {
            if(core.CancellationPending)
            {
                throw new ExecutionCancelledException();               
            }

            //@PERF: Todo add a fast path here for the case where we have a homogenious array so we can directly dispatch
            FunctionEndPoint finalFep = SelectFinalFep(c, functionEndPoint, formalParameters, stackFrame, core);

            if (functionEndPoint == null)
            {
                core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kMethodResolutionFailure,
                                              "Function dispatch could not be completed {2EB39E1B-557C-4819-94D8-CF7C9F933E8A}");
                return StackValue.Null;
            }

            if (core.Options.IDEDebugMode && core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
            {
                DebugFrame debugFrame = core.DebugProps.DebugStackFrame.Peek();
                debugFrame.FinalFepChosen = finalFep;
            }

            List<StackValue> coercedParameters = finalFep.CoerceParameters(formalParameters, core);

            // Correct block id where the function is defined. 
            StackValue funcBlock = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock);
            funcBlock.opdata = finalFep.BlockScope;
            stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock, funcBlock);


            //TraceCache -> TLS
            //Extract left most high-D pack
            ISerializable traceD = previousTraceData.GetLeftMostData();

            if (traceD != null)
            {
                //There was data associated with the previous execution, push this into the TLS

                Dictionary<string, ISerializable> dataDict = new Dictionary<string, ISerializable>();
                dataDict.Add(TRACE_KEY, traceD);

                TraceUtils.SetObjectToTLS(dataDict);
            }
            else
            {
                //There was no trace data for this run
                TraceUtils.ClearAllKnownTLSKeys();
            }

            //EXECUTE
            StackValue ret = finalFep.Execute(c, coercedParameters, stackFrame, core);

            if (ret.IsNull)
            {

                //wipe the trace cache
                TraceUtils.ClearTLSKey(TRACE_KEY);
            }

            //TLS -> TraceCache
            Dictionary<String, ISerializable> traceRet = TraceUtils.GetObjectFromTLS();

            if (traceRet.ContainsKey(TRACE_KEY))
            {
                var val = traceRet[TRACE_KEY];
                newTraceData.Data = val;
            }


            // An explicit call requires return coercion at the return instruction
            if (!ret.IsExplicitCall)
            {
                ret = PerformReturnTypeCoerce(finalFep, core, ret);
            }
            return ret;
        }
예제 #5
0
        private StackValue CallrForMemberFunction(int classIndex,
                                                  int procIndex,
                                                  bool hasDebugInfo,
                                                  ref bool isExplicitCall)
        {
            var arrayDim = rmem.Pop();
            Validity.Assert(arrayDim.IsArrayDimension());

            var blockIndex = rmem.Pop();
            Validity.Assert(blockIndex.IsBlockIndex());

            ClassNode classNode = exe.classTable.ClassNodes[classIndex];
            ProcedureNode procNode = classNode.vtable.procList[procIndex];

            // Get all arguments and replications 
            var arguments = new List<StackValue>();
            var repGuides = new List<List<ReplicationGuide>>();
            PopArgumentsFromStack(procNode.argTypeList.Count,
                                  ref arguments,
                                  ref repGuides);
            arguments.Reverse();
            repGuides = GetCachedReplicationGuides(core, arguments.Count + 1);

            StackValue lhs = rmem.Pop();
            StackValue thisObject = lhs;
            if (StackUtils.IsArray(lhs))
            {
                ArrayUtils.GetFirstNonArrayStackValue(lhs, ref thisObject, core);
                arguments.Insert(0, lhs);
            }

            if (!thisObject.IsObject() && !thisObject.IsArray())
            {
                core.RuntimeStatus.LogWarning(WarningID.kDereferencingNonPointer,
                                              WarningMessage.kDeferencingNonPointer);
                return StackValue.Null;
            }

            var registers = new List<StackValue>();
            SaveRegisters(registers);

            var stackFrame = new StackFrame(thisObject,         // thisptr 
                                            classIndex,         // function class index
                                            procIndex,          // function index
                                            pc + 1,             // return address
                                            0,                  // member function always declared in block 0 */
                                            core.RunningBlock,  // caller block
                                            fepRun ? StackFrameType.kTypeFunction : StackFrameType.kTypeLanguage,
                                            StackFrameType.kTypeFunction,   // frame type
                                            0,                              // block depth
                                            rmem.FramePointer,
                                            registers,
                                            new List<bool>());

            var callsite = core.GetCallSite(core.ExecutingGraphnode,
                                            classIndex,
                                            procNode.name);
            Validity.Assert(null != callsite);

            bool setDebugProperty = core.Options.IDEDebugMode &&
                                    core.ExecMode != InterpreterMode.kExpressionInterpreter &&
                                    procNode != null;

            if (setDebugProperty)
            {
                core.DebugProps.SetUpCallrForDebug(core,
                                                   this,
                                                   procNode,
                                                   pc,
                                                   false,
                                                   callsite,
                                                   arguments,
                                                   repGuides,
                                                   stackFrame,
                                                   null,
                                                   hasDebugInfo);
            }

            SX = StackValue.BuildBlockIndex(0);
            stackFrame.SetAt(StackFrame.AbsoluteIndex.kRegisterSX, SX);

            StackValue sv = callsite.JILDispatch(arguments,
                                                 repGuides,
                                                 stackFrame,
                                                 core,
                                                 new Runtime.Context());

            isExplicitCall = sv.IsExplicitCall();
            if (isExplicitCall)
            {
                Properties.functionCallArguments = arguments;
                Properties.functionCallDotCallDimensions = new List<StackValue>();

                int entryPC = (int)sv.opdata;
                CallExplicit(entryPC);
            }

            return sv;
        }
예제 #6
0
        public void Execute(ProtoCore.Core core, ProtoCore.Runtime.Context context)
        {
            try
            {
                core.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionBegin);
                foreach (ProtoCore.DSASM.CodeBlock codeblock in core.CodeBlockList)
                {
                    //ProtoCore.Runtime.Context context = new ProtoCore.Runtime.Context();

                    int locals = 0;


                    // 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);
                    
                    // 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.SetAt(ProtoCore.DSASM.StackFrame.AbsoluteIndex.kRegisterTX, svCallConvention);

                    core.Bounce(codeblock.codeBlockId, codeblock.instrStream.entrypoint, context, stackFrame, locals, EventSink);
                }
                core.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd);
            }
            catch 
            {
                core.NotifyExecutionEvent(ProtoCore.ExecutionStateEventArgs.State.kExecutionEnd);
                throw;
            }
        }
예제 #7
0
        /// <summary>
        /// Dispatch without replication
        /// </summary>
        private StackValue ExecWithZeroRI(List<FunctionEndPoint> functionEndPoint, ProtoCore.Runtime.Context c,
            List<StackValue> formalParameters, StackFrame stackFrame, Core core,
            FunctionGroup funcGroup)
        {
            //@PERF: Todo add a fast path here for the case where we have a homogenious array so we can directly dispatch

            FunctionEndPoint finalFep = SelectFinalFep(c, functionEndPoint, formalParameters, stackFrame, core);

            /*functionEndPoint = ResolveFunctionEndPointWithoutReplication(c,funcGroup, formalParameters,
                                                                         stackFrame, core);*/

            if (functionEndPoint == null)
            {
                core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kMethodResolutionFailure,
                                              "Function dispatch could not be completed {2EB39E1B-557C-4819-94D8-CF7C9F933E8A}");
                return StackUtils.BuildNull();
            }

            if (core.Options.IDEDebugMode && core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
            {
                DebugFrame debugFrame = core.DebugProps.DebugStackFrame.Peek();
                debugFrame.FinalFepChosen = finalFep;
            }

            //@TODO(Luke): Should this coerce?
            List<StackValue> coercedParameters = finalFep.CoerceParameters(formalParameters, core);

            // Correct block id where the function is defined.
            StackValue funcBlock = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock);
            funcBlock.opdata = finalFep.BlockScope;
            stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock, funcBlock);

            StackValue ret = finalFep.Execute(c, coercedParameters, stackFrame, core);

            // An explicit call requires return coercion at the return instruction
            if (ret.optype != AddressType.ExplicitCall)
            {
                ret = PerformReturnTypeCoerce(finalFep, core, ret);
            }
            return ret;
        }
예제 #8
0
        public StackValue ExecuteContinuation(FunctionEndPoint jilFep, StackFrame stackFrame, Core core)
        {
            // Pushing a dummy stackframe onto the Stack for the current fep
            int ci = -1;
            int fi = 0;

            // Hardcoded for Increment as member function
            if (jilFep.procedureNode == null)
            {
                ci = 14;
                jilFep.procedureNode = core.DSExecutable.classTable.ClassNodes[ci].vtable.procList[fi];
            }
            Validity.Assert(jilFep.procedureNode != null);

            if (core.Options.IDEDebugMode)
            {
                DebugFrame debugFrame = core.DebugProps.DebugStackFrame.Peek();
                debugFrame.FinalFepChosen = jilFep;
            }

            ProtoCore.DSASM.StackValue svThisPtr = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr);
            ProtoCore.DSASM.StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock);
            int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata;
            int depth = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameDepth).opdata;
            DSASM.StackFrameType type = (DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kStackFrameType).opdata;

            int locals = 0;
            int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata;
            int framePointer = core.Rmem.FramePointer;
            DSASM.StackFrameType callerType = (DSASM.StackFrameType)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata;

            StackValue svCallConvention = ProtoCore.DSASM.StackUtils.BuildNode(ProtoCore.DSASM.AddressType.CallingConvention, (long)ProtoCore.DSASM.CallingConvention.CallType.kExplicit);
            // Set TX register
            stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kRegisterTX, svCallConvention);

            // Set SX register
            stackFrame.SetAt(DSASM.StackFrame.AbsoluteIndex.kRegisterSX, svBlockDecl);

            List<ProtoCore.DSASM.StackValue> registers = new List<DSASM.StackValue>();
            registers.AddRange(stackFrame.GetRegisters());

            core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, (int)svBlockDecl.opdata, blockCaller, callerType, type, depth, framePointer, registers, locals, 0);

            return StackUtils.BuildNode(AddressType.ExplicitCall, jilFep.procedureNode.pc);
        }