public void CopyIsACopy() { var stack = new StackValue(); var zedObject = new object(); InvokeDelegate(stack, "PUSH", zedObject); var firstObject = new object(); InvokeDelegate(stack, "PUSH", firstObject); var secondObject = new object(); InvokeDelegate(stack, "PUSH", secondObject); var thirdObject = "third"; InvokeDelegate(stack, "PUSH", thirdObject); var length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(4,length); var copy = InvokeDelegate(stack, "COPY") as StackValue; Assert.AreNotSame(stack, copy); var copyLength = InvokeDelegate(copy, "LENGTH"); Assert.AreEqual(4,copyLength); object popped = InvokeDelegate(copy, "POP"); Assert.AreEqual(thirdObject, popped); InvokeDelegate(copy, "CLEAR"); copyLength = InvokeDelegate(copy, "LENGTH"); Assert.AreEqual(0,copyLength); length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(4,length); }
public static StackValue Repack(Obj obj, ProtoCore.DSASM.Heap heap) { if (obj.Type.IsIndexable) { //Unpack each of the elements DsasmArray arr = (DsasmArray)obj.Payload; StackValue[] sv = new StackValue[arr.members.Length]; //recurse over the array for (int i = 0; i < sv.Length; i++) sv[i] = Repack(arr.members[i], heap); int size = sv.Length; lock (heap.cslock) { int ptr = heap.Allocate(size); ++heap.Heaplist[ptr].Refcount; for (int n = size - 1; n >= 0; --n) { heap.Heaplist[ptr].Stack[n] = sv[n]; } StackValue overallSv = StackUtils.BuildArrayPointer(ptr); return overallSv; } } // For non-arrays, there is nothing to repack so just return the original stackvalue return obj.DsasmValue; }
public void CanClear() { var stack = new StackValue(); InvokeDelegate(stack, "PUSH", new ScalarIntValue(1)); InvokeDelegate(stack, "PUSH", new ScalarIntValue(2)); var length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(new ScalarIntValue(2),length); InvokeDelegate(stack, "CLEAR"); length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(new ScalarIntValue(0),length); }
public void CanClear() { var stack = new StackValue(); InvokeDelegate(stack, "PUSH", 1); InvokeDelegate(stack, "PUSH", new object()); var length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(2,length); InvokeDelegate(stack, "CLEAR"); length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(0,length); }
public StackValueDeref(StackValue pointer) { ValueType = StackValueType.Unknown; ProcessedValue = false; if (pointer is StackValuePointerBase) { Pointer = pointer as StackValuePointerBase; } else { UnknownPointer = pointer; } }
public void CanSerializeStacks() { var stack = new StackValue(); var nested = new StackValue(); stack.Push(new StringValue("item1")); stack.Push(new ScalarIntValue(2)); stack.Push(nested); nested.Push(new StringValue("nested1")); StackValue deserialized = Deserialize(Serialize(stack)) as StackValue; Assert.AreEqual(new StringValue("nested1"), (deserialized.Pop() as StackValue).Pop()); Assert.AreEqual(new ScalarIntValue(2), deserialized.Pop()); Assert.AreEqual(new StringValue("item1"), deserialized.Pop()); }
public void CanTestContains() { var stack = new StackValue(); var zedObject = new StringValue("abc"); InvokeDelegate(stack, "PUSH", zedObject); var firstObject = ScalarIntValue.One; InvokeDelegate(stack, "PUSH", firstObject); var secondObject = ScalarIntValue.Two; var thirdObject = new ScalarIntValue(4); var length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(ScalarIntValue.Two, length); Assert.IsTrue((BooleanValue)InvokeDelegate(stack, "CONTAINS", zedObject)); Assert.IsTrue((BooleanValue)InvokeDelegate(stack, "CONTAINS", firstObject)); Assert.IsFalse((BooleanValue)InvokeDelegate(stack, "CONTAINS", secondObject)); Assert.IsFalse((BooleanValue)InvokeDelegate(stack, "CONTAINS", thirdObject)); }
public void CanPushPopItem() { var stack = new StackValue(); Assert.IsNotNull(stack); var length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(0,length); InvokeDelegate(stack, "PUSH", "value1"); InvokeDelegate(stack, "PUSH", "value2"); length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(2,length); object popped = InvokeDelegate(stack, "POP"); Assert.AreEqual("value2", popped); popped = InvokeDelegate(stack, "POP"); Assert.AreEqual("value1", popped); length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(0, length); }
public void CanPushPopItem() { var stack = new StackValue(); Assert.IsNotNull(stack); var length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(new ScalarIntValue(0), length); InvokeDelegate(stack, "PUSH", new StringValue("value1")); InvokeDelegate(stack, "PUSH", new StringValue("value2")); length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(ScalarIntValue.Two, length); object popped = InvokeDelegate(stack, "POP"); Assert.AreEqual(new StringValue("value2"), popped); popped = InvokeDelegate(stack, "POP"); Assert.AreEqual(new StringValue("value1"), popped); length = InvokeDelegate(stack, "LENGTH"); Assert.AreEqual(ScalarIntValue.Zero, length); }
public string GetClassTrace(StackValue val, Heap heap, int langblock, bool forPrint) { if (!formatParams.ContinueOutputTrace()) return "..."; RuntimeMemory rmem = MirrorTarget.rmem; Executable exe = MirrorTarget.exe; ClassTable classTable = MirrorTarget.RuntimeCore.DSExecutable.classTable; int classtype = val.metaData.type; if (classtype < 0 || (classtype >= classTable.ClassNodes.Count)) { formatParams.RestoreOutputTraceDepth(); return string.Empty; } ClassNode classnode = classTable.ClassNodes[classtype]; if (classnode.IsImportedClass) { var helper = DLLFFIHandler.GetModuleHelper(FFILanguage.CSharp); var marshaller = helper.GetMarshaller(runtimeCore); var strRep = marshaller.GetStringValue(val); formatParams.RestoreOutputTraceDepth(); return strRep; } else { var obj = heap.ToHeapObject<DSObject>(val); List<string> visibleProperties = null; if (null != propertyFilter) { if (!propertyFilter.TryGetValue(classnode.Name, out visibleProperties)) visibleProperties = null; } StringBuilder classtrace = new StringBuilder(); if (classnode.Symbols != null && classnode.Symbols.symbolList.Count > 0) { bool firstPropertyDisplayed = false; for (int n = 0; n < obj.Count; ++n) { SymbolNode symbol = classnode.Symbols.symbolList[n]; string propName = symbol.name; if ((null != visibleProperties) && visibleProperties.Contains(propName) == false) continue; // This property is not to be displayed. if (firstPropertyDisplayed) classtrace.Append(", "); string propValue = ""; if (symbol.isStatic) { var staticSymbol = exe.runtimeSymbols[langblock].symbolList[symbol.symbolTableIndex]; StackValue staticProp = rmem.GetSymbolValue(staticSymbol); propValue = GetStringValue(staticProp, heap, langblock, forPrint); } else { propValue = GetStringValue(obj.GetValueFromIndex(symbol.index, runtimeCore), heap, langblock, forPrint); } classtrace.Append(string.Format("{0} = {1}", propName, propValue)); firstPropertyDisplayed = true; } } else { var stringValues = obj.Values.Select(x => GetStringValue(x, heap, langblock, forPrint)) .ToList(); for (int n = 0; n < stringValues.Count(); ++n) { if (0 != n) classtrace.Append(", "); classtrace.Append(stringValues[n]); } } formatParams.RestoreOutputTraceDepth(); if (classtype >= (int)ProtoCore.PrimitiveType.MaxPrimitive) if (forPrint) return (string.Format("{0}{{{1}}}", classnode.Name, classtrace.ToString())); else { string tempstr = (string.Format("{0}({1})", classnode.Name, classtrace.ToString())); return tempstr; } return classtrace.ToString(); } }
/// <summary> /// array[index1][index2][...][indexN] = value, and /// indices = {index1, index2, ..., indexN} /// </summary> /// <param name="array"></param> /// <param name="indices"></param> /// <param name="value"></param> /// <param name="t"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue SetValueForIndices(StackValue array, List <StackValue> indices, StackValue value, Type t, Core core) { StackValue[][] zippedIndices = ArrayUtils.GetZippedIndices(indices, core); if (zippedIndices == null || zippedIndices.Length == 0) { return(StackValue.Null); } if (zippedIndices.Length == 1) { StackValue coercedData = TypeSystem.Coerce(value, t, core); GCUtils.GCRetain(coercedData, core); return(ArrayUtils.SetValueForIndices(array, zippedIndices[0], coercedData, core)); } if (t.rank > 0) { t.rank = t.rank - 1; } if (value.optype == AddressType.ArrayPointer) { // Replication happens on both side. HeapElement dataHeapElement = GetHeapElement(value, core); int length = Math.Min(zippedIndices.Length, dataHeapElement.VisibleSize); StackValue[] oldValues = new StackValue[length]; for (int i = 0; i < length; ++i) { StackValue coercedData = TypeSystem.Coerce(dataHeapElement.Stack[i], t, core); GCUtils.GCRetain(coercedData, core); oldValues[i] = SetValueForIndices(array, zippedIndices[i], coercedData, core); } // The returned old values shouldn't have any key-value pairs return(HeapUtils.StoreArray(oldValues, null, core)); } else { // Replication is only on the LHS, so collect all old values // and return them in an array. StackValue coercedData = TypeSystem.Coerce(value, t, core); GCUtils.GCRetain(coercedData, core); StackValue[] oldValues = new StackValue[zippedIndices.Length]; for (int i = 0; i < zippedIndices.Length; ++i) { oldValues[i] = SetValueForIndices(array, zippedIndices[i], coercedData, core); } // The returned old values shouldn't have any key-value pairs return(HeapUtils.StoreArray(oldValues, null, core)); } }
/// <summary> /// array[index] = value. Here index can be any type. /// /// Note this function doesn't support the replication of array indexing. /// </summary> /// <param name="array"></param> /// <param name="index"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue SetValueForIndex(StackValue array, StackValue index, StackValue value, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (StackUtils.IsNumeric(index)) { index = index.AsInt(); return(SetValueForIndex(array, (int)index.opdata, value, core)); } else { HeapElement he = GetHeapElement(array, core); if (he.Dict == null) { he.Dict = new Dictionary <StackValue, StackValue>(new StackValueComparer(core)); } StackValue oldValue; if (!he.Dict.TryGetValue(index, out oldValue)) { oldValue = StackValue.Null; } GCUtils.GCRetain(index, core); GCUtils.GCRetain(value, core); he.Dict[index] = value; return(oldValue); } }
public static int GetMaxRankForArray(StackValue array, Core core) { return(GetMaxRankForArray(array, core, 0)); }
public string GetFirstNameFromValue(StackValue v) { if (v.optype != AddressType.Pointer) throw new ArgumentException("SV to highlight must be a pointer"); ProtoCore.DSASM.Executable exe = MirrorTarget.rmem.Executable; List<SymbolNode> symNodes = new List<SymbolNode>(); foreach (SymbolTable symTable in exe.runtimeSymbols) { foreach (SymbolNode symNode in symTable.symbolList.Values) { symNodes.Add(symNode); } } int index = MirrorTarget.rmem.Stack.FindIndex(0, value => value.opdata == v.opdata); List<SymbolNode> matchingNodes = symNodes.FindAll(value => value.index == index); if (matchingNodes.Count > 0) return matchingNodes[0].name; else { return null; } }
//@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, Core core, int type = (int)PrimitiveType.kTypePointer) { switch (val.optype) { case AddressType.ArrayPointer: case AddressType.String: { //It was a pointer that we pulled, so the value lives on the heap Int64 ptr = val.opdata; DsasmArray ret = new DsasmArray(); //Pull the item out of the heap HeapElement hs = heap.Heaplist[(int)ptr]; StackValue[] nodes = hs.Stack; ret.members = new Obj[hs.VisibleSize]; for (int i = 0; i < ret.members.Length; i++) { ret.members[i] = Unpack(nodes[i], heap, core, 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, Type = core.TypeSystem.BuildTypeObject((ret.members.Length > 0) ? core.TypeSystem.GetType(ret.members[0].Type.Name) : (int)ProtoCore.PrimitiveType.kTypeVoid, true) }; return retO; } case AddressType.Int: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeInt, false) }; return o; } case AddressType.Boolean: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = (data != 0), Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeBool, false) }; return o; } case AddressType.Null: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = null, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeNull, false) }; return o; } case AddressType.Char: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeChar, false) }; return o; } case AddressType.Double: { double data = val.opdata_d; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeDouble, false) }; return o; } case AddressType.Pointer: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(type, false) }; return o; } case AddressType.FunctionPointer: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeFunctionPointer, false) }; return o; } case AddressType.Invalid: { return new Obj(val) {Payload = null}; } default: { throw new NotImplementedException(string.Format("unknown datatype {0}", val.optype.ToString())); } } }
/// <summary> /// Compiles the given method definition. /// </summary> /// <param name="method">The method.</param> /// <param name="function">The function.</param> /// <exception cref="System.NotSupportedException"></exception> /// <exception cref="System.NotImplementedException"></exception> /// <exception cref="System.InvalidOperationException">Backward jump with a non-empty stack unknown target.</exception> private void CompileFunction(MethodReference methodReference, Function function) { var method = methodReference.Resolve(); var body = method.Body; var codeSize = body != null ? body.CodeSize : 0; var functionGlobal = function.GeneratedValue; var functionContext = new FunctionCompilerContext(function); functionContext.BasicBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, string.Empty); LLVM.PositionBuilderAtEnd(builder, functionContext.BasicBlock); if (body == null && (method.ImplAttributes & MethodImplAttributes.Runtime) != 0) { var declaringClass = GetClass(function.DeclaringType); // Generate IL for various methods if (declaringClass.BaseType != null && declaringClass.BaseType.Type.TypeReference.FullName == typeof(MulticastDelegate).FullName) { body = GenerateDelegateMethod(method, declaringClass); if (body == null) return; codeSize = UpdateOffsets(body); } } if (body == null) return; var numParams = method.Parameters.Count; // Create stack, locals and args var stack = new List<StackValue>(body.MaxStackSize); var locals = new List<StackValue>(body.Variables.Count); var args = new List<StackValue>(numParams); var exceptionHandlers = new List<ExceptionHandlerInfo>(); var activeTryHandlers = new List<ExceptionHandlerInfo>(); functionContext.Stack = stack; functionContext.Locals = locals; functionContext.Arguments = args; functionContext.ExceptionHandlers = exceptionHandlers; functionContext.ActiveTryHandlers = activeTryHandlers; // Process locals foreach (var local in body.Variables) { // TODO: Anything to do on pinned objects? //if (local.IsPinned) // throw new NotSupportedException(); var type = CreateType(ResolveGenericsVisitor.Process(methodReference, local.VariableType)); locals.Add(new StackValue(type.StackType, type, LLVM.BuildAlloca(builder, type.DefaultType, local.Name))); } // Process args for (int index = 0; index < function.ParameterTypes.Length; index++) { var argType = function.ParameterTypes[index]; var arg = LLVM.GetParam(functionGlobal, (uint)index); // Copy argument on stack var storage = LLVM.BuildAlloca(builder, argType.DefaultType, "arg" + index.ToString()); LLVM.BuildStore(builder, arg, storage); args.Add(new StackValue(argType.StackType, argType, storage)); } // Some wasted space due to unused offsets, but we only keep one so it should be fine. // TODO: Reuse same allocated instance per thread, and grow it only if necessary var branchTargets = new bool[codeSize]; var basicBlocks = new BasicBlockRef[codeSize]; var forwardStacks = new StackValue[codeSize][]; functionContext.BasicBlocks = basicBlocks; functionContext.ForwardStacks = forwardStacks; // Find branch targets (which will require PHI node for stack merging) for (int index = 0; index < body.Instructions.Count; index++) { var instruction = body.Instructions[index]; var flowControl = instruction.OpCode.FlowControl; // Process branch targets if (flowControl == FlowControl.Cond_Branch || flowControl == FlowControl.Branch) { var targets = instruction.Operand is Instruction[] ? (Instruction[])instruction.Operand : new[] { (Instruction)instruction.Operand }; foreach (var target in targets) { // Operand Target can be reached branchTargets[target.Offset] = true; } } // Need to enforce a block to be created for the next instruction after a conditional branch // TODO: Break? if (flowControl == FlowControl.Cond_Branch) { if (instruction.Next != null) branchTargets[instruction.Next.Offset] = true; } } // Setup exception handling if (body.HasExceptionHandlers) { // Add an "ehselector.slot" i32 local, and a "exn.slot" Object reference local functionContext.ExceptionHandlerSelectorSlot = LLVM.BuildAlloca(builder, int32Type, "ehselector.slot"); functionContext.ExceptionSlot = LLVM.BuildAlloca(builder, @object.DefaultType, "exn.slot"); functionContext.EndfinallyJumpTarget = LLVM.BuildAlloca(builder, int32Type, "endfinally.jumptarget"); // Create resume exception block functionContext.ResumeExceptionBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, "eh.resume"); LLVM.PositionBuilderAtEnd(builder2, functionContext.ResumeExceptionBlock); var exceptionObject = LLVM.BuildLoad(builder2, functionContext.ExceptionSlot, "exn"); var ehselectorValue = LLVM.BuildLoad(builder2, functionContext.ExceptionHandlerSelectorSlot, "sel"); exceptionObject = LLVM.BuildPointerCast(builder2, exceptionObject, intPtrType, "exn"); var landingPadValue = LLVM.BuildInsertValue(builder2, LLVM.GetUndef(caughtResultType), exceptionObject, 0, "lpad.val"); landingPadValue = LLVM.BuildInsertValue(builder2, landingPadValue, ehselectorValue, 1, "lpad.val"); LLVM.BuildResume(builder2, landingPadValue); // Exception handlers blocks are also branch targets foreach (var exceptionHandler in body.ExceptionHandlers) { branchTargets[exceptionHandler.HandlerStart.Offset] = true; } } // Create basic block // TODO: Could be done during previous pass for (int offset = 0; offset < branchTargets.Length; offset++) { // Create a basic block if this was a branch target or an instruction after a conditional branch if (branchTargets[offset]) { basicBlocks[offset] = LLVM.AppendBasicBlockInContext(context, functionGlobal, string.Format("L_{0:x4}", offset)); } } // Create catch clause stack if (body.HasExceptionHandlers) { // Exception handlers blocks are also branch targets foreach (var exceptionHandler in body.ExceptionHandlers) { exceptionHandlers.Add(new ExceptionHandlerInfo(exceptionHandler)); if (exceptionHandler.HandlerType != ExceptionHandlerType.Catch) continue; var handlerStart = exceptionHandler.HandlerStart.Offset; var catchBlock = basicBlocks[handlerStart]; var catchClass = GetClass(ResolveGenericsVisitor.Process(methodReference, exceptionHandler.CatchType)); // Extract exception LLVM.PositionBuilderAtEnd(builder2, catchBlock); var exceptionObject = LLVM.BuildLoad(builder2, functionContext.ExceptionSlot, string.Empty); exceptionObject = LLVM.BuildPointerCast(builder2, exceptionObject, catchClass.Type.DefaultType, string.Empty); // Erase exception from exn.slot (it has been handled) LLVM.BuildStore(builder2, LLVM.ConstNull(@object.DefaultType), functionContext.ExceptionSlot); LLVM.BuildStore(builder2, LLVM.ConstInt(int32Type, 0, false), functionContext.ExceptionHandlerSelectorSlot); forwardStacks[handlerStart] = new[] { new StackValue(catchClass.Type.StackType, catchClass.Type, exceptionObject) }; } } foreach (var instruction in body.Instructions) { try { // Check if any exception handlers might have changed if (body.HasExceptionHandlers) UpdateExceptionHandlers(functionContext, instruction); if (branchTargets[instruction.Offset]) UpdateBranching(functionContext, instruction); // Reset states functionContext.FlowingNextInstructionMode = FlowingNextInstructionMode.Implicit; EmitInstruction(functionContext, instruction); // If we do a jump, let's merge stack var flowControl = instruction.OpCode.FlowControl; if (flowControl == FlowControl.Cond_Branch || flowControl == FlowControl.Branch) MergeStacks(functionContext, instruction); } catch (Exception e) { throw new InvalidOperationException(string.Format("Error while processing instruction {0} of method {1}", instruction, methodReference), e); } } }
public static int GetMaxRankForArray(StackValue array, RuntimeCore runtimeCore) { return(GetMaxRankForArray(array, runtimeCore, 0)); }
public ArgumentAtLevel(StackValue argument, List <List <int> > indices, bool isDominant) { Indices = indices; IsDominant = isDominant; Argument = argument; }
public ArgumentAtLevel(StackValue argument) { Indices = new List <List <int> >(); IsDominant = false; Argument = argument; }
public ElementAtLevel(StackValue element, List <int> indices) { Indices = indices; Element = element; }
/// <summary> /// If an input is a dominant list, restructure the result based on the /// structure of dominant list. /// /// Note the dominant structure will be restored only if the dominant /// list is zipped with other arguments, or the replication is applied /// to the dominant list firstly. /// </summary> /// <param name="ret"></param> /// <param name="domStructure"></param> /// <param name="instructions"></param> /// <param name="runtimeCore"></param> /// <returns></returns> public static StackValue RestoreDominantStructure( StackValue ret, DominantListStructure domStructure, List <ReplicationInstruction> instructions, RuntimeCore runtimeCore) { if (domStructure == null) { return(ret); } var domListIndex = domStructure.ArgumentIndex; var indicesList = domStructure.Indices; // If there is replication on the dominant list, it should be the // topest replicaiton. if (instructions != null && instructions.Any()) { var firstInstruciton = instructions.First(); if (firstInstruciton.Zipped) { if (!firstInstruciton.ZipIndecies.Contains(domListIndex)) { return(ret); } } else { if (firstInstruciton.CartesianIndex != domListIndex) { return(ret); } } } // Allocate an empty array to hold the value StackValue newRet; try { newRet = runtimeCore.RuntimeMemory.Heap.AllocateArray(new StackValue[] { }); } catch (RunOutOfMemoryException) { runtimeCore.RuntimeStatus.LogWarning(Runtime.WarningID.RunOutOfMemory, Resources.RunOutOfMemory); return(StackValue.Null); } var array = runtimeCore.Heap.ToHeapObject <DSArray>(newRet); // Write the result back var values = ret.IsArray ? runtimeCore.Heap.ToHeapObject <DSArray>(ret).Values : Enumerable.Repeat(ret, 1); var valueIndicePairs = values.Zip(indicesList, (val, idx) => new { Value = val, Indices = idx }); foreach (var item in valueIndicePairs) { var value = item.Value; var indices = item.Indices.Select(x => StackValue.BuildInt(x)).ToArray(); array.SetValueForIndices(indices, value, runtimeCore); } return(newRet); }
public ElementAtLevel(StackValue element) { Indices = new List <int>(); Element = element; }
///// <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, Core core) { return(RecursiveProtectGetMaxReductionDepth(sv, core, 0)); }
private string GetArrayTrace(StackValue svArray, Heap heap, int langblock, HashSet<int> pointers, bool forPrint) { if (!formatParams.ContinueOutputTrace()) return "..."; StringBuilder arrayElements = new StringBuilder(); var array = heap.ToHeapObject<DSArray>(svArray); int halfArraySize = -1; if (formatParams.MaxArraySize > 0) // If the caller did specify a max value... { // And our array is larger than that max value... if (array.Count > formatParams.MaxArraySize) halfArraySize = (int)Math.Floor(formatParams.MaxArraySize * 0.5); } int totalElementCount = array.Count; if (svArray.IsArray) { totalElementCount = heap.ToHeapObject<DSArray>(svArray).Values.Count(); } for (int n = 0; n < array.Count; ++n) { // As we try to output the next element in the array, there // should be a comma if there were previously output element. if (arrayElements.Length > 0) if(forPrint) arrayElements.Append(","); else arrayElements.Append(", "); StackValue sv = array.GetValueFromIndex(n, runtimeCore); if (sv.IsArray) { arrayElements.Append(GetPointerTrace(sv, heap, langblock, pointers, forPrint)); } else { arrayElements.Append(GetStringValue(array.GetValueFromIndex(n, runtimeCore), heap, langblock, forPrint)); } // If we need to truncate this array (halfArraySize > 0), and we have // already reached the first half of it, then offset the loop counter // to the next half of the array. if (halfArraySize > 0 && (n == halfArraySize - 1)) { arrayElements.Append(", ..."); n = totalElementCount - halfArraySize - 1; } } formatParams.RestoreOutputTraceDepth(); return arrayElements.ToString(); }
//@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> /// 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 = 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); } }
private ValueRef BoxValueType(Class @class, StackValue valueType) { // Allocate object var allocatedObject = AllocateObject(@class.Type, StackValueType.Object); var dataPointer = GetDataPointer(allocatedObject); // Convert to local type var value = ConvertFromStackToLocal(@class.Type, valueType); // Copy data LLVM.BuildStore(builder, value, dataPointer); return allocatedObject; }
/// <summary> /// UnMarshales a given DS object to FFI object of given System.Type /// </summary> /// <param name="dsObject">The DS object</param> /// <param name="context">DS execution context</param> /// <param name="dsi">The current runtime interpreter</param> /// <param name="type">Type of FFI object expected</param> /// <returns>Unmarshaled FFI object</returns> public abstract object UnMarshal(StackValue dsObject, ProtoCore.Runtime.Context context, Interpreter dsi, System.Type type);
public string GetClassTrace(StackValue val, Heap heap, int langblock, bool forPrint) { if (!formatParams.ContinueOutputTrace()) return "..."; ClassTable classTable = MirrorTarget.rmem.Executable.classTable; int classtype = (int)val.metaData.type; if (classtype < 0 || (classtype >= classTable.ClassNodes.Count)) { formatParams.RestoreOutputTraceDepth(); return string.Empty; } ClassNode classnode = classTable.ClassNodes[classtype]; if (classnode.IsImportedClass) { var helper = DLLFFIHandler.GetModuleHelper(FFILanguage.CSharp); var marshaller = helper.GetMarshaller(core); var strRep = marshaller.GetStringValue(val); formatParams.RestoreOutputTraceDepth(); return strRep; } else { int ptr = (int)val.opdata; HeapElement hs = heap.Heaplist[ptr]; List<string> visibleProperties = null; if (null != propertyFilter) { if (!propertyFilter.TryGetValue(classnode.name, out visibleProperties)) visibleProperties = null; } StringBuilder classtrace = new StringBuilder(); if (classnode.symbols != null && classnode.symbols.symbolList.Count > 0) { bool firstPropertyDisplayed = false; for (int n = 0; n < hs.VisibleSize; ++n) { SymbolNode symbol = classnode.symbols.symbolList[n]; string propName = symbol.name; if ((null != visibleProperties) && visibleProperties.Contains(propName) == false) continue; // This property is not to be displayed. if (false != firstPropertyDisplayed) classtrace.Append(", "); string propValue = ""; if (symbol.isStatic) { StackValue opSymbol = new StackValue(); opSymbol.opdata = symbol.symbolTableIndex; opSymbol.optype = AddressType.StaticMemVarIndex; StackValue staticProp = this.core.Rmem.GetStackData(langblock, (int)opSymbol.opdata, Constants.kGlobalScope); propValue = GetStringValue(staticProp, heap, langblock, forPrint); } else { propValue = GetStringValue(hs.Stack[symbol.index], heap, langblock, forPrint); } classtrace.Append(string.Format("{0} = {1}", propName, propValue)); firstPropertyDisplayed = true; } } else { for (int n = 0; n < hs.VisibleSize; ++n) { if (0 != n) classtrace.Append(", "); classtrace.Append(GetStringValue(hs.Stack[n], heap, langblock, forPrint)); } } formatParams.RestoreOutputTraceDepth(); if (classtype >= (int)ProtoCore.PrimitiveType.kMaxPrimitives) if (forPrint) return (string.Format("{0}{{{1}}}", classnode.name, classtrace.ToString())); else { string tempstr = (string.Format("{0}({1})", classnode.name, classtrace.ToString())); return tempstr; } return classtrace.ToString(); } }
/// <summary> /// This is a callback method called when the given DS object is disposed. /// Marshaler gets an opportunity to clear the cache related to the given /// DS object. /// </summary> /// <param name="dsObject">DS object being disposed</param> /// <param name="context">DS execution context</param> /// <param name="dsi">The current runtime interpreter</param> public abstract void OnDispose(StackValue dsObject, ProtoCore.Runtime.Context context, Interpreter dsi); //callback method
/// <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, Core core) { //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; HeapElement he = ArrayUtils.GetHeapElement(reducedParamTypes[index], core); //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 Validity.Assert(he.Stack != null); //The elements of the array are still type structures if (he.VisibleSize == 0) { reducedSV = StackValue.Null; } else { reducedSV = he.Stack[0]; } } 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; HeapElement he = ArrayUtils.GetHeapElement(reducedParamTypes[index], core); //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 //Validity.Assert(arr != null); //Validity.Assert(arr.members[0] != null); Validity.Assert(he.Stack != null); //The elements of the array are still type structures //reducedType = arr.members[0].Type; if (he.VisibleSize == 0) { reducedSV = StackValue.Null; } else { reducedSV = he.Stack[0]; } } 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); }
public static StackValue Coerce(StackValue sv, Type targetType, Core core) { //@TODO(Jun): FIX ME - abort coersion for default args if (sv.IsDefaultArgument) { return(sv); } if (!( sv.metaData.type == targetType.UID || (core.ClassTable.ClassNodes[sv.metaData.type].ConvertibleTo(targetType.UID)) || sv.IsArray)) { core.RuntimeStatus.LogWarning(Runtime.WarningID.kConversionNotPossible, Resources.kConvertNonConvertibleTypes); return(StackValue.Null); } //if it's an array if (sv.IsArray && !targetType.IsIndexable) { //This is an array rank reduction //this may only be performed in recursion and is illegal here string errorMessage = String.Format(Resources.kConvertArrayToNonArray, core.TypeSystem.GetType(targetType.UID)); core.RuntimeStatus.LogWarning(Runtime.WarningID.kConversionNotPossible, errorMessage); return(StackValue.Null); } if (sv.IsArray && targetType.IsIndexable) { Validity.Assert(sv.IsArray); //We're being asked to convert an array into an array //walk over the structure converting each othe elements var hpe = core.Heap.GetHeapElement(sv); //Validity.Assert(targetType.rank != -1, "Arbitrary rank array conversion not yet implemented {2EAF557F-62DE-48F0-9BFA-F750BBCDF2CB}"); //Decrease level of reductions by one Type newTargetType = new Type(); newTargetType.UID = targetType.UID; if (targetType.rank != Constants.kArbitraryRank) { newTargetType.rank = targetType.rank - 1; } else { if (ArrayUtils.GetMaxRankForArray(sv, core) == 1) { //Last unpacking newTargetType.rank = 0; } else { newTargetType.rank = Constants.kArbitraryRank; } } return(ArrayUtils.CopyArray(sv, newTargetType, core)); } if (!sv.IsArray && !sv.IsNull && targetType.IsIndexable && targetType.rank != DSASM.Constants.kArbitraryRank) { //We're being asked to promote the value into an array if (targetType.rank == 1) { Type newTargetType = new Type(); newTargetType.UID = targetType.UID; newTargetType.Name = targetType.Name; newTargetType.rank = 0; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null); return(newSv); } else { Validity.Assert(targetType.rank > 1, "Target rank should be greater than one for this clause"); Type newTargetType = new Type(); newTargetType.UID = targetType.UID; newTargetType.Name = targetType.Name; newTargetType.rank = targetType.rank - 1; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null); return(newSv); } } if (sv.IsPointer) { StackValue ret = ClassCoerece(sv, targetType, core); return(ret); } //If it's anything other than array, just create a new copy switch (targetType.UID) { case (int)PrimitiveType.kInvalidType: Validity.Assert(false, "Can't convert invalid type"); break; case (int)PrimitiveType.kTypeBool: return(sv.ToBoolean(core)); case (int)PrimitiveType.kTypeChar: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeChar }; return(newSV); } case (int)PrimitiveType.kTypeDouble: return(sv.ToDouble()); case (int)PrimitiveType.kTypeFunctionPointer: if (sv.metaData.type != (int)PrimitiveType.kTypeFunctionPointer) { core.RuntimeStatus.LogWarning(Runtime.WarningID.kTypeMismatch, Resources.kFailToConverToFunction); return(StackValue.Null); } return(sv); case (int)PrimitiveType.kTypeHostEntityID: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeHostEntityID }; return(newSV); } case (int)PrimitiveType.kTypeInt: { if (sv.metaData.type == (int)PrimitiveType.kTypeDouble) { //TODO(lukechurch): Once the API is improved (MAGN-5174) //Replace this with a log entry notification //core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, Resources.kConvertDoubleToInt); } return(sv.ToInteger()); } case (int)PrimitiveType.kTypeNull: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(Runtime.WarningID.kTypeMismatch, Resources.kFailToConverToNull); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.kTypePointer: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(Runtime.WarningID.kTypeMismatch, Resources.kFailToConverToPointer); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.kTypeString: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeString }; if (sv.metaData.type == (int)PrimitiveType.kTypeChar) { char ch = EncodingUtils.ConvertInt64ToCharacter(newSV.opdata); newSV = StackValue.BuildString(ch.ToString(), core.Heap); } return(newSV); } case (int)PrimitiveType.kTypeVar: { return(sv); } case (int)PrimitiveType.kTypeArray: { return(ArrayUtils.CopyArray(sv, targetType, core)); } default: if (sv.IsNull) { return(StackValue.Null); } else { throw new NotImplementedException("Requested coercion not implemented"); } } throw new NotImplementedException("Requested coercion not implemented"); }
/// <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> private static StackValue[][] GetZippedIndices(List <StackValue> indices, Core core) { List <StackValue[]> allFlattenValues = new List <StackValue[]>(); int zipLength = System.Int32.MaxValue; foreach (var index in indices) { int length = 1; if (StackUtils.IsArray(index)) { StackValue[] flattenValues = GetFlattenValue(index, core); 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 (StackUtils.IsArray(index)) { values = allFlattenValues[i]; } if (1 == zipLength) { if (AddressType.ArrayPointer == index.optype) { 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); } }
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> /// array[index1][index2][...][indexN] = value, and /// indices = {index1, index2, ..., indexN} /// /// Note this function doesn't support the replication of array indexing. /// </summary> /// <param name="array"></param> /// <param name="indices"></param> /// <param name="value"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue SetValueForIndices(StackValue array, StackValue[] indices, StackValue value, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); for (int i = 0; i < indices.Length - 1; ++i) { StackValue index = indices[i]; HeapElement he = GetHeapElement(array, core); StackValue subArray; if (StackUtils.IsNumeric(index)) { index = index.AsInt(); int absIndex = he.ExpandByAcessingAt((int)index.opdata); subArray = he.Stack[absIndex]; } else { subArray = GetValueFromIndex(array, index, core); } // auto-promotion if (!StackUtils.IsArray(subArray)) { subArray = HeapUtils.StoreArray(new StackValue[] { subArray }, null, core); GCUtils.GCRetain(subArray, core); SetValueForIndex(array, index, subArray, core); } array = subArray; } return(SetValueForIndex(array, indices[indices.Length - 1], value, core)); }
public void TestArrayGetCommonSuperType() { String code = @" class A {} class B extends A {} class C extends B {} tAAA = {A.A(), A.A(), A.A()}; tAAB = {A.A(), A.A(), B.B()}; tAAC = {A.A(), A.A(), C.C()}; tABA = {A.A(), B.B(), A.A()}; tABB = {A.A(), B.B(), B.B()}; tABC = {A.A(), B.B(), C.C()}; tACA = {A.A(), C.C(), A.A()}; tACB = {A.A(), C.C(), B.B()}; tACC = {A.A(), C.C(), C.C()}; //--- tBAA = {B.B(), A.A(), A.A()}; tBAB = {B.B(), A.A(), B.B()}; tBAC = {B.B(), A.A(), C.C()}; tBBA = {B.B(), B.B(), A.A()}; tBBB = {B.B(), B.B(), B.B()}; tBBC = {B.B(), B.B(), C.C()}; tBCA = {B.B(), C.C(), A.A()}; tBCB = {B.B(), C.C(), B.B()}; tBCC = {B.B(), C.C(), C.C()}; //--- tCAA = {C.C(), A.A(), A.A()}; tCAB = {C.C(), A.A(), B.B()}; tCAC = {C.C(), A.A(), C.C()}; tCBA = {C.C(), B.B(), A.A()}; tCBB = {C.C(), B.B(), B.B()}; tCBC = {C.C(), B.B(), C.C()}; tCCA = {C.C(), C.C(), A.A()}; tCCB = {C.C(), C.C(), B.B()}; tCCC = {C.C(), C.C(), C.C()}; "; ProtoScript.Runners.ProtoScriptTestRunner fsr = new ProtoScript.Runners.ProtoScriptTestRunner(); ExecutionMirror mirror = fsr.Execute(code, core); StackValue svAAA = mirror.GetRawFirstValue("tAAA"); ClassNode superAAA = ArrayUtils.GetGreatestCommonSubclassForArray(svAAA, core); Assert.IsTrue(superAAA.name == "A"); StackValue svAAB = mirror.GetRawFirstValue("tAAB"); ClassNode superAAB = ArrayUtils.GetGreatestCommonSubclassForArray(svAAB, core); Assert.IsTrue(superAAB.name == "A"); StackValue svAAC = mirror.GetRawFirstValue("tAAC"); ClassNode superAAC = ArrayUtils.GetGreatestCommonSubclassForArray(svAAC, core); Assert.IsTrue(superAAC.name == "A"); StackValue svABA = mirror.GetRawFirstValue("tABA"); ClassNode superABA = ArrayUtils.GetGreatestCommonSubclassForArray(svABA, core); Assert.IsTrue(superABA.name == "A"); StackValue svABB = mirror.GetRawFirstValue("tABB"); ClassNode superABB = ArrayUtils.GetGreatestCommonSubclassForArray(svABB, core); Assert.IsTrue(superABB.name == "A"); StackValue svABC = mirror.GetRawFirstValue("tABC"); ClassNode superABC = ArrayUtils.GetGreatestCommonSubclassForArray(svABC, core); Assert.IsTrue(superABC.name == "A"); StackValue svACA = mirror.GetRawFirstValue("tACA"); ClassNode superACA = ArrayUtils.GetGreatestCommonSubclassForArray(svACA, core); Assert.IsTrue(superACA.name == "A"); StackValue svACB = mirror.GetRawFirstValue("tACB"); ClassNode superACB = ArrayUtils.GetGreatestCommonSubclassForArray(svACB, core); Assert.IsTrue(superACB.name == "A"); StackValue svACC = mirror.GetRawFirstValue("tACC"); ClassNode superACC = ArrayUtils.GetGreatestCommonSubclassForArray(svACC, core); Assert.IsTrue(superACC.name == "A"); //---- StackValue svBAA = mirror.GetRawFirstValue("tBAA"); ClassNode superBAA = ArrayUtils.GetGreatestCommonSubclassForArray(svBAA, core); Assert.IsTrue(superBAA.name == "A"); StackValue svBAB = mirror.GetRawFirstValue("tBAB"); ClassNode superBAB = ArrayUtils.GetGreatestCommonSubclassForArray(svBAB, core); Assert.IsTrue(superBAB.name == "A"); StackValue svBAC = mirror.GetRawFirstValue("tBAC"); ClassNode superBAC = ArrayUtils.GetGreatestCommonSubclassForArray(svBAC, core); Assert.IsTrue(superBAC.name == "A"); StackValue svBBA = mirror.GetRawFirstValue("tBBA"); ClassNode superBBA = ArrayUtils.GetGreatestCommonSubclassForArray(svBBA, core); Assert.IsTrue(superBBA.name == "A"); StackValue svBBB = mirror.GetRawFirstValue("tBBB"); ClassNode superBBB = ArrayUtils.GetGreatestCommonSubclassForArray(svBBB, core); Assert.IsTrue(superBBB.name == "B"); StackValue svBBC = mirror.GetRawFirstValue("tBBC"); ClassNode superBBC = ArrayUtils.GetGreatestCommonSubclassForArray(svBBC, core); Assert.IsTrue(superBBC.name == "B"); StackValue svBCA = mirror.GetRawFirstValue("tBCA"); ClassNode superBCA = ArrayUtils.GetGreatestCommonSubclassForArray(svBCA, core); Assert.IsTrue(superBCA.name == "A"); StackValue svBCB = mirror.GetRawFirstValue("tBCB"); ClassNode superBCB = ArrayUtils.GetGreatestCommonSubclassForArray(svBCB, core); Assert.IsTrue(superBCB.name == "B"); StackValue svBCC = mirror.GetRawFirstValue("tBCC"); ClassNode superBCC = ArrayUtils.GetGreatestCommonSubclassForArray(svBCC, core); Assert.IsTrue(superBCC.name == "B"); //---- StackValue svCAA = mirror.GetRawFirstValue("tCAA"); ClassNode superCAA = ArrayUtils.GetGreatestCommonSubclassForArray(svCAA, core); Assert.IsTrue(superCAA.name == "A"); StackValue svCAB = mirror.GetRawFirstValue("tCAB"); ClassNode superCAB = ArrayUtils.GetGreatestCommonSubclassForArray(svCAB, core); Assert.IsTrue(superCAB.name == "A"); StackValue svCAC = mirror.GetRawFirstValue("tCAC"); ClassNode superCAC = ArrayUtils.GetGreatestCommonSubclassForArray(svCAC, core); Assert.IsTrue(superCAC.name == "A"); StackValue svCBA = mirror.GetRawFirstValue("tCBA"); ClassNode superCBA = ArrayUtils.GetGreatestCommonSubclassForArray(svCBA, core); Assert.IsTrue(superCBA.name == "A"); StackValue svCBB = mirror.GetRawFirstValue("tCBB"); ClassNode superCBB = ArrayUtils.GetGreatestCommonSubclassForArray(svCBB, core); Assert.IsTrue(superCBB.name == "B"); StackValue svCBC = mirror.GetRawFirstValue("tCBC"); ClassNode superCBC = ArrayUtils.GetGreatestCommonSubclassForArray(svCBC, core); Assert.IsTrue(superCBC.name == "B"); StackValue svCCA = mirror.GetRawFirstValue("tCCA"); ClassNode superCCA = ArrayUtils.GetGreatestCommonSubclassForArray(svCCA, core); Assert.IsTrue(superCCA.name == "A"); StackValue svCCB = mirror.GetRawFirstValue("tCCB"); ClassNode superCCB = ArrayUtils.GetGreatestCommonSubclassForArray(svCCB, core); Assert.IsTrue(superCCB.name == "B"); StackValue svCCC = mirror.GetRawFirstValue("tCCC"); ClassNode superCCC = ArrayUtils.GetGreatestCommonSubclassForArray(svCCC, core); Assert.IsTrue(superCCC.name == "C"); }
public void Defect_TestArrayGetCommonSuperType() { String code = @" class A{}; class B extends A{}; class C extends A{}; class D extends C{}; a = A.A(); b = B.B(); c = C.C(); d = D.D(); //ba:A = B.B(); //ca:A = C.C(); //dc:C = D.D(); tABC = { a, b, c }; tABD = { a, b, d }; tACD = { a, c, d }; tBCD = { b, c, d }; tAB = { a, b }; tAD = { a, d }; tBC = { b, c }; tBD = { b, d }; tCD = { c, d }; "; ProtoScript.Runners.ProtoScriptTestRunner fsr = new ProtoScript.Runners.ProtoScriptTestRunner(); ExecutionMirror mirror = fsr.Execute(code, core); StackValue svABC = mirror.GetRawFirstValue("tABC"); ClassNode superABC = ArrayUtils.GetGreatestCommonSubclassForArray(svABC, core); Assert.IsTrue(superABC.name == "A"); StackValue svABD = mirror.GetRawFirstValue("tABD"); ClassNode superABD = ArrayUtils.GetGreatestCommonSubclassForArray(svABD, core); Assert.IsTrue(superABD.name == "A"); StackValue svACD = mirror.GetRawFirstValue("tACD"); ClassNode superACD = ArrayUtils.GetGreatestCommonSubclassForArray(svACD, core); Assert.IsTrue(superABD.name == "A"); StackValue svBCD = mirror.GetRawFirstValue("tBCD"); ClassNode superBCD = ArrayUtils.GetGreatestCommonSubclassForArray(svBCD, core); Assert.IsTrue(superBCD.name == "A"); StackValue svAB = mirror.GetRawFirstValue("tAB"); ClassNode superAB = ArrayUtils.GetGreatestCommonSubclassForArray(svAB, core); Assert.IsTrue(superAB.name == "A"); StackValue svAD = mirror.GetRawFirstValue("tAD"); ClassNode superAD = ArrayUtils.GetGreatestCommonSubclassForArray(svAD, core); Assert.IsTrue(superAD.name == "A"); StackValue svBC = mirror.GetRawFirstValue("tBC"); ClassNode superBC = ArrayUtils.GetGreatestCommonSubclassForArray(svBC, core); Assert.IsTrue(superBC.name == "A"); StackValue svBD = mirror.GetRawFirstValue("tBD"); ClassNode superBD = ArrayUtils.GetGreatestCommonSubclassForArray(svBD, core); Assert.IsTrue(superBD.name == "A"); StackValue svCD = mirror.GetRawFirstValue("tCD"); ClassNode superCD = ArrayUtils.GetGreatestCommonSubclassForArray(svCD, core); Assert.IsTrue(superCD.name == "C"); }
public StackValuePointerFake(StackValue pointer) { UnknownPointer = pointer; }
private string GetPointerTrace(StackValue ptr, Heap heap, int langblock, HashSet<int> pointers, bool forPrint) { if (pointers.Contains(ptr.ArrayPointer)) { return "{ ... }"; } else { pointers.Add(ptr.ArrayPointer); if (forPrint) { return "{" + GetArrayTrace(ptr, heap, langblock, pointers, forPrint) + "}"; } else { return "{ " + GetArrayTrace(ptr, heap, langblock, pointers, forPrint) + " }"; } } }
/// <summary> /// Experimental constructor that takes in a core object /// Takes a core object to read static data /// </summary> /// <param name="sv"></param> public MirrorData(ProtoCore.Core core, StackValue sv) { this.core = core; svData = sv; }
public string GetStringValue(StackValue val, Heap heap, int langblock, int maxArraySize, int maxOutputDepth, bool forPrint = false) { if (formatParams == null) formatParams = new OutputFormatParameters(maxArraySize, maxOutputDepth); if (val.IsInteger) { return val.IntegerValue.ToString(); } else if (val.IsDouble) { return val.DoubleValue.ToString("F6"); } else if (val.IsNull) { return "null"; } else if (val.IsPointer) { return GetClassTrace(val, heap, langblock, forPrint); } else if (val.IsArray) { HashSet<int> pointers = new HashSet<int> { val.ArrayPointer }; string arrTrace = GetArrayTrace(val, heap, langblock, pointers, forPrint); if (forPrint) return "{" + arrTrace + "}"; else return "{ " + arrTrace + " }"; } else if (val.IsFunctionPointer) { ProcedureNode procNode; if (runtimeCore.DSExecutable.FuncPointerTable.TryGetFunction(val, runtimeCore, out procNode)) { string className = String.Empty; if (procNode.ClassID != Constants.kGlobalScope) { className = runtimeCore.DSExecutable.classTable.GetTypeName(procNode.ClassID).Split('.').Last() + "."; } return "function: " + className + procNode.Name; } return "function: " + val.FunctionPointer.ToString(); } else if (val.IsBoolean) { return val.BooleanValue ? "true" : "false"; } else if (val.IsString) { if (forPrint) return heap.ToHeapObject<DSString>(val).Value; else return "\"" + heap.ToHeapObject<DSString>(val).Value + "\""; } else if (val.IsChar) { Char character = Convert.ToChar(val.CharValue); if (forPrint) return character.ToString(); else return "'" + character + "'"; } else { return "null"; // "Value not yet supported for tracing"; } }
/// <summary> /// Takes a runtime core object to read runtime data /// </summary> /// <param name="sv"></param> public MirrorData(ProtoCore.Core core, ProtoCore.RuntimeCore runtimeCore, StackValue sv) { this.core = core; this.runtimeCore = runtimeCore; svData = sv; }
// this method is used for the IDE to query object values // Copy from the the existing Unpack with some modifications // 1: It is a non-static method so there is no need to pass the core and heap // 2: It does not traverse the array, array traverse is done in method GetArrayElement // 3: The payload for boolean and null is changed to Boolean and null type in .NET, such that the watch windows can directly call ToString() // to print the value, otherwize for boolean it will print either 0 or 1, for null it will print 0 public Obj Unpack(StackValue val) { Obj obj = null; switch (val.optype) { case AddressType.Pointer: obj = new Obj(val) { Payload = val.Pointer, }; break; case AddressType.ArrayPointer: obj = new Obj(val) { Payload = val.ArrayPointer, }; break; case AddressType.Int: obj = new Obj(val) { Payload = val.IntegerValue, }; break; case AddressType.Boolean: obj = new Obj(val) { Payload = val.BooleanValue, }; break; case AddressType.Double: obj = new Obj(val) { Payload = val.DoubleValue, }; break; case AddressType.Null: obj = new Obj(val) { Payload = null, }; break; case AddressType.FunctionPointer: obj = new Obj(val) { Payload = val.FunctionPointer, }; break; case AddressType.String: obj = new Obj(val) { Payload = val.StringPointer, }; break; case AddressType.Char: obj = new Obj(val) { Payload = val.CharValue, }; break; } return obj; }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { List <Object> parameters = new List <object>(); List <StackValue> s = dsi.runtime.rmem.Stack; Object thisObject = null; FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.RuntimeCore); if (!ReflectionInfo.IsStatic) { try { thisObject = marshaller.UnMarshal(s.Last(), c, dsi, ReflectionInfo.DeclaringType); } catch (InvalidOperationException) { string message = String.Format(Resources.kFFIFailedToObtainThisObject, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, message); return(null); } if (thisObject == null) { return(null); //Can't call a method on null object. } } ParameterInfo[] paraminfos = ReflectionInfo.GetParameters(); for (int i = 0; i < mArgTypes.Length; ++i) { // Comment Jun: FFI function stack frames do not contain locals int locals = 0; int relative = 0 - ProtoCore.DSASM.StackFrame.kStackFrameSize - locals - i - 1; StackValue opArg = dsi.runtime.rmem.GetAtRelative(relative); try { Type paramType = paraminfos[i].ParameterType; object param = null; if (opArg.IsDefaultArgument) { param = Type.Missing; } else { param = marshaller.UnMarshal(opArg, c, dsi, paramType); } //null is passed for a value type, so we must return null //rather than interpreting any value from null. fix defect 1462014 if (!paramType.IsGenericType && paramType.IsValueType && param == null) { //This is going to cause a cast exception. This is a very frequently called problem, so we want to short-cut the execution dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, string.Format("Null value cannot be cast to {0}", paraminfos[i].ParameterType.Name)); return(null); //throw new System.InvalidCastException(string.Format("Null value cannot be cast to {0}", paraminfos[i].ParameterType.Name)); } parameters.Add(param); } catch (System.InvalidCastException ex) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); return(null); } catch (InvalidOperationException) { string message = String.Format(Resources.kFFIFailedToObtainObject, paraminfos[i].ParameterType.Name, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, message); return(null); } } object ret = null; StackValue dsRetValue = StackValue.Null; try { ret = InvokeFunctionPointer(thisObject, parameters.Count > 0 ? parameters.ToArray() : null); //Reduce to singleton if the attribute is specified. ret = ReflectionInfo.ReduceReturnedCollectionToSingleton(ret); dsRetValue = marshaller.Marshal(ret, c, dsi, mReturnType); } catch (DllNotFoundException ex) { if (ex.InnerException != null) { dsi.LogSemanticError(ex.InnerException.Message); } dsi.LogSemanticError(ex.Message); } catch (System.Reflection.TargetException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.Reflection.TargetInvocationException ex) { if (ex.InnerException != null) { System.Exception exc = ex.InnerException; if (exc is System.ArgumentException) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, ErrorString(exc)); } else if (exc is System.NullReferenceException) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ErrorString(null)); } else { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ErrorString(exc)); } } else { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ErrorString(ex)); } } catch (System.Reflection.TargetParameterCountException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.MethodAccessException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.InvalidOperationException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.NotSupportedException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kAccessViolation, ex.Message); } catch (System.ArgumentException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, ErrorString(ex.InnerException)); } else { dsi.LogWarning(ProtoCore.Runtime.WarningID.kInvalidArguments, ErrorString(ex)); } } catch (Exception ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.Runtime.WarningID.kDefault, ErrorString(ex.InnerException)); } dsi.LogWarning(ProtoCore.Runtime.WarningID.kDefault, ErrorString(ex)); } return(dsRetValue); }
private ValueRef ResolveVirtualMethod(FunctionCompilerContext functionContext, ref Function targetMethod, ref StackValue thisObject) { ValueRef resolvedMethod; if ((targetMethod.MethodReference.Resolve().Attributes & MethodAttributes.Virtual) == MethodAttributes.Virtual) { // Build indices for GEP var indices = new[] { LLVM.ConstInt(int32Type, 0, false), // Pointer indirection LLVM.ConstInt(int32Type, (int) ObjectFields.RuntimeTypeInfo, false), // Access RTTI }; Class @class; var constrainedClass = functionContext.ConstrainedClass; if (constrainedClass != null) { // Reset state functionContext.ConstrainedClass = null; if (!constrainedClass.Type.TypeReference.IsValueType) { // If thisType is a reference type, dereference thisObject = new StackValue(constrainedClass.Type.StackType, constrainedClass.Type, LLVM.BuildPointerCast(builder, LLVM.BuildLoad(builder, thisObject.Value, string.Empty), constrainedClass.Type.DefaultType, string.Empty)); } else { var matchingMethod = CecilExtensions.TryMatchMethod(constrainedClass, targetMethod.MethodReference, false); if (matchingMethod != null) { // If thisType is a value type and implements method, then ptr is passed unmodified targetMethod = matchingMethod; // Convert to appropriate type (if necessary) var refType = GetType(constrainedClass.Type.TypeReference.MakeByReferenceType()); if (thisObject.StackType != StackValueType.Reference || thisObject.Type != refType) { thisObject = new StackValue(refType.StackType, refType, LLVM.BuildPointerCast(builder, thisObject.Value, refType.DefaultType, string.Empty)); } } else { // If thisType is a value type and doesn't implement method, dereference, box and pass as this thisObject = new StackValue(constrainedClass.Type.StackType, constrainedClass.Type, LLVM.BuildPointerCast(builder, LLVM.BuildLoad(builder, thisObject.Value, string.Empty), constrainedClass.Type.DefaultType, string.Empty)); thisObject = new StackValue(StackValueType.Object, constrainedClass.Type, BoxValueType(constrainedClass, thisObject)); } } @class = constrainedClass; } else { @class = GetClass(thisObject.Type); } // TODO: Checking actual type stored in thisObject we might be able to statically resolve method? // If it's a byref value type, emit a normal call if (thisObject.Type.TypeReference.IsByReference && thisObject.Type.TypeReference.GetElementType().IsValueType && MemberEqualityComparer.Default.Equals(targetMethod.DeclaringType.TypeReference, thisObject.Type.TypeReference.GetElementType())) { resolvedMethod = targetMethod.GeneratedValue; } else { // Get RTTI pointer var rttiPointer = LLVM.BuildInBoundsGEP(builder, thisObject.Value, indices, string.Empty); rttiPointer = LLVM.BuildLoad(builder, rttiPointer, string.Empty); // Cast to expected RTTI type rttiPointer = LLVM.BuildPointerCast(builder, rttiPointer, LLVM.TypeOf(@class.GeneratedRuntimeTypeInfoGlobal), string.Empty); if (targetMethod.MethodReference.DeclaringType.Resolve().IsInterface) { // Interface call // Get method stored in IMT slot indices = new[] { LLVM.ConstInt(int32Type, 0, false), // Pointer indirection LLVM.ConstInt(int32Type, (int) RuntimeTypeInfoFields.InterfaceMethodTable, false), // Access IMT LLVM.ConstInt(int32Type, (ulong) targetMethod.VirtualSlot, false), // Access specific IMT slot }; var imtEntry = LLVM.BuildInBoundsGEP(builder, rttiPointer, indices, string.Empty); var methodPointer = LLVM.BuildLoad(builder, imtEntry, string.Empty); // TODO: Compare method ID and iterate in the linked list until the correct match is found // If no match is found, it's likely due to covariance/contravariance, so we will need a fallback var methodId = GetMethodId(targetMethod.MethodReference); // Resolve interface call resolvedMethod = LLVM.BuildCall(builder, resolveInterfaceCallFunction, new[] { LLVM.ConstInt(int32Type, methodId, false), methodPointer, }, string.Empty); resolvedMethod = LLVM.BuildPointerCast(builder, resolvedMethod, LLVM.PointerType(targetMethod.FunctionType, 0), string.Empty); } else { // Virtual table call // Get method stored in vtable slot indices = new[] { LLVM.ConstInt(int32Type, 0, false), // Pointer indirection LLVM.ConstInt(int32Type, (int) RuntimeTypeInfoFields.VirtualTable, false), // Access vtable LLVM.ConstInt(int32Type, (ulong) targetMethod.VirtualSlot, false), // Access specific vtable slot }; var vtable = LLVM.BuildInBoundsGEP(builder, rttiPointer, indices, string.Empty); resolvedMethod = LLVM.BuildLoad(builder, vtable, string.Empty); resolvedMethod = LLVM.BuildPointerCast(builder, resolvedMethod, LLVM.PointerType(targetMethod.FunctionType, 0), string.Empty); } } } else { // Normal call // Callvirt on non-virtual function is only done to force "this" NULL check // However, that's probably a part of the .NET spec that we want to skip for performance reasons, // so maybe we should keep this as is? resolvedMethod = targetMethod.GeneratedValue; } return resolvedMethod; }
public string PrintClass(StackValue val, Heap heap, int langblock, bool forPrint) { return PrintClass(val, heap, langblock, -1, -1, forPrint); }
/// <summary> /// Merges the stack. /// </summary> /// <param name="sourceStack">The source stack.</param> /// <param name="sourceBasicBlock">The source basic block.</param> /// <param name="targetStack">The target stack.</param> /// <param name="targetBasicBlock">The target basic block.</param> private void MergeStack(List<StackValue> sourceStack, BasicBlockRef sourceBasicBlock, ref StackValue[] targetStack, BasicBlockRef targetBasicBlock) { // First time? Need to create stack and position builder if (targetStack == null) { targetStack = new StackValue[sourceStack.Count]; if (LLVM.GetLastInstruction(targetBasicBlock).Value != IntPtr.Zero && sourceStack.Count != 0) throw new InvalidOperationException("Target basic block should have no instruction yet, or stack should be empty."); } for (int index = 0; index < sourceStack.Count; index++) { var stackValue = sourceStack[index]; var mergedStackValue = targetStack[index]; // First time? Need to create PHI node if (mergedStackValue == null) { // TODO: Check stack type during merging? LLVM.PositionBuilderAtEnd(builder2, targetBasicBlock); mergedStackValue = new StackValue(stackValue.StackType, stackValue.Type, LLVM.BuildPhi(builder2, LLVM.TypeOf(stackValue.Value), string.Empty)); targetStack[index] = mergedStackValue; } // Convert type (if necessary) // TOOD: Reuse common code with cast/conversion code var value = stackValue.Value; if (LLVM.TypeOf(value) != LLVM.TypeOf(mergedStackValue.Value) && LLVM.GetTypeKind(LLVM.TypeOf(mergedStackValue.Value)) == TypeKind.PointerTypeKind) { // Position before last instruction (which should be a branching instruction) LLVM.PositionBuilderBefore(builder2, LLVM.GetLastInstruction(sourceBasicBlock)); value = LLVM.BuildPointerCast(builder2, value, LLVM.TypeOf(mergedStackValue.Value), string.Empty); } // Add values from previous stack value LLVM.AddIncoming(mergedStackValue.Value, new[] { value }, new[] { sourceBasicBlock }); } }
// this method is used for the IDE to query object values // Copy from the the existing Unpack with some modifications // 1: It is a non-static method so there is no need to pass the core and heap // 2: It does not traverse the array, array traverse is done in method GetArrayElement // 3: The payload for boolean and null is changed to Boolean and null type in .NET, such that the watch windows can directly call ToString() // to print the value, otherwize for boolean it will print either 0 or 1, for null it will print 0 public Obj Unpack(StackValue val) { Obj obj = null; switch (val.optype) { case AddressType.Pointer: obj = new Obj(val) { Payload = val.opdata, Type = core.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypePointer, false) }; break; case AddressType.ArrayPointer: obj = new Obj(val) { Payload = val.opdata, Type = core.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeArray, true) }; break; case AddressType.Int: obj = new Obj(val) { Payload = val.opdata, Type = core.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeInt, false) }; break; case AddressType.Boolean: obj = new Obj(val) { Payload = val.opdata == 0 ? false : true, Type = core.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeBool, false) }; break; case AddressType.Double: obj = new Obj(val) { Payload = val.opdata_d, Type = core.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeDouble, false) }; break; case AddressType.Null: obj = new Obj(val) { Payload = null, Type = core.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeNull, false) }; break; case AddressType.FunctionPointer: obj = new Obj(val) { Payload = val.opdata, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeFunctionPointer, false) }; break; case AddressType.String: obj = new Obj(val) { Payload = val.opdata, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeString, true, Constants.kPrimitiveSize) }; break; case AddressType.Char: obj = new Obj(val) { Payload = val.opdata, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeChar, false) }; break; } return obj; }
public static Obj Unpack(StackValue val, Core core) { switch (val.optype) { case AddressType.ArrayPointer: { //It was a pointer that we pulled, so the value lives on the heap Int64 ptr = val.opdata; DsasmArray ret = new DsasmArray(); HeapElement hs = core.Heap.Heaplist[(int)ptr]; StackValue[] nodes = hs.Stack; ret.members = new Obj[nodes.Length]; for (int i = 0; i < ret.members.Length; i++) { ret.members[i] = Unpack(nodes[i], core); } Obj retO = new Obj(val) { Payload = ret, Type = core.TypeSystem.BuildTypeObject((ret.members.Length > 0) ? core.TypeSystem.GetType(ret.members[0].Type.Name) : (int)ProtoCore.PrimitiveType.kTypeVar, true) }; return retO; } case AddressType.Int: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeInt, false) }; return o; } case AddressType.Boolean: { Obj o = new Obj(val) { Payload = val.opdata == 0 ? false : true, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeBool, false) }; return o; } case AddressType.Null: { Obj o = new Obj(val) { Payload = null, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeNull, false) }; return o; } case AddressType.Double: { double data = val.opdata_d; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeDouble, false) }; return o; } case AddressType.Char: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeChar, false) }; return o; } case AddressType.Pointer: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject((int)val.metaData.type, false) }; return o; } case AddressType.DefaultArg: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false) }; return o; } case AddressType.FunctionPointer: { Int64 data = val.opdata; Obj o = new Obj(val) { Payload = data, Type = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeFunctionPointer, false) }; return o; } default: { throw new NotImplementedException(string.Format("unknown datatype {0}", val.optype.ToString())); } } }
public string GetStringValue(StackValue val, Heap heap, int langblock, int maxArraySize, int maxOutputDepth, bool forPrint = false) { if (formatParams == null) formatParams = new OutputFormatParameters(maxArraySize, maxOutputDepth); switch (val.optype) { case AddressType.Int: return val.opdata.ToString(); case AddressType.Double: return val.opdata_d.ToString(core.Options.FormatToPrintFloatingPoints); case AddressType.Null: return "null"; case AddressType.Pointer: return GetClassTrace(val, heap, langblock, forPrint); case AddressType.ArrayPointer: HashSet<int> pointers = new HashSet<int>{(int)val.opdata}; string arrTrace = GetArrayTrace((int)val.opdata, heap, langblock, pointers, forPrint); if (forPrint) return "{" + arrTrace + "}"; else return "{ " + arrTrace + " }"; case AddressType.FunctionPointer: return "fptr: " + val.opdata.ToString(); case AddressType.Boolean: return (val.opdata == 0) ? "false" : "true"; case AddressType.String: if (forPrint) return GetStringTrace((int)val.opdata, heap); else return "\"" + GetStringTrace((int)val.opdata, heap) + "\""; case AddressType.Char: Char character = ProtoCore.Utils.EncodingUtils.ConvertInt64ToCharacter(val.opdata); if (forPrint) return character.ToString(); else return "'" + character + "'"; default: return "null"; // "Value not yet supported for tracing"; } }
public Obj GetDebugValue(string name) { int classcope; int block = core.GetCurrentBlockId(); RuntimeMemory rmem = core.Rmem; SymbolNode symbol; int index = GetSymbolIndex(name, out classcope, ref block, out symbol); StackValue sv = new StackValue(); if (symbol.functionIndex == -1 && classcope != Constants.kInvalidIndex) sv = rmem.GetMemberData(index, classcope); else sv = rmem.GetStackData(block, index, classcope); if (sv.optype == AddressType.Invalid) throw new UninitializedVariableException { Name = name }; return Unpack(sv); }
public StackValue Evaluate(List <StackValue> args, StackFrame stackFrame) { // Build the stackframe var runtimeCore = interpreter.runtime.Core; int classScopeCaller = (int)stackFrame.GetAt(StackFrame.AbsoluteIndex.kClass).opdata; int returnAddr = (int)stackFrame.GetAt(StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = procNode.runtimeIndex; int blockCaller = (int)stackFrame.GetAt(StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = runtimeCore.Rmem.FramePointer; StackValue thisPtr = StackValue.BuildPointer(-1); // Functoion has variable input parameter. This case only happen // for FFI functions whose last parameter's type is (params T[]). // In this case, we need to convert argument list from // // {a1, a2, ..., am, v1, v2, ..., vn} // // to // // {a1, a2, ..., am, {v1, v2, ..., vn}} if (procNode.isVarArg) { int paramCount = procNode.argInfoList.Count; Validity.Assert(paramCount >= 1); int varParamCount = args.Count - (paramCount - 1); var varParams = args.GetRange(paramCount - 1, varParamCount).ToArray(); args.RemoveRange(paramCount - 1, varParamCount); var packedParams = HeapUtils.StoreArray(varParams, null, interpreter.runtime.Core); args.Add(packedParams); } bool isCallingMemberFunciton = procNode.classScope != Constants.kInvalidIndex && !procNode.isConstructor && !procNode.isStatic; bool isValidThisPointer = true; if (isCallingMemberFunciton) { Validity.Assert(args.Count >= 1); thisPtr = args[0]; if (thisPtr.IsArray) { isValidThisPointer = ArrayUtils.GetFirstNonArrayStackValue(thisPtr, ref thisPtr, runtimeCore); } else { args.RemoveAt(0); } } if (!isValidThisPointer || (!thisPtr.IsPointer && !thisPtr.IsArray)) { runtimeCore.RuntimeStatus.LogWarning(WarningID.kDereferencingNonPointer, WarningMessage.kDeferencingNonPointer); return(StackValue.Null); } var callerType = (StackFrameType)stackFrame.GetAt(StackFrame.AbsoluteIndex.kStackFrameType).opdata; interpreter.runtime.TX = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); StackValue svBlockDecl = StackValue.BuildBlockIndex(blockDecl); interpreter.runtime.SX = svBlockDecl; var repGuides = new List <List <ProtoCore.ReplicationGuide> >(); List <StackValue> registers = new List <StackValue>(); interpreter.runtime.SaveRegisters(registers); var newStackFrame = new StackFrame(thisPtr, classScopeCaller, 1, returnAddr, blockDecl, blockCaller, callerType, StackFrameType.kTypeFunction, 0, // depth framePointer, registers, null); bool isInDebugMode = runtimeCore.Options.IDEDebugMode && runtimeCore.ExecMode != InterpreterMode.kExpressionInterpreter; if (isInDebugMode) { runtimeCore.DebugProps.SetUpCallrForDebug(runtimeCore, interpreter.runtime, procNode, returnAddr - 1, false, callsite, args, repGuides, newStackFrame); } StackValue rx = callsite.JILDispatchViaNewInterpreter( new Runtime.Context(), args, repGuides, newStackFrame, runtimeCore); if (isInDebugMode) { runtimeCore.DebugProps.RestoreCallrForNoBreak(runtimeCore, procNode); } interpreter.runtime.DecRefCounter(rx); return(rx); }
public string GetStringValue(StackValue val, Heap heap, int langblock, bool forPrint = false) { return GetStringValue(val, heap, langblock, -1, -1, forPrint); }
public static List <List <StackValue> > ComputeReducedParamsSuperset(List <StackValue> formalParams, List <ReplicationInstruction> replicationInstructions, Core core) { //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; HeapElement he = ArrayUtils.GetHeapElement(basicList[index], core); Validity.Assert(he.Stack != null); //The elements of the array are still type structures if (he.VisibleSize == 0) { reducedSV = StackValue.Null; } else { var arrayStats = ArrayUtils.GetTypeExamplesForLayer(basicList[index], core).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; HeapElement he = ArrayUtils.GetHeapElement(basicList[index], core); //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 Validity.Assert(he.Stack != null); //The elements of the array are still type structures if (he.VisibleSize == 0) { reducedSV = StackValue.Null; } else { var arrayStats = ArrayUtils.GetTypeExamplesForLayer(basicList[index], core).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 WatchViewModel ProcessThing(object value, ProtoCore.RuntimeCore runtimeCore, string tag, bool showRawData, WatchHandlerCallback callback, List <string> preferredDictionaryOrdering = null) { if (value is DesignScript.Builtin.Dictionary || value is IDictionary) { IEnumerable <string> keys; IEnumerable <object> values; if (value is DesignScript.Builtin.Dictionary) { var dict = value as DesignScript.Builtin.Dictionary; keys = dict.Keys; values = dict.Values; if (preferredDictionaryOrdering != null && preferredDictionaryOrdering.Count > 1) { keys = preferredDictionaryOrdering; values = keys.Select(k => dict.ValueAtKey(k)); } } else { var dict = value as IDictionary; keys = dict.Keys.Cast <string>(); values = dict.Values.Cast <object>(); } var node = new WatchViewModel(keys.Any() ? WatchViewModel.DICTIONARY : WatchViewModel.EMPTY_DICTIONARY, tag, RequestSelectGeometry, true); foreach (var e in keys.Zip(values, (key, val) => new { key, val })) { node.Children.Add(ProcessThing(e.val, runtimeCore, tag + ":" + e.key, showRawData, callback)); } return(node); } if (!(value is string) && value is IEnumerable) { var list = (value as IEnumerable).Cast <dynamic>().ToList(); var node = new WatchViewModel(list.Count == 0 ? WatchViewModel.EMPTY_LIST : WatchViewModel.LIST, tag, RequestSelectGeometry, true); foreach (var e in list.Select((element, idx) => new { element, idx })) { node.Children.Add(callback(e.element, null, runtimeCore, tag + ":" + e.idx, showRawData)); } return(node); } if (runtimeCore != null && value is StackValue) { StackValue stackValue = (StackValue)value; string stringValue = string.Empty; if (stackValue.IsFunctionPointer) { stringValue = StringUtils.GetStringValue(stackValue, runtimeCore); } else { int typeId = runtimeCore.DSExecutable.TypeSystem.GetType(stackValue); stringValue = runtimeCore.DSExecutable.classTable.ClassNodes[typeId].Name; } return(new WatchViewModel(stringValue, tag, RequestSelectGeometry)); } if (value is Enum) { return(new WatchViewModel(((Enum)value).GetDescription(), tag, RequestSelectGeometry)); } return(new WatchViewModel(ToString(value), tag, RequestSelectGeometry)); }
/// <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, Core core) { if (!StackUtils.IsArray(array)) { throw new ArgumentException("The stack value provided was not an array"); } Dictionary <ClassNode, int> typeStats = GetTypeStatisticsForArray(array, core); //@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) { //<<<<<<< .mine List <int> chain = ClassUtils.GetClassUpcastChain(cn, core); //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)); } } //======= // List<int> chain = GetConversionChain(cn, core); //>>>>>>> .r2886 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(core.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(core.ClassTable.ClassNodes[orderedTypes.First()]); }
public string PrintClass(StackValue val, Heap heap, int langblock, int maxArraySize, int maxOutputDepth, bool forPrint) { if (null == formatParams) formatParams = new OutputFormatParameters(maxArraySize, maxOutputDepth); return GetClassTrace(val, heap, langblock, forPrint); }
/// <summary> /// Simply copy an array. /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue CopyArray(StackValue array, Core core) { Type anyType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, Constants.kArbitraryRank); return(CopyArray(array, anyType, core)); }
public override void Execute(SharedObjects shared) { Structure[] argArray = new Structure[CountRemainingArgs(shared)]; for (int i = argArray.Length - 1 ; i >= 0 ; --i) argArray[i] = PopStructureAssertEncapsulated(shared); // fill array in reverse order because .. stack args. AssertArgBottomAndConsume(shared); var stackValue = new StackValue(argArray.ToList()); ReturnValue = stackValue; }
/// <summary> /// Get all values from an array. /// </summary> /// <param name="array"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue[] GetValues(StackValue array, Core core) { List <StackValue> values = GetValues <StackValue>(array, core, (StackValue sv) => sv); return(values.ToArray()); }