public static StackValue ConvertToString(StackValue sv, RuntimeCore runtimeCore, ProtoCore.Runtime.RuntimeMemory rmem) { StackValue returnSV; //TODO: Change Execution mirror class to have static methods, so that an instance does not have to be created ProtoCore.DSASM.Mirror.ExecutionMirror mirror = new DSASM.Mirror.ExecutionMirror(new ProtoCore.DSASM.Executive(runtimeCore), runtimeCore); returnSV = ProtoCore.DSASM.StackValue.BuildString(mirror.GetStringValue(sv, runtimeCore.RuntimeMemory.Heap, 0, true), runtimeCore.RuntimeMemory.Heap); return returnSV; }
public static int CompareString(StackValue s1, StackValue s2, RuntimeCore runtimeCore) { if (!s1.IsString || !s2.IsString) return Constants.kInvalidIndex; if (s1.Equals(s2)) return 0; string str1 = runtimeCore.RuntimeMemory.Heap.ToHeapObject<DSString>(s1).Value; string str2 = runtimeCore.RuntimeMemory.Heap.ToHeapObject<DSString>(s2).Value; return string.Compare(str1, str2); }
/// <summary> /// Returns the number of upcasts that need to be performed to turn a class into another class in its upcast chain /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="core"></param> /// <returns></returns> public static int GetUpcastCountTo(ClassNode from, ClassNode to, RuntimeCore runtimeCore) { int toID = runtimeCore.DSExecutable.classTable.ClassNodes.IndexOf(to); List<int> upcastChain = GetClassUpcastChain(from, runtimeCore); if (!upcastChain.Contains(toID)) return int.MaxValue; return upcastChain.IndexOf(toID); }
private static List<ElementAtLevel> GetElementsAtLevel(StackValue argument, int level, List<int> indices, bool recordIndices, RuntimeCore runtimeCore) { var array = runtimeCore.Heap.ToHeapObject<DSArray>(argument); if (array == null) { return new List<ElementAtLevel>(); } int count = array.Values.Count(); if (level == 0) { return array.Values.Zip(Enumerable.Range(0, count), (v, i) => { if (recordIndices) { var newIndices = new List<int>(indices); newIndices.Add(i); return new ElementAtLevel(v, newIndices); } else { return new ElementAtLevel(v); } }).ToList(); } else { return array.Values.Zip(Enumerable.Range(0, count), (v, i) => { if (recordIndices) { var newIndices = new List<int>(indices); newIndices.Add(i); return GetElementsAtLevel(v, level - 1, newIndices, recordIndices, runtimeCore); } else { return GetElementsAtLevel(v, level - 1, new List<int>(), recordIndices, runtimeCore); } }).SelectMany(vs => vs).ToList(); } }
/// <summary> /// Returns the list of classes that this can be upcast to /// It includes the class itself /// </summary> /// <param name="cn"></param> /// <param name="core"></param> /// <returns></returns> public static List<int> GetClassUpcastChain(ClassNode cn, RuntimeCore runtimeCore) { List<int> ret = new List<int>(); //@TODO: Replace this with an ID ret.Add(runtimeCore.DSExecutable.classTable.ClassNodes.IndexOf(cn)); ClassNode target = cn; while (target.Base != Constants.kInvalidIndex) { ret.Add(target.Base); target = runtimeCore.DSExecutable.classTable.ClassNodes[target.Base]; } if (!ret.Contains((int)(PrimitiveType.Var))) ret.Add((int)PrimitiveType.Var); return ret; }
/// <summary> /// Returns the list of classes that this can be upcast to /// It includes the class itself /// </summary> /// <param name="cn"></param> /// <param name="core"></param> /// <returns></returns> public static List<int> GetClassUpcastChain(ClassNode cn, RuntimeCore runtimeCore) { List<int> ret = new List<int>(); //@TODO: Replace this with an ID ret.Add(runtimeCore.DSExecutable.classTable.ClassNodes.IndexOf(cn)); ClassNode target = cn; while (target.Bases.Count > 0) { Validity.Assert(target.Bases.Count == 1, "Multiple Inheritence not yet supported, {F5DDC58D-F721-4319-854A-622175AC43F8}"); ret.Add(target.Bases[0]); target = runtimeCore.DSExecutable.classTable.ClassNodes[target.Bases[0]]; } if (!ret.Contains((int)(PrimitiveType.Var))) ret.Add((int)PrimitiveType.Var); return ret; }
public Executive(RuntimeCore runtimeCore, bool isFep = false) { IsExplicitCall = false; Validity.Assert(runtimeCore != null); this.runtimeCore = runtimeCore; enableLogging = runtimeCore.Options.Verbose; exe = runtimeCore.DSExecutable; istream = null; fepRun = isFep; Properties = new InterpreterProperties(); rmem = runtimeCore.RuntimeMemory; // Execute DS View VM Log // debugFlags = (int)DebugFlags.ENABLE_LOG; bounceType = CallingConvention.BounceType.Implicit; deferedGraphNodes = new List<AssociativeGraph.GraphNode>(); }
/// <summary> /// Whether sv is double or arrays contains double value. /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <returns></returns> public static bool ContainsDoubleElement(StackValue sv, RuntimeCore runtimeCore) { Executable exe = runtimeCore.DSExecutable; if (!sv.IsArray) return exe.TypeSystem.GetType(sv) == (int)PrimitiveType.kTypeDouble; DSArray array = runtimeCore.Heap.ToHeapObject<DSArray>(sv); return array.Values.Any( v => (v.IsArray && ContainsDoubleElement(v, runtimeCore)) || (exe.TypeSystem.GetType(v) == (int)PrimitiveType.kTypeDouble)); }
public InjectionExecutive(RuntimeCore runtimeCore, bool isFep = false) : base(runtimeCore, isFep) { }
public static int GetMaxRankForArray(StackValue array, RuntimeCore runtimeCore) { return GetMaxRankForArray(array, runtimeCore, 0); }
public static bool CompareFromDifferentCore(DSArray array1, DSArray array2, RuntimeCore rtCore1, RuntimeCore rtCore2, Context context = null) { if (array1.Count != array2.Count) { return(false); } for (int i = 0; i < array1.Count; i++) { if (!StackUtils.CompareStackValues(array1.GetValueAt(i), array2.GetValueAt(i), rtCore1, rtCore2, context)) { return(false); } } foreach (var key in array1.Dict.Keys) { StackValue value1 = array1.Dict[key]; StackValue value2 = StackValue.Null; if (!array2.Dict.TryGetValue(key, out value2)) { return(false); } if (!StackUtils.CompareStackValues(value1, value2, rtCore1, rtCore2)) { return(false); } } return(true); }
/// <summary> /// This computes the max depth to which the element can be reduced /// It contains a protected envelope /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <param name="depthCount"></param> /// <returns></returns> private static int RecursiveProtectGetMaxReductionDepth(StackValue sv, RuntimeCore runtimeCore, int depthCount) { Validity.Assert(depthCount < 1000, "StackOverflow protection trap. This is almost certainly a VM cycle-in-array bug. {0B530165-2E38-431D-88D9-56B0636364CD}"); //PERF(Luke): Could be non-recursive if (!sv.IsArray) return 0; int maxReduction = 0; //De-ref the sv var array = runtimeCore.Heap.ToHeapObject<DSArray>(sv); foreach (var subSv in array.VisibleItems) { maxReduction = Math.Max(maxReduction, RecursiveProtectGetMaxReductionDepth(subSv, runtimeCore, depthCount + 1)); } return 1 + maxReduction; }
/// <summary> /// Retrieve the first non-array element in an array /// </summary> /// <param name="svArray"></param> /// <param name="sv"></param> /// <param name="core"></param> /// <returns> true if the element was found </returns> public static bool GetFirstNonArrayStackValue(StackValue svArray, ref StackValue sv, RuntimeCore runtimeCore) { RuntimeMemory rmem = runtimeCore.RuntimeMemory; if (!svArray.IsArray) { return false; } var array = rmem.Heap.ToHeapObject<DSArray>(svArray); if (!array.Values.Any()) { return false; } while (array.GetValueFromIndex(0, runtimeCore).IsArray) { array = rmem.Heap.ToHeapObject<DSArray>(array.GetValueFromIndex(0, runtimeCore)); // Handle the case where the array is valid but empty if (!array.Values.Any()) { return false; } } sv = array.GetValueFromIndex(0, runtimeCore).ShallowClone(); return true; }
/// <summary> /// For an array we supporting zipped replicaiton for array indexing as /// well. I.e., for the following expression: /// /// a[1..3][2..4] = x; /// /// It will be expanded to /// /// a[1][2] = x; /// a[2][3] = x; /// a[3][4] = x; /// /// So here we need to calculate zipped indices. The length of returned /// indices is decided by the shortest length of index that used in /// array indexing. E.g., /// /// For array indexing /// /// [{1, 2, 3}][{"x", "y"}][{6, 7, 8}], i.e., /// /// 1 -> "x" -> 6 /// 2 -> "y" -> 7 /// 3 -> -> 8 /// /// The shortest length of index is 2 ({"x", "y"}), so function will /// returns: /// /// {{1, "x", 6}, {2, "y", 7}} /// /// </summary> /// <param name="indices"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue[][] GetZippedIndices(List<StackValue> indices, RuntimeCore runtimeCore) { List<StackValue[]> allFlattenValues = new List<StackValue[]>(); int zipLength = System.Int32.MaxValue; foreach (var index in indices) { int length = 1; if (index.IsArray) { StackValue[] flattenValues = GetFlattenValue(index, runtimeCore); allFlattenValues.Add(flattenValues); length = flattenValues.Count(); } else { allFlattenValues.Add(null); } if (zipLength > length) { zipLength = length; } } if (zipLength == 0) { return null; } else { int dims = indices.Count; StackValue[][] zippedIndices = new StackValue[zipLength][]; for (int i = 0; i < zipLength; ++i) { zippedIndices[i] = new StackValue[dims]; } for (int i = 0; i < dims; ++i) { StackValue index = indices[i]; StackValue[] values = null; if (index.IsArray) { values = allFlattenValues[i]; } if (1 == zipLength) { if (index.IsArray) { zippedIndices[0][i] = values[0]; } else { zippedIndices[0][i] = index; } } else { for (int j = 0; j < zipLength; ++j) { zippedIndices[j][i] = values[j]; } } } return zippedIndices; } }
/// <summary> /// Performs addition on 2 StackValues /// This is used by the VM when adding strings /// </summary> /// <param name="sv1"></param> /// <param name="sv2"></param> /// <returns></returns> public static StackValue AddStackValueString(StackValue sv1, StackValue sv2, RuntimeCore runtimeCore) { Validity.Assert(sv1.IsString || sv2.IsString); if (sv1.IsString && sv2.IsString) { return StringUtils.ConcatString(sv2, sv1, runtimeCore); } else if (sv1.IsString || sv2.IsString) { StackValue newSV; if (sv1.IsNull || sv2.IsNull) { return StackValue.BuildNull(); } else if (sv1.IsString) { newSV = StringUtils.ConvertToString(sv2, runtimeCore, runtimeCore.RuntimeMemory); return StringUtils.ConcatString(newSV, sv1, runtimeCore); } else if (sv2.IsString) { newSV = StringUtils.ConvertToString(sv1, runtimeCore, runtimeCore.RuntimeMemory); return StringUtils.ConcatString(sv2, newSV, runtimeCore); } } return StackValue.BuildNull(); }
/*internal static void VerifyWatch_Run(int lineAtPrevBreak, string symbolName, Core core, StreamReader log, * bool watchNestedMode = false) * { * //bool check = true; * * // search for the line and LHS string in the log file * // verify that the LHS identifier name equals 'symbolName' * // pass the LHS string to GetWatchValue() and inspect it * // verify the watch values with the log output * string line = null; * while ((line = log.ReadLine()) != null) * { * // Get line no. * Match m = Regex.Match(line, @"At line, (\d+)"); * if (m.Success) * { * int lineNo = int.Parse(m.Groups[1].Value); * if (lineNo == lineAtPrevBreak) * { * // Get lhs string * // m = Regex.Match(line, @"(\d+), (\w+)"); * m = Regex.Match(line, @"(\d+), (.*)([^\s]+)"); * if (m.Success) * { * string lhsString = m.Groups[2].Value; * * // Get lhs symbol name * m = Regex.Match(lhsString, @"(\w+)"); * if (m.Success) * { * string lhsName = m.Groups[1].Value; * if (lhsName.Equals(symbolName)) * { * ExpressionInterpreterRunner watchRunner = new ExpressionInterpreterRunner(core); * ProtoCore.DSASM.Mirror.ExecutionMirror mirror = watchRunner.Execute(lhsString); * Obj obj = mirror.GetWatchValue(); * * if (!watchNestedMode) * { * // Cheat by peeking into heap etc. to dump output string * // match string with log output to verify * string result = mirror.GetStringValue(obj.DsasmValue, core.Heap, 0, true); * line = log.ReadLine(); * * m = Regex.Match(line, @"Info: (.*)"); * if (m.Success) * { * string output = m.Groups[1].Value; * if (!output.Equals(result)) * { * Assert.Fail(string.Format("\tThe value of expression \"{0}\" doesn't match in run mode and in watch.\n", lhsString)); * return; * } * } * } * else * { * // TODO: Implement this - pratapa * // if obj is a class pointer, handle separately * // if obj is an array pointer, handle separately * // if obj is a literal, verify watch value with log output directly * GetStringValue(obj, mirror); * } * break; * } * } * } * } * } * } * }*/ internal static void VerifyWatch_Run(int lineAtPrevBreak, string symbolName, Core core, RuntimeCore runtimeCore, Dictionary <int, List <string> > map, bool watchNestedMode = false, int ci = Constants.kInvalidIndex, string defectID = "") { //bool check = true; // search for the line and LHS string in the map // verify that the LHS identifier name equals 'symbolName' // pass the LHS string to GetWatchValue() and inspect it // verify the watch values with the log output if (!map.ContainsKey(lineAtPrevBreak)) { return; } List <string> expressions = map[lineAtPrevBreak]; foreach (string exp in expressions) { // Get line no. // Get lhs symbol name string lhsName = null; int index = exp.IndexOf('.'); if (index != -1) { string[] parts = exp.Split('.'); lhsName = parts[parts.Length - 1]; } else { Match m = Regex.Match(exp, @"(\w+)"); if (m.Success) { lhsName = m.Groups[1].Value; } } if (lhsName.Equals(symbolName)) { ExpressionInterpreterRunner watchRunner = new ExpressionInterpreterRunner(core, runtimeCore); ProtoCore.DSASM.Mirror.ExecutionMirror mirror = watchRunner.Execute(exp); Obj obj = mirror.GetWatchValue(); if (!watchNestedMode) { // Cheat by peeking into heap etc. to dump output string // match string with map output to verify string result = mirror.GetStringValue(obj.DsasmValue, runtimeCore.RuntimeMemory.Heap, 0, true); Expression expr = new Expression(lineAtPrevBreak, exp, ci); if (!InjectionExecutive.ExpressionMap.ContainsKey(expr)) { return; } List <string> values = InjectionExecutive.ExpressionMap[expr]; if (!values.Contains(result)) { Assert.Fail(string.Format("\tThe value of expression \"{0}\" doesn't match in run mode and in watch.\nTracked by Defect: {1}", exp, defectID)); return; } } else { // TODO: Implement this! - pratapa // if obj is a class pointer, handle separately // if obj is an array pointer, handle separately // if obj is a literal, verify watch value with log output directly GetStringValue(obj, mirror); } //break; } } }
/// <summary> /// Try to get value for key from nested dictionaries. This function is /// used in the case that indexing into dictionaries that returned from /// a replicated function whose return type is dictionary. /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public bool TryGetValueFromNestedDictionaries(StackValue key, out StackValue value, RuntimeCore runtimeCore) { if (Dict != null && Dict.TryGetValue(key, out value)) { return(true); } var values = new List <StackValue>(); bool hasValue = false; foreach (var element in Values) { if (!(element.IsArray)) { continue; } StackValue valueInElement; DSArray subArray = heap.ToHeapObject <DSArray>(element); if (subArray.TryGetValueFromNestedDictionaries(key, out valueInElement, runtimeCore)) { hasValue = true; values.Add(valueInElement); } } if (hasValue) { try { value = heap.AllocateArray(values.ToArray()); return(true); } catch (RunOutOfMemoryException) { value = StackValue.Null; runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(false); } } else { value = StackValue.Null; return(false); } }
//@TODO(Luke): Add in the methods here that correspond to each of the internal datastructures in use by the executive //@TODO(Jun): if this method stays static, then the Heap needs to be referenced from a parameter /// <summary> /// Do the recursive unpacking of the data structure into mirror objects /// </summary> /// <param name="val"></param> /// <returns></returns> public static Obj Unpack(StackValue val, Heap heap, RuntimeCore runtimeCore, int type = (int)PrimitiveType.Pointer) { Executable exe = runtimeCore.DSExecutable; switch (val.optype) { case AddressType.ArrayPointer: { DsasmArray ret = new DsasmArray(); //Pull the item out of the heap var array = heap.ToHeapObject <DSArray>(val); StackValue[] nodes = array.Values.ToArray(); ret.members = new Obj[array.Count]; for (int i = 0; i < ret.members.Length; i++) { ret.members[i] = Unpack(nodes[i], heap, runtimeCore, type); } // TODO Jun: ret.members[0] is hardcoded and means we are assuming a homogenous collection // How to handle mixed-type arrays? Obj retO = new Obj(val) { Payload = ret, }; return(retO); } case AddressType.String: { string str = heap.ToHeapObject <DSString>(val).Value; Obj o = new Obj(val) { Payload = str, }; return(o); } case AddressType.Int: { Obj o = new Obj(val) { Payload = val.IntegerValue, }; return(o); } case AddressType.Boolean: { Obj o = new Obj(val) { Payload = val.BooleanValue, }; return(o); } case AddressType.Null: { Obj o = new Obj(val) { Payload = null, }; return(o); } case AddressType.Char: { Obj o = new Obj(val) { Payload = val.CharValue, }; return(o); } case AddressType.Double: { Obj o = new Obj(val) { Payload = val.DoubleValue, }; return(o); } case AddressType.Pointer: { Obj o = new Obj(val) { Payload = val.Pointer, }; return(o); } case AddressType.FunctionPointer: { Obj o = new Obj(val) { Payload = val.FunctionPointer, }; return(o); } case AddressType.Invalid: { return(new Obj(val) { Payload = null }); } default: { throw new NotImplementedException(string.Format("unknown datatype {0}", val.optype.ToString())); } } }
/// <summary> /// <param name="core"></param> /// <returns></returns> /// </summary> public StackValue CopyArray(RuntimeCore runtimeCore) { Type anyType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var, Constants.kArbitraryRank); return(CopyArray(anyType, runtimeCore)); }
public override StackValue Execute(Runtime.Context c, List <StackValue> formalParameters, StackFrame stackFrame, RuntimeCore runtimeCore) { StackValue svThisPtr = stackFrame.ThisPtr; if (mInterpreter == null) { Init(runtimeCore); } if (mFunctionPointer == null) { return(StackValue.Null); } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != mFNode && mFNode.IsAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = svThisPtr.IsPointer && Constants.kInvalidPointer == svThisPtr.Pointer; if (isStaticCall) { stackFrame.ThisPtr = formalParameters[thisPtrIndex]; } // Comment Jun: Execute() can handle a null this pointer. // But since we don't even need to to reach there if we don't have a valid this pointer, then just return null if (formalParameters[thisPtrIndex].IsNull) { runtimeCore.RuntimeStatus.LogWarning( Runtime.WarningID.DereferencingNonPointer, Resources.kDeferencingNonPointer); return(StackValue.Null); } // These are the op types allowed. Validity.Assert(formalParameters[thisPtrIndex].IsPointer || formalParameters[thisPtrIndex].IsDefaultArgument); // Make sure we to pass a pointer to unmarshal. if (formalParameters[thisPtrIndex].IsPointer) { svThisPtr = formalParameters[thisPtrIndex]; } formalParameters.RemoveAt(thisPtrIndex); } formalParameters.Add(svThisPtr); Object ret = mFunctionPointer.Execute(c, mInterpreter, formalParameters); 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)); } return(op); }
public Interpreter(RuntimeCore runtimeCore, bool isFEP = false) { runtime = runtimeCore.ExecutiveProvider.CreateExecutive(runtimeCore, isFEP); }
/// <summary> /// If the passed in value is not an array or an empty array or an array which contains only empty arrays, return false. /// Otherwise, return true; /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <returns></returns> public static bool ContainsNonArrayElement(StackValue sv, RuntimeCore runtimeCore) { if (!sv.IsArray) return true; var array = runtimeCore.Heap.ToHeapObject<DSArray>(sv); return array.Values.Any(v => ContainsNonArrayElement(v, runtimeCore)); }
internal static void DebugRunnerStepIn(string includePath, string code, /*string logFile*/ Dictionary <int, List <string> > map, bool watchNestedMode = false, string defectID = "") { //Internal setup ProtoCore.Core core; DebugRunner fsr; // Specify some of the requirements of IDE. var options = new ProtoCore.Options(); options.ExecutionMode = ProtoCore.ExecutionMode.Serial; options.SuppressBuildOutput = false; options.GCTempVarsOnDebug = false; // Cyclic dependency threshold is lowered from the default (2000) // as this causes the test framework to be painfully slow options.kDynamicCycleThreshold = 5; // Pass the absolute path so that imported filepaths can be resolved // in "FileUtils.GetDSFullPathName()" if (!String.IsNullOrEmpty(includePath)) { includePath = Path.GetDirectoryName(includePath); options.IncludeDirectories.Add(includePath); } core = new ProtoCore.Core(options); core.Compilers.Add(ProtoCore.Language.kAssociative, new ProtoAssociative.Compiler(core)); core.Compilers.Add(ProtoCore.Language.kImperative, new ProtoImperative.Compiler(core)); fsr = new DebugRunner(core); DLLFFIHandler.Register(FFILanguage.CSharp, new CSModuleHelper()); //Run fsr.PreStart(code); RuntimeCore runtimeCore = fsr.runtimeCore; //StreamReader log = new StreamReader(logFile); //bool isPrevBreakAtPop = false; int lineAtPrevBreak = -1; string symbolName = null; DebugRunner.VMState vms = null; while (!fsr.isEnded) { vms = fsr.LastState; OpCode opCode = OpCode.NONE; DebugInfo debug = null; if (vms != null) { // check if previous break is a POP // if so, get the line no. and LHS opCode = fsr.CurrentInstruction.opCode; debug = fsr.CurrentInstruction.debug; if (opCode == ProtoCore.DSASM.OpCode.POP) { //isPrevBreakAtPop = true; lineAtPrevBreak = vms.ExecutionCursor.StartInclusive.LineNo; } } DebugRunner.VMState currentVms = fsr.Step(); //if (isPrevBreakAtPop) if (debug != null) { // Do not do the verification for imported DS files, for which the FilePath is non null if (debug.Location.StartInclusive.SourceLocation.FilePath == null) { if (opCode == ProtoCore.DSASM.OpCode.POP) { VerifyWatch_Run(lineAtPrevBreak, runtimeCore.DebugProps.CurrentSymbolName, core, runtimeCore, map, watchNestedMode, defectID: defectID); } // if previous breakpoint was at a CALLR else if (opCode == ProtoCore.DSASM.OpCode.CALLR) { if (runtimeCore.DebugProps.IsPopmCall) { int ci = (int)currentVms.mirror.MirrorTarget.rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexClass).opdata; VerifyWatch_Run(InjectionExecutive.callrLineNo, runtimeCore.DebugProps.CurrentSymbolName, core, runtimeCore, map, watchNestedMode, ci, defectID); } } } } //isPrevBreakAtPop = false; } runtimeCore.Cleanup(); }
public static bool IsUniform(StackValue sv, RuntimeCore runtimeCore) { if (!sv.IsArray) return false; if (Utils.ArrayUtils.GetTypeStatisticsForArray(sv, runtimeCore).Count != 1) return false; return true; }
public static List<List<StackValue>> ComputeReducedParamsSuperset(List<StackValue> formalParams, List<ReplicationInstruction> replicationInstructions, RuntimeCore runtimeCore) { //Compute the reduced Type args List<List<StackValue>> reducedParams = new List<List<StackValue>>(); List<StackValue> basicList = new List<StackValue>(); //Copy the types so unaffected ones get copied back directly foreach (StackValue sv in formalParams) basicList.Add(sv); reducedParams.Add(basicList); foreach (ReplicationInstruction ri in replicationInstructions) if (ri.Zipped) { foreach (int index in ri.ZipIndecies) { //This should generally be a collection, so we need to do a one phase unboxing StackValue target = basicList[index]; StackValue reducedSV = StackValue.Null; if (target.IsArray) { //Array arr = formalParams[index].Payload as Array; var array = runtimeCore.Heap.ToHeapObject<DSArray>(basicList[index]); //The elements of the array are still type structures if (array.VisibleSize == 0) reducedSV = StackValue.Null; else { var arrayStats = ArrayUtils.GetTypeExamplesForLayer(basicList[index], runtimeCore).Values; List<List<StackValue>> clonedList = new List<List<StackValue>>(); foreach (List<StackValue> list in reducedParams) clonedList.Add(list); reducedParams.Clear(); foreach (StackValue sv in arrayStats) { foreach (List<StackValue> lst in clonedList) { List<StackValue> newArgs = new List<StackValue>(); newArgs.AddRange(lst); newArgs[index] = sv; reducedParams.Add(newArgs); } } } } else { System.Console.WriteLine("WARNING: Replication unbox requested on Singleton. Trap: 437AD20D-9422-40A3-BFFD-DA4BAD7F3E5F"); reducedSV = target; } //reducedType.IsIndexable = false; //reducedParamTypes[index] = reducedSV; } } else { //This should generally be a collection, so we need to do a one phase unboxing int index = ri.CartesianIndex; //This should generally be a collection, so we need to do a one phase unboxing StackValue target = basicList[index]; StackValue reducedSV = StackValue.Null; if (target.IsArray) { //Array arr = formalParams[index].Payload as Array; var array = runtimeCore.Heap.ToHeapObject<DSArray>(basicList[index]); //It is a collection, so cast it to an array and pull the type of the first element //@TODO(luke): Deal with sparse arrays, if the first element is null this will explode //The elements of the array are still type structures if (array.VisibleSize == 0) reducedSV = StackValue.Null; else { var arrayStats = ArrayUtils.GetTypeExamplesForLayer(basicList[index], runtimeCore).Values; List<List<StackValue>> clonedList = new List<List<StackValue>>(); foreach (List<StackValue> list in reducedParams) clonedList.Add(list); reducedParams.Clear(); foreach (StackValue sv in arrayStats) { foreach (List<StackValue> lst in clonedList) { List<StackValue> newArgs = new List<StackValue>(); newArgs.AddRange(lst); newArgs[index] = sv; reducedParams.Add(newArgs); } } } } else { System.Console.WriteLine("WARNING: Replication unbox requested on Singleton. Trap: 437AD20D-9422-40A3-BFFD-DA4BAD7F3E5F"); reducedSV = target; } } return reducedParams; }
private static StackValue[] GetFlattenValue(StackValue array, RuntimeCore runtimeCore) { Queue<StackValue> workingSet = new Queue<StackValue>(); List<StackValue> flattenValues = new List<StackValue>(); if (!array.IsArray) { return null; } workingSet.Enqueue(array); while (workingSet.Count > 0) { array = workingSet.Dequeue(); foreach (var value in runtimeCore.Heap.ToHeapObject<DSArray>(array).Values) { if (value.IsArray) { workingSet.Enqueue(value); } else { flattenValues.Add(value); } } } return flattenValues.ToArray(); }
public static List<List<ReplicationInstruction>> BuildReplicationCombinations(List<ReplicationInstruction> providedControl, List<StackValue> formalParams, RuntimeCore runtimeCore) { //@TODO: Performance hint - this should really be done with a yield-generator unless the parrallelism is useful //@ROSO: This is not generating a minimal set //First build a list of reducible parameters List<int> reducibles = new List<int>(); int maxDepth = 0; for (int i = 0; i < formalParams.Count; i++) { int itemMaxDepth = GetMaxReductionDepth(formalParams[i], runtimeCore); if (itemMaxDepth > 0) reducibles.Add(i); maxDepth = maxDepth + itemMaxDepth; } if (providedControl.Count > maxDepth) { throw new ReplicationCaseNotCurrentlySupported( string.Format(Resources.MaxDimensionExceeded, "{1EC8AF3C-48D6-4582-999E-ADBCBF9155D1}")); } else { //Reduce the available reducions by the amount that we've been instructed to maxDepth -= providedControl.Count; } List<List<int>> cleanedReductions = new List<List<int>>(); if (maxDepth > 0) { List<List<int>> reductions = new List<List<int>>(); for (int i = 0; i <= maxDepth; i++) reductions.AddRange(BuildAllocation(formalParams.Count, maxDepth)); if (providedControl.Count > 0) { //The add in the reductions associated with the provided controls. //The silly copy-ctoring here is to avoid the issues of modifying a collection with an iterator on it List<List<int>> completedReductions = new List<List<int>>(); List<ReplicationInstruction> reversedControl = new List<ReplicationInstruction>(); reversedControl.AddRange(providedControl); reversedControl.Reverse(); foreach (List<int> reduction in reductions) { List<int> reducitonList = new List<int>(); reducitonList.AddRange(reduction); foreach (ReplicationInstruction ri in reversedControl) { if (!ri.Zipped) reducitonList[ri.CartesianIndex] = reducitonList[ri.CartesianIndex] + 1; else { foreach (int i in ri.ZipIndecies) reducitonList[i] = reducitonList[i] + 1; } } completedReductions.Add(reducitonList); } reductions = completedReductions; } foreach (List<int> list in reductions) { bool append = true; for (int i = 0; i < list.Count; i++) if (list[i] > GetMaxReductionDepth(formalParams[i], runtimeCore)) { append = false; break; } int acc = 0; for (int i = 0; i < list.Count; i++) acc += list[i]; //We must be reducing something if (acc == 0) append = false; if (append) cleanedReductions.Add(list); } } //if (providedControl.Count > 0) // throw new NotImplementedException("begone."); List<List<ReplicationInstruction>> ret = new List<List<ReplicationInstruction>>(); //At this stage cleanedReductions holds the number of times to try and reduce each argument //All options being suggested should be possible foreach (List<int> reduction in cleanedReductions) { ////@PERF - unify data formats so we don't have to do this conversion again //List<List<int>> partial = new List<List<int>>(); //foreach (int i in reduction) //{ // if (i == 0) // partial.Add(new List<int> { }); // else // partial.Add(new List<int> { i }); //} //ret.Add(ReductionToInstructions(reduction));//Replicator.Old_ConvertGuidesToInstructions(partial)); ret.Add(ReductionToInstructions(reduction, providedControl));//Replicator.Old_ConvertGuidesToInstructions(partial)); } return ret; }
//@TODO(Luke): Add in the methods here that correspond to each of the internal datastructures in use by the executive //@TODO(Jun): if this method stays static, then the Heap needs to be referenced from a parameter /// <summary> /// Do the recursive unpacking of the data structure into mirror objects /// </summary> /// <param name="val"></param> /// <returns></returns> public static Obj Unpack(StackValue val, Heap heap, RuntimeCore runtimeCore, int type = (int)PrimitiveType.Pointer) { Executable exe = runtimeCore.DSExecutable; switch (val.optype) { case AddressType.ArrayPointer: { DsasmArray ret = new DsasmArray(); //Pull the item out of the heap var array = heap.ToHeapObject<DSArray>(val); StackValue[] nodes = array.Values.ToArray(); ret.members = new Obj[array.Count]; for (int i = 0; i < ret.members.Length; i++) { ret.members[i] = Unpack(nodes[i], heap, runtimeCore, type); } // TODO Jun: ret.members[0] is hardcoded and means we are assuming a homogenous collection // How to handle mixed-type arrays? Obj retO = new Obj(val) { Payload = ret, }; return retO; } case AddressType.String: { string str = heap.ToHeapObject<DSString>(val).Value; Obj o = new Obj(val) { Payload = str, }; return o; } case AddressType.Int: { Obj o = new Obj(val) { Payload = val.IntegerValue, }; return o; } case AddressType.Boolean: { Obj o = new Obj(val) { Payload = val.BooleanValue, }; return o; } case AddressType.Null: { Obj o = new Obj(val) { Payload = null, }; return o; } case AddressType.Char: { Obj o = new Obj(val) { Payload = val.CharValue, }; return o; } case AddressType.Double: { Obj o = new Obj(val) { Payload = val.DoubleValue, }; return o; } case AddressType.Pointer: { Obj o = new Obj(val) { Payload = val.Pointer, }; return o; } case AddressType.FunctionPointer: { Obj o = new Obj(val) { Payload = val.FunctionPointer, }; return o; } case AddressType.Invalid: { return new Obj(val) {Payload = null}; } default: { throw new NotImplementedException(string.Format("unknown datatype {0}", val.optype.ToString())); } } }
/// <summary> /// array[index1][index2][...][indexN] = value, and /// indices = {index1, index2, ..., indexN} /// </summary> /// <param name="indices"></param> /// <param name="value"></param> /// <param name="t"></param> /// <param name="core"></param> /// <returns></returns> public StackValue SetValueForIndices(List <StackValue> indices, StackValue value, RuntimeCore runtimeCore) { StackValue[][] zippedIndices = ArrayUtils.GetZippedIndices(indices, runtimeCore); if (zippedIndices == null || zippedIndices.Length == 0) { return(StackValue.Null); } var t = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var); if (zippedIndices.Length == 1) { StackValue coercedData = TypeSystem.Coerce(value, t, runtimeCore); return(SetValueForIndices(zippedIndices[0], coercedData, runtimeCore)); } if (value.IsArray) { // Replication happens on both side. DSArray dataElements = heap.ToHeapObject <DSArray>(value); int length = Math.Min(zippedIndices.Length, dataElements.Count); StackValue[] oldValues = new StackValue[length]; for (int i = 0; i < length; ++i) { StackValue coercedData = TypeSystem.Coerce(dataElements.GetValueAt(i), t, runtimeCore); oldValues[i] = SetValueForIndices(zippedIndices[i], coercedData, runtimeCore); } // The returned old values shouldn't have any key-value pairs try { return(heap.AllocateArray(oldValues)); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } } else { // Replication is only on the LHS, so collect all old values // and return them in an array. StackValue coercedData = TypeSystem.Coerce(value, t, runtimeCore); StackValue[] oldValues = new StackValue[zippedIndices.Length]; for (int i = 0; i < zippedIndices.Length; ++i) { oldValues[i] = SetValueForIndices(zippedIndices[i], coercedData, runtimeCore); } // The returned old values shouldn't have any key-value pairs try { return(heap.AllocateArray(oldValues)); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } } }
public static string GetStringValue(StackValue sv, RuntimeCore runtimeCore) { ProtoCore.DSASM.Mirror.ExecutionMirror mirror = new DSASM.Mirror.ExecutionMirror(new ProtoCore.DSASM.Executive(runtimeCore), runtimeCore); return mirror.GetStringValue(sv, runtimeCore.RuntimeMemory.Heap, 0, true); }
/// <summary> /// For a class node using single inheritence, get the chain of inheritences /// </summary> /// <param name="cn"></param> /// <param name="core"></param> /// <returns></returns> public static List<int> GetConversionChain(ClassNode cn, RuntimeCore runtimeCore) { List<int> ret = new List<int>(); /* //@TODO: Replace this with an ID ret.Add(core.classTable.list.IndexOf(cn)); ClassNode target = cn; while (target.baseList.Count > 0) { Validity.Assert(target.baseList.Count == 1, "Multiple Inheritence not yet supported, {F5DDC58D-F721-4319-854A-622175AC43F8}"); ret.Add(cn.baseList[0]); target = core.classTable.list[cn.baseList[0]]; } */ List<int> coercableTypes = new List<int>(); foreach (int typeID in cn.CoerceTypes.Keys) { bool inserted = false; for (int i = 0; i < coercableTypes.Count; i++) { if (cn.CoerceTypes[typeID] < cn.CoerceTypes[coercableTypes[i]]) { inserted = true; coercableTypes.Insert(typeID, i); break; } } if (!inserted) coercableTypes.Add(typeID); } coercableTypes.Add(runtimeCore.DSExecutable.classTable.ClassNodes.IndexOf(cn)); ret.AddRange(coercableTypes); return ret; }
public static StackValue ConcatString(StackValue op1, StackValue op2, RuntimeCore runtimeCore) { var v1 = runtimeCore.RuntimeMemory.Heap.ToHeapObject<DSString>(op1).Value; var v2 = runtimeCore.RuntimeMemory.Heap.ToHeapObject<DSString>(op2).Value; return StackValue.BuildString(v1 + v2, runtimeCore.RuntimeMemory.Heap); }
public static Dictionary<int, StackValue> GetTypeExamplesForLayer(StackValue array, RuntimeCore runtimeCore) { if (!array.IsArray) { Dictionary<int, StackValue> ret = new Dictionary<int, StackValue>(); ret.Add(array.metaData.type, array); return ret; } Dictionary<int, StackValue> usageFreq = new Dictionary<int, StackValue>(); //This is the element on the heap that manages the data structure var dsArray = runtimeCore.Heap.ToHeapObject<DSArray>(array); foreach (var sv in dsArray.Values) { if (!usageFreq.ContainsKey(sv.metaData.type)) usageFreq.Add(sv.metaData.type, sv); } return usageFreq; }
/// <summary> /// This function takes a replication instruction set and uses it to compute all of the types that would be called /// </summary> /// <param name="formalParams"></param> /// <param name="replicationInstructions"></param> /// <param name="core"></param> /// <returns></returns> public static List<List<StackValue>> ComputeAllReducedParams(List<StackValue> formalParams, List<ReplicationInstruction> replicationInstructions, RuntimeCore runtimeCore) { List<List<StackValue>> ret; //= new List<List<StackValue>>(); //First approximation generates possibilities that may never actually exist, due to ret = ComputeReducedParamsSuperset(formalParams, replicationInstructions, runtimeCore); return ret; }
/// <summary> /// If an empty array is passed, the result will be null /// if there are instances, but they share no common supertype the result will be var /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static ClassNode GetGreatestCommonSubclassForArray(StackValue array, RuntimeCore runtimeCore) { if (!array.IsArray) throw new ArgumentException("The stack value provided was not an array"); Dictionary<ClassNode, int> typeStats = GetTypeStatisticsForArray(array, runtimeCore); //@PERF: This could be improved with a List<List<int>> chains = new List<List<int>>(); HashSet<int> commonTypeIDs = new HashSet<int>(); foreach (ClassNode cn in typeStats.Keys) { List<int> chain = ClassUtils.GetClassUpcastChain(cn, runtimeCore); //Now add in the other conversions - as we don't have a common superclass yet //@TODO(Jun): Remove this hack when we have a proper casting structure foreach (int id in cn.CoerceTypes.Keys) if (!chain.Contains(id)) chain.Add((id)); chains.Add(chain); foreach (int nodeId in chain) commonTypeIDs.Add(nodeId); } //Remove nulls if they exist { if (commonTypeIDs.Contains( (int)PrimitiveType.kTypeNull)) commonTypeIDs.Remove((int)PrimitiveType.kTypeNull); List<List<int>> nonNullChains = new List<List<int>>(); foreach (List<int> chain in chains) { if (chain.Contains((int)PrimitiveType.kTypeNull)) chain.Remove((int)PrimitiveType.kTypeNull); if (chain.Count > 0) nonNullChains.Add(chain); } chains = nonNullChains; } //Contract the hashset so that it contains only the nodes present in all chains //@PERF: this is very inefficent { foreach (List<int> chain in chains) { commonTypeIDs.IntersectWith(chain); } } //No common subtypes if (commonTypeIDs.Count == 0) return null; if (commonTypeIDs.Count == 1) return runtimeCore.DSExecutable.classTable.ClassNodes[commonTypeIDs.First()]; List<int> lookupChain = chains[0]; //Insertion sort the IDs, we may only have a partial ordering on them. List<int> orderedTypes = new List<int>(); foreach (int typeToInsert in commonTypeIDs) { bool inserted = false; for (int i = 0; i < orderedTypes.Count; i++) { int orderedType = orderedTypes[i]; if (lookupChain.IndexOf(typeToInsert) < lookupChain.IndexOf(orderedType)) { inserted = true; orderedTypes.Insert(i, typeToInsert); break; } } if (!inserted) orderedTypes.Add(typeToInsert); } return runtimeCore.DSExecutable.classTable.ClassNodes[orderedTypes.First()]; }
/// <summary> /// Compute the effects of the replication guides on the formal parameter lists /// The results of this loose data, and will not be correct on jagged arrays of hetrogenius types /// </summary> /// <param name="formalParams"></param> /// <param name="replicationInstructions"></param> /// <returns></returns> public static List<StackValue> EstimateReducedParams(List<StackValue> formalParams, List<ReplicationInstruction> replicationInstructions, RuntimeCore runtimeCore) { //Compute the reduced Type args List<StackValue> reducedParamTypes = new List<StackValue>(); //Copy the types so unaffected ones get copied back directly foreach (StackValue sv in formalParams) reducedParamTypes.Add(sv); foreach (ReplicationInstruction ri in replicationInstructions) if (ri.Zipped) { foreach (int index in ri.ZipIndecies) { //This should generally be a collection, so we need to do a one phase unboxing StackValue target = reducedParamTypes[index]; StackValue reducedSV = StackValue.Null; if (target.IsArray) { //Array arr = formalParams[index].Payload as Array; var array = runtimeCore.Heap.ToHeapObject<DSArray>(reducedParamTypes[index]); //It is a collection, so cast it to an array and pull the type of the first element //The elements of the array are still type structures if (array.VisibleSize == 0) reducedSV = StackValue.Null; else reducedSV = array.GetValueFromIndex(0, runtimeCore); } else { System.Console.WriteLine("WARNING: Replication unbox requested on Singleton. Trap: 437AD20D-9422-40A3-BFFD-DA4BAD7F3E5F"); reducedSV = target; } //reducedType.IsIndexable = false; reducedParamTypes[index] = reducedSV; } } else { //This should generally be a collection, so we need to do a one phase unboxing int index = ri.CartesianIndex; StackValue target = reducedParamTypes[index]; StackValue reducedSV; if (target.IsArray) { //ProtoCore.DSASM.Mirror.DsasmArray arr = formalParams[index].Payload as ProtoCore.DSASM.Mirror.DsasmArray; var array = runtimeCore.Heap.ToHeapObject<DSArray>(reducedParamTypes[index]); //The elements of the array are still type structures //reducedType = arr.members[0].Type; if (array.VisibleSize == 0) reducedSV = StackValue.Null; else reducedSV = array.GetValueFromIndex(0, runtimeCore); } else { System.Console.WriteLine("WARNING: Replication unbox requested on Singleton. Trap: 437AD20D-9422-40A3-BFFD-DA4BAD7F3E5F"); reducedSV = target; } //reducedType.IsIndexable = false; reducedParamTypes[index] = reducedSV; } return reducedParamTypes; }
/// <summary> /// Generate type statistics for the whole array /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static Dictionary<ClassNode, int> GetTypeStatisticsForArray(StackValue array, RuntimeCore runtimeCore) { if (!array.IsArray) { Dictionary<ClassNode, int> ret = new Dictionary<ClassNode, int>(); ret.Add(runtimeCore.DSExecutable.classTable.ClassNodes[array.metaData.type], 1); return ret; } Dictionary<ClassNode, int> usageFreq = new Dictionary<ClassNode, int>(); //This is the element on the heap that manages the data structure var dsArray = runtimeCore.Heap.ToHeapObject<DSArray>(array); foreach (var sv in dsArray.Values) { if (sv.IsArray) { //Recurse Dictionary<ClassNode, int> subLayer = GetTypeStatisticsForArray(sv, runtimeCore); foreach (ClassNode cn in subLayer.Keys) { if (!usageFreq.ContainsKey(cn)) usageFreq.Add(cn, 0); usageFreq[cn] = usageFreq[cn] + subLayer[cn]; } } else { ClassNode cn = runtimeCore.DSExecutable.classTable.ClassNodes[sv.metaData.type]; if (!usageFreq.ContainsKey(cn)) usageFreq.Add(cn, 0); usageFreq[cn] = usageFreq[cn] + 1; } } return usageFreq; }
///// <summary> ///// Get the maximum depth to which an object can be reduced ///// </summary> ///// <param name="obj"></param> ///// <returns></returns> //[Obsolete] //public static int GetMaxReductionDepth(ProtoCore.Lang.Obj obj) //{ // if (!obj.Type.IsIndexable) // return 0; // else // { // return 1 + GetMaxReductionDepth((Obj)((DSASM.Mirror.DsasmArray)obj.Payload).members[0]); // } //} /// <summary> /// Get the maximum depth to which an element can be reduced /// This will include cases where only partial reduction can be performed on jagged arrays /// </summary> /// <param name="sv"></param> /// <param name="core"></param> /// <returns></returns> public static int GetMaxReductionDepth(StackValue sv, RuntimeCore runtimeCore) { return RecursiveProtectGetMaxReductionDepth(sv, runtimeCore, 0); }
private static int GetMaxRankForArray(StackValue array, RuntimeCore runtimeCore, int tracer) { if (tracer > RECURSION_LIMIT) throw new CompilerInternalException("Internal Recursion limit exceeded in Rank Check - Possible heap corruption {3317D4F6-4758-4C19-9680-75B68DA0436D}"); if (!array.IsArray) return 0; //throw new ArgumentException("The stack value provided was not an array"); int ret = 1; int largestSub = 0; //This is the element on the heap that manages the data structure foreach (var sv in runtimeCore.Heap.ToHeapObject<DSArray>(array).Values) { if (sv.IsArray) { int subArrayRank = GetMaxRankForArray(sv, runtimeCore, tracer + 1); largestSub = Math.Max(subArrayRank, largestSub); } } return largestSub + ret; }
public ProtoCore.DSASM.Executive CreateExecutive(RuntimeCore runtimeCore, bool isFep) { return(new InjectionExecutive(runtimeCore, isFep)); }