private void ImportProcedure(string library, ProcedureNode proc) { string procName = proc.name; if (proc.isAutoGeneratedThisProc || CoreUtils.IsSetter(procName) || CoreUtils.IsDisposeMethod(procName) || CoreUtils.StartsWithDoubleUnderscores(procName)) { return; } string obsoleteMessage = ""; int classScope = proc.classScope; string className = string.Empty; MethodAttributes methodAttribute = proc.MethodAttribute; ClassAttributes classAttribute = null; if (classScope != Constants.kGlobalScope) { var classNode = LibraryManagementCore.ClassTable.ClassNodes[classScope]; classAttribute = classNode.ClassAttributes; className = classNode.name; } // MethodAttribute's HiddenInLibrary has higher priority than // ClassAttribute's HiddenInLibrary var isVisible = true; var canUpdatePeriodically = false; if (methodAttribute != null) { isVisible = !methodAttribute.HiddenInLibrary; canUpdatePeriodically = methodAttribute.CanUpdatePeriodically; } else { if (classAttribute != null) { isVisible = !classAttribute.HiddenInLibrary; } } FunctionType type; if (classScope == Constants.kGlobalScope) { type = FunctionType.GenericFunction; } else { if (CoreUtils.IsGetter(procName)) { type = proc.isStatic ? FunctionType.StaticProperty : FunctionType.InstanceProperty; string property; if (CoreUtils.TryGetPropertyName(procName, out property)) { procName = property; } } else { if (proc.isConstructor) { type = FunctionType.Constructor; } else if (proc.isStatic) { type = FunctionType.StaticMethod; } else { type = FunctionType.InstanceMethod; } } } List <TypedParameter> arguments = proc.argInfoList.Zip( proc.argTypeList, (arg, argType) => { AssociativeNode defaultArgumentNode; // Default argument specified by DefaultArgumentAttribute // takes higher priority if (!TryGetDefaultArgumentFromAttribute(arg, out defaultArgumentNode) && arg.IsDefault) { var binaryExpr = arg.DefaultExpression as BinaryExpressionNode; if (binaryExpr != null) { defaultArgumentNode = binaryExpr.RightNode; } } return(new TypedParameter(arg.Name, argType, defaultArgumentNode)); }).ToList(); IEnumerable <string> returnKeys = null; if (proc.MethodAttribute != null) { if (proc.MethodAttribute.ReturnKeys != null) { returnKeys = proc.MethodAttribute.ReturnKeys; } if (proc.MethodAttribute.IsObsolete) { obsoleteMessage = proc.MethodAttribute.ObsoleteMessage; } } var function = new FunctionDescriptor(new FunctionDescriptorParams { Assembly = library, ClassName = className, FunctionName = procName, Parameters = arguments, ReturnType = proc.returntype, FunctionType = type, IsVisibleInLibrary = isVisible, ReturnKeys = returnKeys, PathManager = pathManager, IsVarArg = proc.isVarArg, ObsoleteMsg = obsoleteMessage, CanUpdatePeriodically = canUpdatePeriodically, IsBuiltIn = pathManager.PreloadedLibraries.Contains(library) }); AddImportedFunctions(library, new[] { function }); }
/// <summary> /// Sets the function to an inactive state where it can no longer be used by the front-end and backend /// </summary> /// <param name="functionDef"></param> public void SetFunctionInactive(FunctionDefinitionNode functionDef) { // DS language only supports function definition on the global and first language block scope // TODO Jun: Determine if it is still required to combine function tables in the codeblocks and callsite // Update the functiond definition in the codeblocks int hash = CoreUtils.GetFunctionHash(functionDef); ProcedureNode procNode = null; foreach (CodeBlock block in CodeBlockList) { // Update the current function definition in the current block procNode = block.procedureTable.Procedures.FirstOrDefault(p => p.HashID == hash); int index = procNode == null ? Constants.kInvalidIndex: procNode.ID; if (Constants.kInvalidIndex == index) { continue; } procNode.IsActive = false; // Remove staled graph nodes var graph = block.instrStream.dependencyGraph; graph.GraphList.RemoveAll(g => g.classIndex == ClassIndex && g.procIndex == index); graph.RemoveNodesFromScope(Constants.kGlobalScope, index); // Make a copy of all symbols defined in this function var localSymbols = block.symbolTable.symbolList.Values .Where(n => n.classScope == Constants.kGlobalScope && n.functionIndex == index) .ToList(); foreach (var symbol in localSymbols) { block.symbolTable.UndefineSymbol(symbol); } break; } if (null != procNode) { // Remove codeblock defined in procNode from CodeBlockList and CompleteCodeBlockList foreach (int cbID in procNode.ChildCodeBlocks) { CompleteCodeBlockList.RemoveAll(x => x.codeBlockId == cbID); foreach (CodeBlock cb in CodeBlockList) { cb.children.RemoveAll(x => x.codeBlockId == cbID); } } } // Update the function definition in global function tables foreach (KeyValuePair <int, Dictionary <string, FunctionGroup> > functionGroupList in DSExecutable.FunctionTable.GlobalFuncTable) { foreach (KeyValuePair <string, FunctionGroup> functionGroup in functionGroupList.Value) { functionGroup.Value.FunctionEndPoints.RemoveAll(func => func.procedureNode.HashID == hash); } } }
public void SetUpStepOverFunctionCalls(RuntimeCore runtimeCore, ProcedureNode fNode, GraphNode graphNode, bool hasDebugInfo) { int tempPC = DebugEntryPC; int limit = 0; // end pc of current expression InstructionStream istream; int pc = tempPC; if (runtimeCore.DebugProps.InlineConditionOptions.isInlineConditional) { tempPC = InlineConditionOptions.startPc; limit = InlineConditionOptions.endPc; istream = runtimeCore.DSExecutable.instrStreamList[InlineConditionOptions.instructionStream]; } else { pc = tempPC; istream = runtimeCore.DSExecutable.instrStreamList[runtimeCore.RunningBlock]; if (istream.language == Language.Associative) { limit = FindEndPCForAssocGraphNode(pc, istream, fNode, graphNode, runtimeCore.Options.ExecuteSSA); //Validity.Assert(limit != ProtoCore.DSASM.Constants.kInvalidIndex); } else if (istream.language == Language.Imperative) { // Check for 'SETEXPUID' instruction to check for end of expression while (++pc < istream.instrList.Count) { Instruction instr = istream.instrList[pc]; if (instr.opCode == OpCode.SETEXPUID) { limit = pc; break; } } } } // Determine if this is outermost CALLR in the expression // until then do not restore any breakpoints // If outermost CALLR, restore breakpoints after end of expression pc = tempPC; int numNestedFunctionCalls = 0; while (++pc <= limit) { Instruction instr = istream.instrList[pc]; if (instr.opCode == OpCode.CALLR && instr.debug != null) { numNestedFunctionCalls++; } } if (numNestedFunctionCalls == 0) { // If this is the outermost function call runtimeCore.Breakpoints.Clear(); runtimeCore.Breakpoints.AddRange(AllbreakPoints); pc = tempPC; while (++pc <= limit) { Instruction instr = istream.instrList[pc]; // We still want to break at the closing brace of a function or ctor call or language block if (instr.debug != null && instr.opCode != OpCode.RETURN && (instr.opCode != OpCode.RETB)) { if (runtimeCore.Breakpoints.Contains(instr)) { runtimeCore.Breakpoints.Remove(instr); } } } } }
private void ImportProcedure(string library, ProcedureNode proc) { string procName = proc.Name; if (proc.IsAutoGeneratedThisProc || // There could be DS functions that have private access // that shouldn't be imported into the Library proc.AccessModifier == AccessModifier.Private || CoreUtils.IsSetter(procName) || CoreUtils.IsDisposeMethod(procName) || CoreUtils.StartsWithDoubleUnderscores(procName)) { return; } string obsoleteMessage = ""; int classScope = proc.ClassID; string className = string.Empty; MethodAttributes methodAttribute = proc.MethodAttribute; ClassAttributes classAttribute = null; if (classScope != Constants.kGlobalScope) { var classNode = LibraryManagementCore.ClassTable.ClassNodes[classScope]; classAttribute = classNode.ClassAttributes; className = classNode.Name; } // MethodAttribute's HiddenInLibrary has higher priority than // ClassAttribute's HiddenInLibrary var isVisible = true; var canUpdatePeriodically = false; if (methodAttribute != null) { isVisible = !methodAttribute.HiddenInLibrary; canUpdatePeriodically = methodAttribute.CanUpdatePeriodically; } else { if (classAttribute != null) { isVisible = !classAttribute.HiddenInLibrary; } } FunctionType type; if (classScope == Constants.kGlobalScope) { type = FunctionType.GenericFunction; } else { if (CoreUtils.IsGetter(procName)) { type = proc.IsStatic ? FunctionType.StaticProperty : FunctionType.InstanceProperty; string property; if (CoreUtils.TryGetPropertyName(procName, out property)) { procName = property; } } else { if (proc.IsConstructor) { type = FunctionType.Constructor; } else if (proc.IsStatic) { type = FunctionType.StaticMethod; } else { type = FunctionType.InstanceMethod; } } } List <TypedParameter> arguments = proc.ArgumentInfos.Zip( proc.ArgumentTypes, (arg, argType) => { AssociativeNode defaultArgumentNode; // Default argument specified by DefaultArgumentAttribute // takes higher priority if (!TryGetDefaultArgumentFromAttribute(arg, out defaultArgumentNode) && arg.IsDefault) { var binaryExpr = arg.DefaultExpression as BinaryExpressionNode; if (binaryExpr != null) { defaultArgumentNode = binaryExpr.RightNode; } } string shortName = null; if (defaultArgumentNode != null) { shortName = defaultArgumentNode.ToString(); var rewriter = new ElementRewriter(LibraryManagementCore.ClassTable, LibraryManagementCore.BuildStatus.LogSymbolConflictWarning); defaultArgumentNode = defaultArgumentNode.Accept(rewriter); } return(new TypedParameter(arg.Name, argType, defaultArgumentNode, shortName)); }).ToList(); bool isLacingDisabled = false; IEnumerable <string> returnKeys = null; if (proc.MethodAttribute != null) { if (proc.MethodAttribute.ReturnKeys != null) { returnKeys = proc.MethodAttribute.ReturnKeys; } if (proc.MethodAttribute.IsObsolete) { obsoleteMessage = proc.MethodAttribute.ObsoleteMessage; } isLacingDisabled = proc.MethodAttribute.IsLacingDisabled; } var function = new FunctionDescriptor(new FunctionDescriptorParams { Assembly = library, ClassName = className, FunctionName = procName, Parameters = arguments, ReturnType = proc.ReturnType, FunctionType = type, IsVisibleInLibrary = isVisible, ReturnKeys = returnKeys, PathManager = pathManager, IsVarArg = proc.IsVarArg, ObsoleteMsg = obsoleteMessage, CanUpdatePeriodically = canUpdatePeriodically, IsBuiltIn = pathManager.PreloadedLibraries.Contains(library), IsPackageMember = packagedLibraries.Contains(library), IsLacingDisabled = isLacingDisabled }); AddImportedFunctions(library, new[] { function }); }
private int FindEndPCForAssocGraphNode(int tempPC, InstructionStream istream, ProcedureNode fNode, GraphNode graphNode, bool handleSSATemps) { int limit = Constants.kInvalidIndex; GraphNode currentGraphNode = graphNode; if (currentGraphNode != null) { if (tempPC < currentGraphNode.updateBlock.startpc || tempPC > currentGraphNode.updateBlock.endpc) { return(Constants.kInvalidIndex); } int i = currentGraphNode.dependencyGraphListID; GraphNode nextGraphNode = currentGraphNode; while (currentGraphNode.exprUID != Constants.kInvalidIndex && currentGraphNode.exprUID == nextGraphNode.exprUID) { limit = nextGraphNode.updateBlock.endpc; if (++i < istream.dependencyGraph.GraphList.Count) { nextGraphNode = istream.dependencyGraph.GraphList[i]; } else { break; } // Is it the next statement // This check will be deprecated on full SSA if (handleSSATemps) { if (!nextGraphNode.IsSSANode()) { // The next graphnode is nolonger part of the current statement // This is the end pc needed to run until nextGraphNode = istream.dependencyGraph.GraphList[i]; limit = nextGraphNode.updateBlock.endpc; break; } } } } // If graph node is null in associative lang block, it either is the very first property declaration or // it is the very first or only function call statement ("return = f();") inside the calling function // Here there's most likely a DEP or RETURN respectively after the function call // in which case, search for the instruction and set that as the new pc limit else if (!fNode.Name.Contains(Constants.kSetterPrefix)) { while (++tempPC < istream.instrList.Count) { Instruction instr = istream.instrList[tempPC]; if (instr.opCode == OpCode.DEP || instr.opCode == OpCode.RETURN) { limit = tempPC; break; } } } return(limit); }
public void SetUpCallrForDebug(RuntimeCore runtimeCore, DSASM.Executive exec, ProcedureNode fNode, int pc, bool isBaseCall = false, CallSite callsite = null, List <StackValue> arguments = null, List <List <ReplicationGuide> > replicationGuides = null, StackFrame stackFrame = null, List <StackValue> dotCallDimensions = null, bool hasDebugInfo = false, bool isMember = false, StackValue?thisPtr = null) { //ProtoCore.DSASM.Executive exec = core.CurrentExecutive.CurrentDSASMExec; DebugFrame debugFrame = new DebugFrame(); debugFrame.IsBaseCall = isBaseCall; debugFrame.Arguments = arguments; debugFrame.IsMemberFunction = isMember; debugFrame.ThisPtr = thisPtr; debugFrame.HasDebugInfo = hasDebugInfo; if (CoreUtils.IsDisposeMethod(fNode.Name)) { debugFrame.IsDisposeCall = true; ReturnPCFromDispose = DebugEntryPC; } if (RunMode == Runmode.StepNext) { debugFrame.FunctionStepOver = true; } bool isReplicating = false; bool isExternalFunction = false; // callsite is set to null for a base class constructor call in CALL if (callsite == null) { isReplicating = false; isExternalFunction = false; SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); return; } // Comment Jun: A dot call does not replicate and must be handled immediately if (fNode.Name == Constants.kDotMethodName) { isReplicating = false; isExternalFunction = false; debugFrame.IsDotCall = true; debugFrame.DotCallDimensions = dotCallDimensions; SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); return; } List <List <ReplicationInstruction> > replicationTrials; bool willReplicate = callsite.WillCallReplicate(new Context(), arguments, replicationGuides, stackFrame, runtimeCore, out replicationTrials); // the inline conditional built-in is handled separately as 'WillCallReplicate' is always true in this case if (fNode.Name.Equals(Constants.kInlineConditionalMethodName)) { // The inline conditional built-in is created only for associative blocks and needs to be handled separately as below InstructionStream istream = runtimeCore.DSExecutable.instrStreamList[CurrentBlockId]; Validity.Assert(istream.language == Language.Associative); { runtimeCore.DebugProps.InlineConditionOptions.isInlineConditional = true; runtimeCore.DebugProps.InlineConditionOptions.startPc = pc; runtimeCore.DebugProps.InlineConditionOptions.endPc = FindEndPCForAssocGraphNode(pc, istream, fNode, exec.Properties.executingGraphNode, runtimeCore.Options.ExecuteSSA); runtimeCore.DebugProps.InlineConditionOptions.instructionStream = runtimeCore.RunningBlock; debugFrame.IsInlineConditional = true; } // no replication case if (willReplicate && replicationTrials.Count == 1) { runtimeCore.DebugProps.InlineConditionOptions.ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); isReplicating = false; isExternalFunction = false; } else // an inline conditional call that replicates { // Clear all breakpoints for outermost replicated call if (!DebugStackFrameContains(StackFrameFlagOptions.IsReplicating)) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } isExternalFunction = false; isReplicating = true; } SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec, 0); DebugStackFrame.Push(debugFrame); return; } // Prevent breaking inside a function that is external except for dot calls // by clearing all breakpoints from outermost external function call // This check takes precedence over the replication check else if (fNode.IsExternal && fNode.Name != Constants.kDotMethodName) { // Clear all breakpoints if (!DebugStackFrameContains(StackFrameFlagOptions.IsExternalFunction) && fNode.Name != Constants.kFunctionRangeExpression) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } isExternalFunction = true; isReplicating = false; } // Find if function call will replicate or not and if so // prevent stepping in by removing all breakpoints from outermost replicated call else if (willReplicate) { // Clear all breakpoints for outermost replicated call if (!DebugStackFrameContains(StackFrameFlagOptions.IsReplicating)) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } isReplicating = true; isExternalFunction = false; } // For all other function calls else { isReplicating = false; isExternalFunction = false; } SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); }
private void ImportProcedure(string library, ProcedureNode proc) { string procName = proc.name; if (proc.isAutoGeneratedThisProc || CoreUtils.IsSetter(procName) || CoreUtils.IsDisposeMethod(procName) || CoreUtils.StartsWithDoubleUnderscores(procName)) { return; } int classScope = proc.classScope; string className = string.Empty; MethodAttributes methodAttribute = proc.MethodAttribute; ClassAttributes classAttribute = null; if (classScope != ProtoCore.DSASM.Constants.kGlobalScope) { var classNode = GraphUtilities.GetCore().ClassTable.ClassNodes[classScope]; classAttribute = classNode.ClassAttributes; className = classNode.name; } // MethodAttribute's HiddenInLibrary has higher priority than // ClassAttribute's HiddenInLibrary bool isVisible = true; if (methodAttribute != null) { isVisible = !methodAttribute.HiddenInLibrary; } else { if (classAttribute != null) { isVisible = !classAttribute.HiddenInLibrary; } } FunctionType type; if (classScope == ProtoCore.DSASM.Constants.kGlobalScope) { type = FunctionType.GenericFunction; } else { if (CoreUtils.IsGetter(procName)) { type = proc.isStatic ? FunctionType.StaticProperty : FunctionType.InstanceProperty; string property; if (CoreUtils.TryGetPropertyName(procName, out property)) { procName = property; } } else { if (proc.isConstructor) { type = FunctionType.Constructor; } else if (proc.isStatic) { type = FunctionType.StaticMethod; } else { type = FunctionType.InstanceMethod; } } } IEnumerable <TypedParameter> arguments = proc.argInfoList.Zip( proc.argTypeList, (arg, argType) => { object defaultValue = null; if (arg.IsDefault) { var binaryExpr = arg.DefaultExpression as BinaryExpressionNode; if (binaryExpr != null) { AssociativeNode vnode = binaryExpr.RightNode; if (vnode is IntNode) { defaultValue = (vnode as IntNode).Value; } else if (vnode is DoubleNode) { defaultValue = (vnode as DoubleNode).Value; } else if (vnode is BooleanNode) { defaultValue = (vnode as BooleanNode).Value; } else if (vnode is StringNode) { defaultValue = (vnode as StringNode).value; } } } return(new TypedParameter(arg.Name, argType.ToString(), defaultValue)); }); IEnumerable <string> returnKeys = null; if (proc.MethodAttribute != null && proc.MethodAttribute.ReturnKeys != null) { returnKeys = proc.MethodAttribute.ReturnKeys; } var function = new FunctionDescriptor( library, className, procName, arguments, proc.returntype.ToString(), type, isVisible, returnKeys, proc.isVarArg); AddImportedFunctions(library, new[] { function }); }
public static bool IsNonStaticPropertyLookupOnClass(ProcedureNode procCallNode, string className) { return(procCallNode.ArgumentInfos.Count == 1 && procCallNode.ArgumentInfos[0].Name == Constants.kThisPointerArgName && procCallNode.ArgumentTypes[0].Name == className); }
private void ImportProcedure(string library, ClassNode classNode, ProcedureNode proc) { if (proc.isAutoGeneratedThisProc) { return; } bool isVisibleInLibrary = !(null != proc.MethodAttribute && proc.MethodAttribute.HiddenInLibrary); //If the class is Hidden all methods are hidden. if (null != classNode.ClassAttributes && classNode.ClassAttributes.HiddenInLibrary) { isVisibleInLibrary = null != proc.MethodAttribute && !proc.MethodAttribute.HiddenInLibrary; //But if a particular method is not hidden, then this method is visible } string procName = proc.name; if (CoreUtils.IsSetter(procName) || CoreUtils.IsDisposeMethod(procName) || CoreUtils.StartsWithDoubleUnderscores(procName)) { return; } FunctionType type; if (CoreUtils.IsGetter(procName)) { type = proc.isStatic ? FunctionType.StaticProperty : FunctionType.InstanceProperty; string property; if (CoreUtils.TryGetPropertyName(procName, out property)) { procName = property; } } else { if (proc.isConstructor) { type = FunctionType.Constructor; } else if (proc.isStatic) { type = FunctionType.StaticMethod; } else { type = FunctionType.InstanceMethod; } } IEnumerable <TypedParameter> arguments = proc.argInfoList.Zip( proc.argTypeList, (arg, argType) => { object defaultValue = null; if (arg.IsDefault) { var binaryExpr = arg.DefaultExpression as BinaryExpressionNode; if (binaryExpr != null) { AssociativeNode vnode = binaryExpr.RightNode; if (vnode is IntNode) { defaultValue = (vnode as IntNode).Value; } else if (vnode is DoubleNode) { defaultValue = (vnode as DoubleNode).Value; } else if (vnode is BooleanNode) { defaultValue = (vnode as BooleanNode).Value; } else if (vnode is StringNode) { defaultValue = (vnode as StringNode).value; } } } return(new TypedParameter(arg.Name, argType.ToString(), defaultValue)); }); IEnumerable <string> returnKeys = null; if (proc.MethodAttribute != null && proc.MethodAttribute.ReturnKeys != null) { returnKeys = proc.MethodAttribute.ReturnKeys; } var function = new FunctionDescriptor( library, classNode.name, procName, arguments, proc.returntype.ToString(), type, isVisibleInLibrary, returnKeys, proc.isVarArg); AddImportedFunctions(library, new[] { function }); }
public override StackValue Execute(ProtoCore.Runtime.Context c, List <StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, RuntimeCore runtimeCore) { // ensure there is no data race, function resolution and execution happens in parallel // but for FFI we want it to be serial cause the code we are calling into may not cope // with parallelism. // // we are always looking and putting our function pointers in handler with each lang // so better lock for FFIHandler (being static) it will be good object to lock // lock (FFIHandlers) { Interpreter interpreter = new Interpreter(runtimeCore, true); // Setup the stack frame data StackValue svThisPtr = stackFrame.ThisPtr; int ci = activation.JILRecord.classIndex; int fi = activation.JILRecord.funcIndex; int returnAddr = stackFrame.ReturnPC; int blockDecl = stackFrame.FunctionBlock; int blockCaller = stackFrame.FunctionCallerBlock; int framePointer = runtimeCore.RuntimeMemory.FramePointer; int locals = activation.JILRecord.locals; FFIHandler handler = FFIHandlers[activation.ModuleType]; FFIActivationRecord r = activation; string className = ""; if (activation.JILRecord.classIndex > 0) { className = runtimeCore.DSExecutable.classTable.ClassNodes[activation.JILRecord.classIndex].Name; } List <ProtoCore.Type> argTypes = new List <Type>(r.ParameterTypes); ProcedureNode fNode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != ci) { fNode = interpreter.runtime.exe.classTable.ClassNodes[ci].ProcTable.Procedures[fi]; } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != fNode && fNode.IsAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = svThisPtr.IsPointer && Constants.kInvalidPointer == svThisPtr.Pointer; if (isStaticCall) { stackFrame.ThisPtr = formalParameters[thisPtrIndex]; } argTypes.RemoveAt(thisPtrIndex); // Comment Jun: Execute() can handle a null this pointer. // But since we dont even need to to reach there if we dont have a valid this pointer, then just return null if (formalParameters[thisPtrIndex].IsNull) { runtimeCore.RuntimeStatus.LogWarning(ProtoCore.Runtime.WarningID.DereferencingNonPointer, Resources.kDeferencingNonPointer); return(StackValue.Null); } // These are the op types allowed. Validity.Assert(formalParameters[thisPtrIndex].IsPointer || formalParameters[thisPtrIndex].IsDefaultArgument); svThisPtr = formalParameters[thisPtrIndex]; formalParameters.RemoveAt(thisPtrIndex); } FFIFunctionPointer functionPointer = handler.GetFunctionPointer(r.ModuleName, className, r.FunctionName, argTypes, r.ReturnType); mFunctionPointer = Validate(functionPointer) ? functionPointer : null; mFunctionPointer.IsDNI = activation.IsDNI; if (mFunctionPointer == null) { return(ProtoCore.DSASM.StackValue.Null); } { interpreter.runtime.executingBlock = runtimeCore.RunningBlock; activation.JILRecord.globs = runtimeCore.DSExecutable.runtimeSymbols[runtimeCore.RunningBlock].GetGlobalSize(); // Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } List <StackValue> registers = interpreter.runtime.GetRegisters(); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = 0; StackFrameType callerType = stackFrame.CallerStackFrameType; // FFI calls do not have execution states runtimeCore.RuntimeMemory.PushFrameForLocals(locals); StackFrame newStackFrame = new StackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, StackFrameType.Function, depth, framePointer, 0, registers, 0); runtimeCore.RuntimeMemory.PushStackFrame(newStackFrame); //is there a way the current stack be passed across and back into the managed runtime by FFI calling back into the language? //e.g. DCEnv* carrying all the stack information? look at how vmkit does this. // = jilMain.Run(ActivationRecord.JILRecord.pc, null, true); //double[] tempArray = GetUnderlyingArray<double>(jilMain.runtime.rmem.stack); Object ret = mFunctionPointer.Execute(c, interpreter); StackValue op; if (ret == null) { op = StackValue.Null; } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = StackValue.BuildInt((Int64)ret); } else if (ret is double) { op = StackValue.BuildDouble((double)ret); } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } // Clear the FFI stack frame // FFI stack frames have no local variables interpreter.runtime.rmem.FramePointer = (int)interpreter.runtime.rmem.GetAtRelative(StackFrame.FrameIndexFramePointer).IntegerValue; interpreter.runtime.rmem.PopFrame(StackFrame.StackFrameSize + formalParameters.Count); return(op); } } }
private void Visit(ProcedureNode node) { }
//private PropertyMirror(string name) //{ // PropertyName = name; //} internal PropertyMirror(ProcedureNode procNode, bool isSetter = false) { this.procNode = procNode; string getterPrefix = ProtoCore.DSASM.Constants.kGetterPrefix; int prefixLength = getterPrefix.Length; PropertyName = procNode.name.Substring(prefixLength); this.isSetter = isSetter; }
internal MethodMirror(ProcedureNode procNode) { MethodName = procNode.name; IsConstructor = procNode.isConstructor; IsStatic = procNode.isStatic; //IsAutoGenerated = procNode.isAutoGenerated; //IsAutoGeneratedThisProc = procNode.isAutoGeneratedThisProc; this.procNode = procNode; }
public override StackValue Execute(ProtoCore.Runtime.Context c, List <StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { // ensure there is no data race, function resolution and execution happens in parallel // but for FFI we want it to be serial cause the code we are calling into may not cope // with parallelism. // // we are always looking and putting our function pointers in handler with each lang // so better lock for FFIHandler (being static) it will be good object to lock // lock (FFIHandlers) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); StackValue svThisPtr = stackFrame.GetAt(StackFrame.AbsoluteIndex.kThisPtr); StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.JILRecord.classIndex; int fi = activation.JILRecord.funcIndex; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)svBlockDecl.opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = core.Rmem.FramePointer; int locals = activation.JILRecord.locals; FFIHandler handler = FFIHandlers[activation.ModuleType]; FFIActivationRecord r = activation; string className = ""; if (activation.JILRecord.classIndex > 0) { className = core.DSExecutable.classTable.ClassNodes[activation.JILRecord.classIndex].name; } bool gcThisPtr = false; List <ProtoCore.Type> argTypes = new List <Type>(r.ParameterTypes); ProcedureNode fNode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != ci) { fNode = interpreter.runtime.exe.classTable.ClassNodes[ci].vtable.procList[fi]; } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != fNode && fNode.isAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = svThisPtr.IsPointer && Constants.kInvalidPointer == (int)svThisPtr.opdata; if (isStaticCall) { thisPtrIndex = formalParameters.Count - 1; } argTypes.RemoveAt(thisPtrIndex); // Comment Jun: Execute() can handle a null this pointer. // But since we dont even need to to reach there if we dont have a valid this pointer, then just return null if (formalParameters[thisPtrIndex].IsNull) { core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kDereferencingNonPointer, ProtoCore.RuntimeData.WarningMessage.kDeferencingNonPointer); return(StackValue.Null); } // These are the op types allowed. Validity.Assert(formalParameters[thisPtrIndex].IsPointer || formalParameters[thisPtrIndex].IsDefaultArgument); svThisPtr = formalParameters[thisPtrIndex]; gcThisPtr = true; formalParameters.RemoveAt(thisPtrIndex); } FFIFunctionPointer functionPointer = handler.GetFunctionPointer(r.ModuleName, className, r.FunctionName, argTypes, r.ReturnType); mFunctionPointer = Validate(functionPointer) ? functionPointer : null; mFunctionPointer.IsDNI = activation.IsDNI; if (mFunctionPointer == null) { return(ProtoCore.DSASM.StackValue.Null); } List <object> ps = new List <object>(); //obsolete { interpreter.runtime.executingBlock = core.RunningBlock; activation.JILRecord.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } List <StackValue> registers = new List <DSASM.StackValue>(); interpreter.runtime.SaveRegisters(registers); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = 0; StackFrameType callerType = (StackFrameType)stackFrame.GetAt(StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; // FFI calls do not have execution states core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, ProtoCore.DSASM.StackFrameType.kTypeFunction, depth, framePointer, registers, locals, 0); //is there a way the current stack be passed across and back into the managed runtime by FFI calling back into the language? //e.g. DCEnv* carrying all the stack information? look at how vmkit does this. // = jilMain.Run(ActivationRecord.JILRecord.pc, null, true); //double[] tempArray = GetUnderlyingArray<double>(jilMain.runtime.rmem.stack); Object ret = mFunctionPointer.Execute(c, interpreter); StackValue op; if (ret == null) { op = StackValue.Null; } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = StackValue.BuildInt((Int64)ret); } else if (ret is double) { op = StackValue.BuildDouble((double)ret); } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } // gc the parameters if (gcThisPtr)// && core.Options.EnableThisPointerFunctionOverload) { // thisptr is sent as parameter, so need to gc it. // but when running in expression interpreter mode, do not GC because in DSASM.Executive.DecRefCounter() related GC functions, // the reference count will not be changed in expression interpreter mode. if (core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { interpreter.runtime.Core.Rmem.Heap.GCRelease(new StackValue[] { svThisPtr }, interpreter.runtime); } } interpreter.runtime.Core.Rmem.Heap.GCRelease(formalParameters.ToArray(), interpreter.runtime); // increment the reference counter of the return value interpreter.runtime.GCRetain(op); // Clear the FFI stack frame // FFI stack frames have no local variables interpreter.runtime.rmem.FramePointer = (int)interpreter.runtime.rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; interpreter.runtime.rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + formalParameters.Count); return(op); //DSASM.Mirror.ExecutionMirror.Unpack(op, core.heap, core); } } }
private void LoadObjects(DbObjectSearch search = null) { try { pbLoading.Visible = true; OperationStarted?.Invoke(this, "Loading objects..."); tvwObjects.BeginUpdate(); tvwObjects.Nodes.Clear(); var schemas = _objects .Where(obj => !string.IsNullOrEmpty(obj.Schema) && (search?.IsIncluded(obj) ?? true)) .GroupBy(obj => obj.Schema).OrderBy(grp => grp.Key); FolderNode folderNode = null; foreach (var schemaGrp in schemas) { var schemaNode = new SchemaNode(schemaGrp.Key, schemaGrp.Count()); tvwObjects.Nodes.Add(schemaNode); var tables = schemaGrp.OfType <Table>().OrderBy(obj => obj.Name); if (tables.Any()) { folderNode = new FolderNode("Tables", tables.Count()); schemaNode.Nodes.Add(folderNode); foreach (var table in tables) { var tableNode = new TableNode(table); if (_aliasManager.ContainsTable(table.ToString(), out string alias)) { tableNode.Alias = alias; } folderNode.Nodes.Add(tableNode); var foreignKeys = table.GetParentForeignKeys(_objects); tableNode.Columns.AddRange(table.Columns.Select(col => { var node = new ColumnNode(col, foreignKeys, table.IdentityColumn); if (IsUniqueMultiColumn(table, col)) { node.NodeFont = new Font(tvwObjects.Font, FontStyle.Bold); } return(node); })); var childFKs = table.GetChildForeignKeys(_objects); if (childFKs.Any()) { var childFolderNode = new TreeNode($"Child Tables ({childFKs.Count()})") { ImageKey = "join", SelectedImageKey = "join" }; tableNode.Nodes.Add(childFolderNode); foreach (var childFK in childFKs) { var fkNode = new TableNode(childFK); childFolderNode.Nodes.Add(fkNode); } } } folderNode.Expand(); } var views = schemaGrp.OfType <SqlSchema.Library.Models.View>().OrderBy(obj => obj.Name); if (views.Any()) { folderNode = new FolderNode("Views", views.Count()); schemaNode.Nodes.Add(folderNode); foreach (var view in views) { var viewNode = new ViewNode(view); folderNode.Nodes.Add(viewNode); } } var functions = schemaGrp.OfType <TableFunction>().OrderBy(obj => obj.Name); if (functions.Any()) { folderNode = new FolderNode("Functions", functions.Count()); schemaNode.Nodes.Add(folderNode); foreach (var func in functions) { var functionNode = new FunctionNode(func); folderNode.Nodes.Add(functionNode); } } var procs = schemaGrp.OfType <Procedure>().OrderBy(obj => obj.Name); if (procs.Any()) { folderNode = new FolderNode("Procedures", procs.Count()); schemaNode.Nodes.Add(folderNode); foreach (var proc in procs) { var procNode = new ProcedureNode(proc); folderNode.Nodes.Add(procNode); } } schemaNode.Expand(); } } finally { tvwObjects.EndUpdate(); pbLoading.Visible = false; OperationEnded?.Invoke(this, new EventArgs()); } }