private void RETC_Handler(Instruction instruction) { runtimeVerify(rmem.ValidateStackFrame()); RX = rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexThisPtr); int ci = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata; int fi = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunction).opdata; pc = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexReturnAddress).opdata; // block id is used in ReturnSiteGC to get the procedure node if it is not a member function // not meaningful here, because we are inside a constructor int blockId = (int)SX.opdata; if (core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { ReturnSiteGC(blockId, ci, fi); } RestoreFromCall(); core.RunningBlock = executingBlock; // If we're returning from a block to a function, the instruction stream needs to be restored. StackValue sv = rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexRegisterTX); Validity.Assert(AddressType.CallingConvention == sv.optype); CallingConvention.CallType callType = (CallingConvention.CallType)sv.opdata; bool explicitCall = CallingConvention.CallType.kExplicit == callType || CallingConvention.CallType.kExplicitBase == callType; isExplicitCall = explicitCall; if (!core.Options.IDEDebugMode || core.ExecMode == InterpreterMode.kExpressionInterpreter) { int localCount = 0; int paramCount = 0; GetLocalAndParamCount(blockId, ci, fi, out localCount, out paramCount); rmem.FramePointer = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + localCount + paramCount); if (core.ExecMode != InterpreterMode.kExpressionInterpreter) { // Restoring the registers require the current frame pointer of the stack frame RestoreRegistersFromStackFrame(); bounceType = (ProtoCore.DSASM.CallingConvention.BounceType)TX.opdata; } } terminate = !explicitCall; Properties = PopInterpreterProps(); ProcedureNode procNode = GetProcedureNode(blockId, ci, fi); if (explicitCall) { //RX = CallSite.PerformReturnTypeCoerce(procNode, core, RX); bool wasDebugPropsPopped = DebugReturn(procNode, pc); // Comment Jun: For explicit calls, we need to manually GC decrement the arguments. // These arguments were GC incremented on callr if (!wasDebugPropsPopped) //if (!core.Options.IDEDebugMode || core.ExecMode == ExecutionMode.kExpressionInterpreter) { for (int i = 0; i < Properties.functionCallArguments.Count; ++i) { GCUtils.GCRelease(Properties.functionCallArguments[i], core); } } if (CallingConvention.CallType.kExplicitBase != callType) { //if (!core.Options.IDEDebugMode || core.ExecMode == ExecutionMode.kExpressionInterpreter) if (!wasDebugPropsPopped) { DecRefCounter(RX); } } } return; }
private void EmitAllocc(int type) { SetEntry(); Instruction instr = new Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.ALLOCC; instr.op1 = StackValue.BuildClassIndex(type); ++pc; codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr); }
protected void EmitJumpDependency() { EmitInstrConsole(ProtoCore.DSASM.kw.jdep); Instruction instr = new Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.JDEP; ++pc; codeBlock.instrStream.instrList.Add(instr); }
private void EmitPushDep(int block, int depth, int classScope) { EmitInstrConsole(ProtoCore.DSASM.kw.pushdep, block.ToString() + "[block]", depth.ToString() + "[depth]", classScope.ToString() + "[classScope]"); ProtoCore.DSASM.Instruction instr = new ProtoCore.DSASM.Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.PUSHDEP; ProtoCore.DSASM.StackValue opBlock = new ProtoCore.DSASM.StackValue(); opBlock.optype = ProtoCore.DSASM.AddressType.BlockIndex; opBlock.opdata = block; ProtoCore.DSASM.StackValue opDepth = new ProtoCore.DSASM.StackValue(); opDepth.optype = ProtoCore.DSASM.AddressType.Int; opDepth.opdata = depth; ProtoCore.DSASM.StackValue opClass = new ProtoCore.DSASM.StackValue(); opClass.optype = ProtoCore.DSASM.AddressType.ClassIndex; opClass.opdata = classScope; instr.op1 = opBlock; instr.op2 = opDepth; instr.op3 = opClass; ++pc; codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr); }
private void EmitSetExpressionUID(int exprId) { EmitInstrConsole(ProtoCore.DSASM.kw.setexpuid, exprId.ToString() + "[exprId]"); ProtoCore.DSASM.Instruction instr = new ProtoCore.DSASM.Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.SETEXPUID; ProtoCore.DSASM.StackValue opExId = new ProtoCore.DSASM.StackValue(); opExId.optype = ProtoCore.DSASM.AddressType.Int; opExId.opdata = exprId; instr.op1 = opExId; ++pc; codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr); }
private void Exec(Instruction instruction) { switch (instruction.opCode) { case OpCode.ALLOC: { ALLOC_Handler(instruction); return; } case OpCode.ALLOCC: { ALLOCC_Handler(instruction); return; } case OpCode.ALLOCM: { ALLOCM_Handler(instruction); return; } case OpCode.PUSH: { PUSH_Handler(instruction); return; } case OpCode.PUSHW: { PUSHW_Handler(instruction); return; } case OpCode.PUSHINDEX: { PUSHINDEX_Handler(instruction); return; } case OpCode.PUSHG: { PUSHG_Handler(instruction); return; } case OpCode.PUSHB: { PUSHB_Handler(instruction); return; } case OpCode.POPB: { POPB_Handler(instruction); return; } case OpCode.PUSHM: { PUSHM_Handler(instruction); return; } case OpCode.PUSHLIST: { PUSHLIST_Handler(instruction); return; } case OpCode.PUSH_ARRAYKEY: { PUSH_VARSIZE_Handler(instruction); return; } case OpCode.POP: { POP_Handler(instruction); return; } case OpCode.POPW: { POPW_Handler(instruction); return; } case OpCode.POPG: { POPG_Handler(instruction); return; } case OpCode.POPM: { POPM_Handler(instruction); return; } case OpCode.POPLIST: { POPLIST_Handler(instruction); return; } case OpCode.MOV: { MOV_Handler(instruction); return; } case OpCode.ADD: { ADD_Handler(instruction); return; } case OpCode.ADDD: { ADDD_Handler(instruction); return; } case OpCode.SUB: { SUB_Handler(instruction); return; } case OpCode.SUBD: { SUBD_Handler(instruction); return; } case OpCode.MUL: { MUL_Handler(instruction); return; } case OpCode.MULD: { MULD_Handler(instruction); return; } case OpCode.DIV: { DIV_Handler(instruction); return; } case OpCode.DIVD: { DIVD_Handler(instruction); return; } case OpCode.MOD: { MOD_Handler(instruction); return; } #if ENABLE_BIT_OP case OpCode.BITAND: { BITAND_HANDLER(instruction); return; } case OpCode.BITOR: { BITOR_HANDLER(instruction); return; } case OpCode.BITXOR: { BITXOR_HANDLER(instruction); return; } case OpCode.NEGATE: { NEGATE_HAndler(instruction); return; #endif case OpCode.NEG: { NEG_Handler(instruction); return; } case OpCode.AND: { AND_Handler(instruction); return; } case OpCode.OR: { OR_Handler(instruction); return; } case OpCode.NOT: { NOT_Handler(instruction); return; } case OpCode.EQ: { EQ_Handler(instruction); return; } case OpCode.EQD: { EQD_Handler(instruction); return; } case OpCode.NQ: { NQ_Handler(instruction); return; } case OpCode.NQD: { NQD_Handler(instruction); return; } case OpCode.GT: { GT_Handler(instruction); return; } case OpCode.GTD: { GTD_Handler(instruction); return; } case OpCode.LT: { LT_Handler(instruction); return; } case OpCode.LTD: { LTD_Handler(instruction); return; } case OpCode.GE: { GE_Handler(instruction); return; } case OpCode.GED: { GED_Handler(instruction); return; } case OpCode.LE: { LE_Handler(instruction); return; } case OpCode.LED: { LED_Handler(instruction); return; } case OpCode.ALLOCA: { ALLOCA_Handler(instruction); return; } case OpCode.BOUNCE: { BOUNCE_Handler(instruction); return; } case OpCode.CALL: { CALL_Handler(instruction); return; } case OpCode.CALLC: { CALLC_Handler(instruction); return; } case OpCode.CALLR: { CALLR_Handler(instruction); return; } case OpCode.RETC: { RETC_Handler(instruction); return; } case OpCode.RETB: { RETB_Handler(instruction); return; } case OpCode.RETCN: { RETCN_Handler(instruction); return; } case OpCode.RETURN: { RETURN_Handler(instruction); return; } case OpCode.JMP: { JMP_Handler(instruction); return; } case OpCode.CJMP: { CJMP_Handler(instruction); return; } case OpCode.JMP_EQ: { JMP_EQ_Handler(instruction); return; } case OpCode.JMP_GT: { JMP_GT_Handler(instruction); return; } case OpCode.JMP_GTEQ: { JMP_GTEQ_Handler(instruction); return; } case OpCode.JMP_LT: { JMP_LT_Handler(instruction); return; } case OpCode.JMP_LTEQ: { JMP_LTEQ_Handler(instruction); return; } case OpCode.JMP_NEQ: { JMP_NEQ_Handler(instruction); return; } case OpCode.JLZ: { JLZ_Handler(instruction); return; } case OpCode.JGZ: { JGZ_Handler(instruction); return; } case OpCode.JZ: { JZ_Handler(instruction); return; } case OpCode.CAST: { CAST_Handler(instruction); return; } case OpCode.DEP: { DEP_Handler(instruction); return; } case OpCode.PUSHDEP: { PUSHDEP_Handler(instruction); return; } case OpCode.DEPX: { DEPX_Handler(instruction); return; } case OpCode.THROW: { THROW_Handler(instruction); return; } case OpCode.SETEXPUID: { SETEXPUID_Handler(instruction); return; } default: //Unknown OpCode throw new NotImplementedException("Unknown Op code, NIE Marker: {D6028708-CD47-4D0B-97FC-E681BD65DB5C}"); } }
private void EmitAllocc(int type) { SetEntry(); ProtoCore.DSASM.Instruction instr = new ProtoCore.DSASM.Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.ALLOCC; ProtoCore.DSASM.StackValue op = new ProtoCore.DSASM.StackValue(); op.optype = ProtoCore.DSASM.AddressType.ClassIndex; op.opdata = type; instr.op1 = op; ++pc; codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr); }
private void JMP_GT_Handler(Instruction instruction) { StackValue opdata1 = GetOperandData(instruction.op1); StackValue opdata2 = GetOperandData(instruction.op2); bool isGT = false; if (AddressType.Double == opdata1.optype || AddressType.Double == opdata2.optype) { isGT = opdata1.opdata_d > opdata2.opdata_d; } else { isGT = opdata1.opdata > opdata2.opdata; } if (isGT) { pc = (int)instruction.op3.opdata; } else { ++pc; } return; }
private void JMP_LT_Handler(Instruction instruction) { StackValue opdata1 = GetOperandData(instruction.op1); StackValue opdata2 = GetOperandData(instruction.op2); if (AddressType.Double == opdata1.optype || AddressType.Double == opdata2.optype) { if (opdata1.opdata_d < opdata2.opdata_d) { pc = (int)instruction.op3.opdata; } else { ++pc; } } else { if (opdata1.opdata < opdata2.opdata) { pc = (int)instruction.op3.opdata; } else { ++pc; } } return; }
private void JMP_Handler(Instruction instruction) { pc = (int)instruction.op1.opdata; return; }
private void CJMP_Handler(Instruction instruction) { StackValue opdata1 = GetOperandData(instruction.op1); if (opdata1.optype == ProtoCore.DSASM.AddressType.Double) { if (0 == opdata1.opdata_d) { pc = (int)GetOperandData(instruction.op3).opdata; } else { pc = (int)GetOperandData(instruction.op2).opdata; } } else { if (opdata1.optype == ProtoCore.DSASM.AddressType.Pointer) { pc = (int)GetOperandData(instruction.op2).opdata; } else if (0 == opdata1.opdata) { pc = (int)GetOperandData(instruction.op3).opdata; } else { pc = (int)GetOperandData(instruction.op2).opdata; } } return; }
private void RETURN_Handler(Instruction instruction) { isGlobScope = true; runtimeVerify(rmem.ValidateStackFrame()); int ptr = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexThisPtr).opdata; int ci = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata; int fi = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunction).opdata; int blockId = (int)SX.opdata; StackValue svBlockDecl = rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexRegisterSX); Validity.Assert(AddressType.BlockIndex == svBlockDecl.optype); blockId = (int)svBlockDecl.opdata; ProcedureNode procNode = GetProcedureNode(blockId, ci, fi); if (core.Options.ExecuteSSA) { if (core.Options.GCTempVarsOnDebug && core.Options.IDEDebugMode) { // GC anonymous variables in the return stmt if (null != Properties.executingGraphNode && !Properties.executingGraphNode.IsSSANode()) { GCAnonymousSymbols(Properties.executingGraphNode.symbolListWithinExpression); Properties.executingGraphNode.symbolListWithinExpression.Clear(); } } } pc = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexReturnAddress).opdata; executingBlock = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunctionCallerBlock).opdata; if (core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { ReturnSiteGC(blockId, ci, fi); } RestoreFromCall(); core.RunningBlock = executingBlock; // If we're returning from a block to a function, the instruction stream needs to be restored. StackValue sv = rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexRegisterTX); Validity.Assert(AddressType.CallingConvention == sv.optype); CallingConvention.CallType callType = (CallingConvention.CallType)sv.opdata; bool explicitCall = CallingConvention.CallType.kExplicit == callType; isExplicitCall = explicitCall; List<bool> execStateRestore = new List<bool>(); if (!core.Options.IDEDebugMode || core.ExecMode == InterpreterMode.kExpressionInterpreter) { // Get stack frame size int localCount = 0; int paramCount = 0; GetLocalAndParamCount(blockId, ci, fi, out localCount, out paramCount); // Retrieve the execution execution states int execstates = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexExecutionStates).opdata; if (execstates > 0) { int offset = ProtoCore.DSASM.StackFrame.kStackFrameSize + localCount + paramCount; for (int n = 0; n < execstates; ++n) { int relativeIndex = -offset - n - 1; StackValue svState = rmem.GetAtRelative(relativeIndex); Validity.Assert(svState.optype == AddressType.Boolean); execStateRestore.Add(svState.opdata == 0 ? false : true); } } // Pop the stackframe rmem.FramePointer = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; // Get the size of the stackframe and all variable size contents (local, args and exec states) int stackFrameSize = ProtoCore.DSASM.StackFrame.kStackFrameSize + localCount + paramCount + execstates; rmem.PopFrame(stackFrameSize); if (core.ExecMode != InterpreterMode.kExpressionInterpreter) { // Restoring the registers require the current frame pointer of the stack frame RestoreRegistersFromStackFrame(); bounceType = (ProtoCore.DSASM.CallingConvention.BounceType)TX.opdata; } } terminate = !explicitCall; // Comment Jun: Dispose calls are always implicit and need to terminate // TODO Jun: This instruction should not know about dispose bool isDispose = CoreUtils.IsDisposeMethod(procNode.name); if (isDispose) { terminate = true; } // Let the return graphNode always be active if (null != Properties.executingGraphNode) { Properties.executingGraphNode.isDirty = true; } Properties = PopInterpreterProps(); if (explicitCall) { bool wasDebugPropsPopped = false; if (!isDispose) { wasDebugPropsPopped = DebugReturn(procNode, pc); } // This condition should only be reached in the following cases: // 1. Debug StepOver or External Function call in non-replicating mode // 2. Normal execution in Serial (explicit call), non-replicating mode if (!wasDebugPropsPopped) { RX = CallSite.PerformReturnTypeCoerce(procNode, core, RX); // Comment Jun: For explicit calls, we need to manually GC decrement the arguments passed into the function // These arguments were GC incremented on callr for (int i = 0; i < Properties.functionCallArguments.Count; ++i) { GCUtils.GCRelease(Properties.functionCallArguments[i], core); } StackValue svRet = RX; GCDotMethods(procNode.name, ref svRet, Properties.functionCallDotCallDimensions, Properties.functionCallArguments); DecRefCounter(svRet); RX = svRet; } } // Restore the execution states if (execStateRestore.Count > 0) { // Now that the stack frame is popped off, we can retrieve the returned scope // Get graphnodes at the current scope after the return int currentScopeClass = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata; int currentScopeFunction = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunction).opdata; bool isReturningFromRecursiveCall = procNode.procId == currentScopeFunction; if (isReturningFromRecursiveCall) { // Since there are execution states retrieved from the stack frame, // this means that we must be returning to a function and not the global scope Validity.Assert(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; List<AssociativeGraph.GraphNode> graphNodesInScope = depgraph.GetGraphNodesAtScope(currentScopeClass, currentScopeFunction); Validity.Assert(execStateRestore.Count == graphNodesInScope.Count); for (int n = 0; n < execStateRestore.Count; ++n) { graphNodesInScope[n].isDirty = execStateRestore[n]; } } } return; }
private void RETCN_Handler(Instruction instruction) { if (core.ExecMode != InterpreterMode.kExpressionInterpreter) { core.Rmem.PopConstructBlockId(); } StackValue op1 = instruction.op1; runtimeVerify(op1.optype == AddressType.BlockIndex); int blockId = (int)op1.opdata; CodeBlock codeBlock = core.CompleteCodeBlockList[blockId]; runtimeVerify(codeBlock.blockType == CodeBlockType.kConstruct); GCCodeBlock(blockId); pc++; return; }
private void RETB_Handler(Instruction instruction) { if (core.ExecMode != InterpreterMode.kExpressionInterpreter) { core.Rmem.PopConstructBlockId(); } if (!core.Options.IsDeltaExecution || (core.Options.IsDeltaExecution && 0 != core.RunningBlock)) { GCCodeBlock(core.RunningBlock); } if (ProtoCore.DSASM.CallingConvention.BounceType.kExplicit == bounceType) { RestoreFromBounce(); core.RunningBlock = executingBlock; } if (ProtoCore.DSASM.CallingConvention.BounceType.kImplicit == bounceType) { pc = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexReturnAddress).opdata; terminate = true; } ProtoCore.DSASM.StackFrameType type = StackFrameType.kTypeLanguage; // Comment Jun: Just want to see if this is the global rerb, in which case we dont retrieve anything //if (executingBlock > 0) { StackValue svCallerType = rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexCallerStackFrameType); type = (ProtoCore.DSASM.StackFrameType)svCallerType.opdata; } // Pop the frame as we are adding stackframes for language blocks as well - pratapa // Do not do this for the final Retb //if (core.RunningBlock != 0) if (!core.Options.IDEDebugMode || core.ExecMode == InterpreterMode.kExpressionInterpreter) { rmem.FramePointer = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize); if (bounceType == CallingConvention.BounceType.kExplicit) { // Restoring the registers require the current frame pointer of the stack frame RestoreRegistersFromStackFrame(); bounceType = (ProtoCore.DSASM.CallingConvention.BounceType)TX.opdata; #if ENABLE_EXCEPTION_HANDLING core.ExceptionHandlingManager.CurrentActiveRegistration = core.stackActiveExceptionRegistration.Pop(); if (core.ExceptionHandlingManager.IsStackUnwinding) { #region __MERGE_WITH_STACKUNWIND // The excecution of last langage block is interrupted // abnormally because of stack unwinding, so we need to // run GC to reclaim those allocated memory. GCCodeBlock(core.RunningBlock); int newpc = ProtoCore.DSASM.Constants.kInvalidIndex; if (core.ExceptionHandlingManager.CanHandleIt(ref newpc)) { LX = RX; pc = newpc; core.ExceptionHandlingManager.SetHandled(); } // else cannot handle in this scope, so in the next // loop of Execute(), current executive will be ; // ended and returns to the last scope, continues // stack unwinding int origRunningBlock = executingBlock; core.RunningBlock = origRunningBlock; #endregion } else { DecRefCounter(RX); } #else DecRefCounter(RX); #endif } } else { DecRefCounter(RX); } if (type == StackFrameType.kTypeFunction) { // Comment Jun: // Consider moving this to a restore to function method // If this language block was called explicitly, only then do we need to restore the instruction stream if (bounceType == CallingConvention.BounceType.kExplicit) { // If we're returning from a block to a function, the instruction stream needs to be restored. StackValue sv = rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexRegisterTX); Validity.Assert(AddressType.CallingConvention == sv.optype); CallingConvention.CallType callType = (CallingConvention.CallType)sv.opdata; if (CallingConvention.CallType.kExplicit == callType) { int callerblock = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunctionBlock).opdata; istream = exe.instrStreamList[callerblock]; } } } Properties = PopInterpreterProps(); return; }
private void THROW_Handler(Instruction instruction) { #if ENABLE_EXCEPTION_HANDLING runtimeVerify(ProtoCore.DSASM.AddressType.BlockIndex == instruction.op1.optype); int blockId = (int)instruction.op1.opdata; runtimeVerify(ProtoCore.DSASM.AddressType.ClassIndex == instruction.op2.optype); int classScope = (int)instruction.op2.opdata; runtimeVerify(ProtoCore.DSASM.AddressType.FunctionIndex == instruction.op3.optype); int functionScope = (int)instruction.op3.opdata; StackValue exceptionValue = LX; ProtoCore.Exceptions.ExceptionContext context = new Exceptions.ExceptionContext(); context.pc = pc; context.codeBlockId = blockId; context.functionScope = functionScope; context.classScope = classScope; switch (exceptionValue.optype) { case AddressType.Int: context.typeUID = (int)ProtoCore.PrimitiveType.kTypeInt; break; case AddressType.Double: context.typeUID = (int)ProtoCore.PrimitiveType.kTypeDouble; break; case AddressType.Boolean: context.typeUID = (int)ProtoCore.PrimitiveType.kTypeBool; break; case AddressType.Pointer: context.typeUID = (int)exceptionValue.metaData.type; break; default: context.typeUID = (int)ProtoCore.PrimitiveType.kTypeVar; break; } // Walk through exception chain, a.k.a. 1st hand exception // handling core.ExceptionHandlingManager.HandleFirstHandException(context); // The exception can be handled in current scope, so simply jmp to // the corresponding catch block int newpc = ProtoCore.DSASM.Constants.kInvalidIndex; if (core.ExceptionHandlingManager.CanHandleIt(ref newpc)) { pc = newpc; core.ExceptionHandlingManager.SetHandled(); } else { RX = LX; } if (core.ExceptionHandlingManager.IsStackUnwinding) { while (core.stackActiveExceptionRegistration.Count > 1) { StackValue svType = rmem.GetAtRelative(StackFrame.kFrameIndexStackFrameType); StackFrameType type = (StackFrameType)svType.opdata; if (StackFrameType.kTypeLanguage == type) { RestoreFromBounce(); rmem.FramePointer = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize); // Restoring the registers require the current frame pointer of the stack frame RestoreRegistersFromStackFrame(); bounceType = (ProtoCore.DSASM.CallingConvention.BounceType)TX.opdata; core.ExceptionHandlingManager.CurrentActiveRegistration = core.stackActiveExceptionRegistration.Pop(); #region __MERGE_WITH_STACKUNWIND // The excecution of last langage block is interrupted // abnormally because of stack unwinding, so we need to // run GC to reclaim those allocated memory. GCCodeBlock(core.RunningBlock); newpc = ProtoCore.DSASM.Constants.kInvalidIndex; if (core.ExceptionHandlingManager.CanHandleIt(ref newpc)) { LX = RX; pc = newpc; core.ExceptionHandlingManager.SetHandled(); break; } // else cannot handle in this scope, so in the next // loop of Execute(), current executive will be ; // ended and returns to the last scope, continues // stack unwinding int origRunningBlock = executingBlock; core.RunningBlock = origRunningBlock; #endregion } else { RestoreFromCall(); int ci = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata; int fi = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunction).opdata; int localCount = 0; int paramCount = 0; GetLocalAndParamCount(executingBlock, ci, fi, out localCount, out paramCount); rmem.FramePointer = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + localCount + paramCount); } } } return; #else throw new NotImplementedException(); #endif }
private void JMP_NEQ_Handler(Instruction instruction) { StackValue opdata1 = GetOperandData(instruction.op1); StackValue opdata2 = GetOperandData(instruction.op2); if (AddressType.Double == opdata1.optype || AddressType.Double == opdata2.optype) { if (!MathUtils.Equals(opdata1.opdata_d, opdata2.opdata_d)) { pc = (int)instruction.op3.opdata; } else { ++pc; } } else { if (opdata1.opdata != opdata2.opdata) { pc = (int)instruction.op3.opdata; } else { ++pc; } } return; }
private void SETEXPUID_Handler(Instruction instruction) { if (core.Options.IDEDebugMode && core.ExecMode != InterpreterMode.kExpressionInterpreter) { if (core.DebugProps.RunMode == Runmode.StepNext) { if (!core.DebugProps.DebugStackFrameContains(DebugProperties.StackFrameFlagOptions.IsFunctionStepOver)) { // if ec is at end of an expression in imperative lang block // we force restore the breakpoints core.Breakpoints.Clear(); core.Breakpoints.AddRange(core.DebugProps.AllbreakPoints); } } } pc++; return; }
private void JGZ_Handler(Instruction instruction) { StackValue opdata1 = GetOperandData(instruction.op1); if (opdata1.opdata_d > 0) { pc = (int)instruction.op2.opdata; } else { ++pc; } return; }
//protected override void EmitDependency(int exprUID, bool isSSAAssign) protected void EmitDependency(int exprUID, int modBlkUID, bool isSSAAssign) { SetEntry(); EmitInstrConsole(ProtoCore.DSASM.kw.dep, exprUID.ToString() + "[ExprUID]", isSSAAssign.ToString() + "[SSA]"); ProtoCore.DSASM.Instruction instr = new ProtoCore.DSASM.Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.DEP; ProtoCore.DSASM.StackValue opExprId = new ProtoCore.DSASM.StackValue(); opExprId.optype = ProtoCore.DSASM.AddressType.Int; opExprId.opdata = exprUID; instr.op1 = opExprId; ProtoCore.DSASM.StackValue opIsSSA = new ProtoCore.DSASM.StackValue(); opIsSSA.optype = ProtoCore.DSASM.AddressType.Int; opIsSSA.opdata = (isSSAAssign) ? 1 : 0; instr.op2 = opIsSSA; ProtoCore.DSASM.StackValue opModBlkId = new ProtoCore.DSASM.StackValue(); opModBlkId.optype = ProtoCore.DSASM.AddressType.Int; opModBlkId.opdata = modBlkUID; instr.op3 = opModBlkId; ++pc; codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr); }
private void JZ_Handler(Instruction instruction) { StackValue opdata1 = GetOperandData(instruction.op1); if (MathUtils.Equals(opdata1.opdata_d, 0)) { pc = (int)instruction.op2.opdata; } else { ++pc; } return; }
private void EmitRetc(int line = ProtoCore.DSASM.Constants.kInvalidIndex, int col = ProtoCore.DSASM.Constants.kInvalidIndex, int eline = ProtoCore.DSASM.Constants.kInvalidIndex, int ecol = ProtoCore.DSASM.Constants.kInvalidIndex) { ProtoCore.DSASM.Instruction instr = new ProtoCore.DSASM.Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.RETC; ++pc; instr.debug = GetDebugObject(line, col, eline, ecol, ProtoCore.DSASM.Constants.kInvalidIndex); codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr, line, col); updatePcDictionary(line, col); }
private void CAST_Handler(Instruction instruction) { ++pc; return; }
private void EmitPushVarSize(int symbol, int block, int classIndex) { ProtoCore.DSASM.Instruction instr = new ProtoCore.DSASM.Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.PUSH_VARSIZE; ProtoCore.DSASM.StackValue op1 = new ProtoCore.DSASM.StackValue(); op1.optype = ProtoCore.DSASM.AddressType.VarIndex; op1.opdata = symbol; instr.op1 = op1; ProtoCore.DSASM.StackValue op2 = new ProtoCore.DSASM.StackValue(); op2.optype = ProtoCore.DSASM.AddressType.BlockIndex; op2.opdata = block; instr.op2 = op2; ProtoCore.DSASM.StackValue op3 = new ProtoCore.DSASM.StackValue(); op3.optype = ProtoCore.DSASM.AddressType.ClassIndex; op3.opdata = classIndex; instr.op3 = op3; ++pc; codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr); }
//instruction dep(block, symbol) // def sv = stack.get(block,symbol) // if sv is not equal to _dx (i.e. is dirty) // // An update is triggered // // Find all graph nodes whos dependents contain this symbol // // Mark those nodes as dirty // for n = 0 to graphNodeList.size n++ // def index = graphNodeList[n].Contains(block,symbol) // if index is valid // graphNodeList[n].isDirty = true // break // end // end // end // SetupDependencyGraph() //end private void DEP_Handler(Instruction instruction) { // This expression ID of this instruction runtimeVerify(ProtoCore.DSASM.AddressType.Int == instruction.op1.optype); int exprID = (int)instruction.op1.opdata; // The SSA assignment flag runtimeVerify(ProtoCore.DSASM.AddressType.Int == instruction.op2.optype); bool isSSA = (1 == (int)instruction.op2.opdata) ? true : false; runtimeVerify(ProtoCore.DSASM.AddressType.Int == instruction.op3.optype); int modBlkID = (int)instruction.op3.opdata; // The current function and class scope int ci = DSASM.Constants.kInvalidIndex; int fi = DSASM.Constants.kGlobalScope; bool isInFunction = core.FunctionCallDepth > 0; StackValue svType = rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexStackFrameType); ProtoCore.DSASM.StackFrameType type = (ProtoCore.DSASM.StackFrameType)svType.opdata; isInFunction = IsInsideFunction(); if (core.Options.IDEDebugMode && core.ExecMode != InterpreterMode.kExpressionInterpreter) { Validity.Assert(core.DebugProps.DebugStackFrame.Count > 0); { isInFunction = core.DebugProps.DebugStackFrameContains(DebugProperties.StackFrameFlagOptions.FepRun); } } if (isInFunction) { ci = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata; fi = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunction).opdata; } if (null != Properties.executingGraphNode) { // Append this modified graph into the x-lang list if (!isSSA && (Properties.executingGraphNode.updateNodeRefList.Count > 0)) { if (!istream.xUpdateList.Contains(Properties.executingGraphNode.updateNodeRefList[0])) { istream.xUpdateList.Add(Properties.executingGraphNode.updateNodeRefList[0]); } } if (core.Options.ExecuteSSA) { if (core.Options.GCTempVarsOnDebug && core.Options.IDEDebugMode) { if (!Properties.executingGraphNode.IsSSANode()) { bool isSetter = Properties.executingGraphNode.updateNodeRefList[0].nodeList.Count > 1; GCAnonymousSymbols(Properties.executingGraphNode.symbolListWithinExpression, isSetter); Properties.executingGraphNode.symbolListWithinExpression.Clear(); } } } if (core.Options.ExecuteSSA) { if (!Properties.executingGraphNode.IsSSANode()) { foreach (AssociativeGraph.GraphNode gnode in deferedGraphNodes) { gnode.isDirty = true; } deferedGraphNodes.Clear(); } } } UpdateGraph(exprID, modBlkID, isSSA); // Get the next graph to be executed SetupNextExecutableGraph(fi, ci); return; }
protected override void EmitRetcn(int blockId = Constants.kInvalidIndex, int line = ProtoCore.DSASM.Constants.kInvalidIndex, int col = ProtoCore.DSASM.Constants.kInvalidIndex, int endline = ProtoCore.DSASM.Constants.kInvalidIndex, int endcol = ProtoCore.DSASM.Constants.kInvalidIndex) { ProtoCore.DSASM.Instruction instr = new ProtoCore.DSASM.Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.RETCN; ProtoCore.DSASM.StackValue op1 = new ProtoCore.DSASM.StackValue(); op1.optype = AddressType.BlockIndex; op1.opdata = blockId; instr.op1 = op1; AuditReturnLocationFromCodeBlock(ref line, ref col, ref endline, ref endcol); ++pc; instr.debug = GetDebugObject(line, col, endline, endcol, pc); codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr, line, col); updatePcDictionary(line, col); }
private void PUSHDEP_Handler(Instruction instruction) { // The symbol block runtimeVerify(ProtoCore.DSASM.AddressType.BlockIndex == instruction.op1.optype); int block = (int)instruction.op1.opdata; runtimeVerify(ProtoCore.DSASM.AddressType.Int == instruction.op2.optype); int depth = (int)instruction.op2.opdata; // The symbol and its class index runtimeVerify(ProtoCore.DSASM.AddressType.ClassIndex == instruction.op3.optype); int classIndex = (int)instruction.op3.opdata; // Get the identifier list List<StackValue> symbolList = new List<StackValue>(); for (int n = 0; n < depth; ++n) { // TODO Jun: use the proper ID for this StackValue sv = rmem.Pop(); runtimeVerify(sv.optype == AddressType.Int); symbolList.Add(sv); } symbolList.Reverse(); // TODO Jun: use the proper ID for this runtimeVerify(AddressType.Int == symbolList[0].optype); int symindex = (int)symbolList[0].opdata; if (ProtoCore.DSASM.Constants.kInvalidIndex != symindex) { ProtoCore.DSASM.SymbolNode symnode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != classIndex) { symnode = core.ClassTable.ClassNodes[classIndex].symbols.symbolList[symindex]; } else { symnode = core.DSExecutable.runtimeSymbols[block].symbolList[symindex]; } ProtoCore.AssociativeGraph.UpdateNode updateNode = new AssociativeGraph.UpdateNode(); updateNode.symbol = symnode; updateNode.nodeType = AssociativeGraph.UpdateNodeType.kSymbol; // Build the first symbol of the modified ref ProtoCore.AssociativeGraph.UpdateNodeRef modifiedRef = new AssociativeGraph.UpdateNodeRef(); modifiedRef.nodeList.Add(updateNode); modifiedRef.block = symnode.runtimeTableIndex; // Update the current type classIndex = symnode.datatype.UID; // Build the rest of the list of symbols of the modified ref for (int n = 1; n < symbolList.Count; ++n) { // TODO Jun: This should be a memvarindex address type runtimeVerify(symbolList[n].optype == AddressType.Int); symindex = (int)symbolList[n].opdata; // Get the symbol and append it to the modified ref updateNode = new AssociativeGraph.UpdateNode(); updateNode.symbol = core.ClassTable.ClassNodes[classIndex].symbols.symbolList[symindex]; updateNode.nodeType = AssociativeGraph.UpdateNodeType.kSymbol; runtimeVerify(null != updateNode.symbol); modifiedRef.nodeList.Add(updateNode); // Update the current type classIndex = symnode.datatype.UID; } // Get the current value of symbol StackValue svSym; if (DSASM.Constants.kInvalidIndex != symnode.classScope && DSASM.Constants.kInvalidIndex == symnode.functionIndex) { svSym = StackValue.BuildMemVarIndex(symnode.symbolTableIndex); } else { svSym = StackValue.BuildVarIndex(symnode.symbolTableIndex); } modifiedRef.symbolData = GetOperandData(block, svSym, instruction.op3); bool addNewModifiedRef = true; for (int i = 0; i < istream.xUpdateList.Count; ++i) { var udpatedRef = istream.xUpdateList[i]; if (modifiedRef.IsEqual(istream.xUpdateList[i])) { istream.xUpdateList[i].symbolData = modifiedRef.symbolData; addNewModifiedRef = false; break; } } if (addNewModifiedRef) { istream.xUpdateList.Add(modifiedRef); } } ++pc; return; }
protected override void EmitReturn(int line = ProtoCore.DSASM.Constants.kInvalidIndex, int col = ProtoCore.DSASM.Constants.kInvalidIndex, int endline = ProtoCore.DSASM.Constants.kInvalidIndex, int endcol = ProtoCore.DSASM.Constants.kInvalidIndex) { Instruction instr = new Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.RETURN; AuditReturnLocation(ref line, ref col, ref endline, ref endcol); ++pc; instr.debug = GetDebugObject(line, col, endline, endcol, ProtoCore.DSASM.Constants.kInvalidIndex); codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr, line, col); updatePcDictionary(line, col); }
// // instruction depx() // foreach dependencygraph in exe.instructionstreams // foreach graphnode in dependencygraph // foreach updatenode in updatelist // if graphnode.dependsOn(updatenode.symbol) // if graphnode.symdata is equal to updatenode.symdata // graphnode.isdirty = true // end // end // end // end // end // updatelist.clear() // end // private void DEPX_Handler(Instruction instruction) { //XLangUpdateDependencyGraph(); //// Clear the propagation list //istream.xUpdateList.Clear(); runtimeVerify(Language.kAssociative == istream.language); // The current function and class scope int ci = DSASM.Constants.kInvalidIndex; int fi = DSASM.Constants.kGlobalScope; if (fepRun) { ci = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata; fi = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFunction).opdata; } // Set the next graph to be executed SetupNextExecutableGraph(fi, ci); return; }
protected void EmitDependency(int exprUID, int modBlkUID, bool isSSAAssign) { SetEntry(); EmitInstrConsole(ProtoCore.DSASM.kw.dep, exprUID.ToString() + "[ExprUID]", isSSAAssign.ToString() + "[SSA]"); Instruction instr = new Instruction(); instr.opCode = ProtoCore.DSASM.OpCode.DEP; instr.op1 = StackValue.BuildInt(exprUID); instr.op2 = StackValue.BuildInt(isSSAAssign ? 1 : 0); instr.op3 = StackValue.BuildInt(modBlkUID); ++pc; codeBlock.instrStream.instrList.Add(instr); // TODO: Figure out why using AppendInstruction fails for adding these instructions to ExpressionInterpreter //AppendInstruction(instr); if (!core.Options.IsDeltaExecution) { EmitJumpDependency(); } }
protected virtual void CALLR_Handler(Instruction instruction) { bool isDynamicCall = false; Instruction instr = new Instruction(); //a new copy of instruction. this will be modified if it is dynamic call instr.op1 = instruction.op1; instr.op2 = instruction.op2; instr.op3 = instruction.op3; instr.debug = instruction.debug; instr.opCode = instruction.opCode; //core.DebugProps.IsInFunction = true; if (instr.op1.optype == AddressType.Dynamic) { isDynamicCall = true; bool succeeded = ProcessDynamicFunction(instr); if (!succeeded) { RX = StackValue.Null; ++pc; return; } } // runtime verification runtimeVerify(ProtoCore.DSASM.AddressType.FunctionIndex == instr.op1.optype); int functionIndex = (int)instr.op1.opdata; runtimeVerify(ProtoCore.DSASM.AddressType.ClassIndex == instr.op2.optype); int classIndex = (int)instr.op2.opdata; StackValue valDepth = instr.op3; runtimeVerify(ProtoCore.DSASM.AddressType.Int == valDepth.optype); int depth = (int)valDepth.opdata; // chain up exception registration int blockId = ProtoCore.DSASM.Constants.kInvalidIndex; int stackIndex = rmem.Stack.Count - 3; if (rmem.Stack[stackIndex].optype == AddressType.BlockIndex) { blockId = (int)rmem.Stack[stackIndex].opdata; } #if ENABLE_EXCEPTION_HANDLING core.stackActiveExceptionRegistration.Push(core.ExceptionHandlingManager.CurrentActiveRegistration); core.ExceptionHandlingManager.SwitchContextTo(blockId, functionIndex, classIndex, pc); #endif ++core.FunctionCallDepth; bool explicitCall = false; // // Comment Jun: // This solution is implemented to be able to capture Exceptions thrown from the callsite that cannot be handled by the runtime // It will allow execution to continue in graph mode while nullifying the RX register // This is a temporary solution until unhandle exceptions in the callsite are addressed // // TODO: // Luke/Jun to fix the error propagation from the callsite // if (!core.Options.IsDeltaExecution) { RX = Callr(functionIndex, classIndex, depth, ref explicitCall, isDynamicCall, instr.debug != null); } else { // // Comment Jun: // Running in graph mode, nullify the result and continue. // The only affected downstream operations are the ones connected to the graph associated with this call try { RX = Callr(functionIndex, classIndex, depth, ref explicitCall, isDynamicCall, instr.debug != null); } catch (ReplicationCaseNotCurrentlySupported e) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kReplicationWarning, e.Message); RX = StackValue.Null; } } --core.FunctionCallDepth; if (!explicitCall) { #if ENABLE_EXCEPTION_HANDLING core.ExceptionHandlingManager.CurrentActiveRegistration = core.stackActiveExceptionRegistration.Pop(); if (core.ExceptionHandlingManager.IsStackUnwinding) { int newpc = ProtoCore.DSASM.Constants.kInvalidIndex; if (core.ExceptionHandlingManager.CanHandleIt(ref newpc)) { LX = RX; pc = newpc; core.ExceptionHandlingManager.SetHandled(); } else { // Clean up stack isGlobScope = true; runtimeVerify(rmem.ValidateStackFrame()); pc = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexReturnAddress).opdata; ReturnSiteGC(blockId, classIndex, functionIndex); rmem.FramePointer = (int)rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; int localCount, paramCount; GetLocalAndParamCount(blockId, classIndex, functionIndex, out localCount, out paramCount); rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + localCount + paramCount); if (fepRunStack.Count > 0) { terminate = fepRunStack.Pop(); } else if (fepRun) { terminate = true; } } } else { ++pc; setPC(pc); } #else ++pc; #endif } return; }