public static StackValue SetDataAtIndices(StackValue array, int[] indices, StackValue data, Core core) { Validity.Assert(array.optype == AddressType.ArrayPointer || array.optype == AddressType.String); StackValue arrayItem = array; for (int i = 0; i < indices.Length - 1; ++i) { HeapElement arrayHeap = core.Heap.Heaplist[(int)arrayItem.opdata]; int index = arrayHeap.ExpandByAcessingAt(indices[i]); arrayItem = arrayHeap.Stack[index]; if (arrayItem.optype == AddressType.String) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kOverIndexing, ProtoCore.RuntimeData.WarningMessage.kStringOverIndexed); return(StackUtils.BuildNull()); } else if (arrayItem.optype != AddressType.ArrayPointer) { StackValue sv = HeapUtils.StoreArray(new StackValue[] { arrayItem }, core); GCUtils.GCRetain(sv, core); arrayHeap.Stack[index] = sv; arrayItem = arrayHeap.Stack[index]; } } return(ArrayUtils.SetDataAtIndex(arrayItem, indices[indices.Length - 1], data, core)); }
private void PushFrame(int size) { for (int n = 0; n < size; ++n) { Stack.Add(StackUtils.BuildNull()); } }
/// <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 = StackUtils.BuildNull(); } GCUtils.GCRetain(index, core); GCUtils.GCRetain(value, core); he.Dict[index] = value; return(oldValue); } }
public void PushGlobFrame(int globsize) { for (int n = 0; n < globsize; ++n) { Stack.Add(StackUtils.BuildNull()); } }
/// <summary> /// = array[index1][index2][...][indexN], 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="core"></param> /// <returns></returns> public static StackValue GetValueFromIndices(StackValue array, StackValue[] indices, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); for (int i = 0; i < indices.Length - 1; ++i) { if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { core.RuntimeStatus.LogWarning(WarningID.kOverIndexing, WarningMessage.kArrayOverIndexed); return(StackUtils.BuildNull()); } StackValue index = indices[i]; if (StackUtils.IsNumeric(index)) { index = index.AsInt(); array = GetValueFromIndex(array, (int)index.opdata, core); } else { if (array.optype != AddressType.ArrayPointer) { core.RuntimeStatus.LogWarning(WarningID.kOverIndexing, WarningMessage.kArrayOverIndexed); return(StackUtils.BuildNull()); } array = GetValueFromIndex(array, index, core); } } return(GetValueFromIndex(array, indices[indices.Length - 1], core)); }
public static StackValue GetNextKey(StackValue key, Core core) { if (StackUtils.IsNull(key) || key.optype != AddressType.ArrayKey || key.opdata < 0 || key.metaData.type < 0) { return(StackUtils.BuildNull()); } int ptr = key.metaData.type; int index = (int)key.opdata; HeapElement he = core.Heap.Heaplist[ptr]; if ((he.VisibleSize > index + 1) || (he.Dict != null && he.Dict.Count + he.VisibleSize > index + 1)) { StackValue newKey = key; newKey.opdata = newKey.opdata + 1; return(newKey); } return(StackUtils.BuildNull()); }
/// <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(StackUtils.BuildNull()); } if (zippedIndices.Length == 1) { StackValue coercedData = TypeSystem.Coerce(value, t, core); GCUtils.GCRetain(coercedData, core); return(ArrayUtils.SetValueForIndices(array, zippedIndices[0], coercedData, core)); } else if (value.optype == AddressType.ArrayPointer) { // Replication happens on both side. if (t.rank > 0) { t.rank = t.rank - 1; if (t.rank == 0) { t.IsIndexable = false; } } 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]. /// /// Note this function doesn't support the replication of array indexing. /// </summary> /// <param name="array"></param> /// <param name="index"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue GetValueFromIndex(StackValue array, StackValue index, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { return(StackUtils.BuildNull()); } if (StackUtils.IsNumeric(index)) { index = index.AsInt(); return(GetValueFromIndex(array, (int)index.opdata, core)); } else if (index.optype == AddressType.ArrayKey) { int fullIndex = (int)index.opdata; HeapElement he = GetHeapElement(array, core); if (he.VisibleSize > fullIndex) { return(GetValueFromIndex(array, fullIndex, core)); } else { fullIndex = fullIndex - he.VisibleSize; if (he.Dict != null && he.Dict.Count > fullIndex) { int count = 0; foreach (var key in he.Dict.Keys) { if (count == fullIndex) { return(he.Dict[key]); } count = count + 1; } } } return(StackUtils.BuildNull()); } else { HeapElement he = GetHeapElement(array, core); StackValue value = StackUtils.BuildNull(); if (he.Dict != null && he.Dict.TryGetValue(index, out value)) { return(value); } else { return(StackUtils.BuildNull()); } } }
/// <summary> /// = array[index] /// </summary> /// <param name="array"></param> /// <param name="index"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue GetValueFromIndex(StackValue array, int index, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { return(StackUtils.BuildNull()); } HeapElement he = GetHeapElement(array, core); return(StackUtils.GetValue(he, index, core)); }
public StackValue BuildNullArray(int size) { lock (Heap.cslock) { int ptr = Heap.Allocate(size); for (int n = 0; n < size; ++n) { Heap.Heaplist[ptr].Stack[n] = StackUtils.BuildNull(); } return(StackUtils.BuildArrayPointer(ptr)); } }
public static StackValue SetDataAtIndices(StackValue array, List <StackValue> indices, StackValue data, Type t, Core core) { int[][] zippedIndices = ArrayUtils.GetZippedIndices(indices, core); if (zippedIndices == null || zippedIndices.Length == 0) { return(StackUtils.BuildNull()); } if (zippedIndices.Length == 1) { StackValue coercedData = TypeSystem.Coerce(data, t, core); GCUtils.GCRetain(coercedData, core); return(ArrayUtils.SetDataAtIndices(array, zippedIndices[0], coercedData, core)); } else if (data.optype == AddressType.ArrayPointer) { if (t.rank > 0) { t.rank = t.rank - 1; if (t.rank == 0) { t.IsIndexable = false; } } HeapElement dataHeapElement = core.Heap.Heaplist[(int)data.opdata]; 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] = ArrayUtils.SetDataAtIndices(array, zippedIndices[i], coercedData, core); } return(HeapUtils.StoreArray(oldValues, core)); } else { StackValue coercedData = TypeSystem.Coerce(data, t, core); GCUtils.GCRetain(coercedData, core); StackValue[] oldValues = new StackValue[zippedIndices.Length]; for (int i = 0; i < zippedIndices.Length; ++i) { oldValues[i] = ArrayUtils.SetDataAtIndices(array, zippedIndices[i], coercedData, core); } return(HeapUtils.StoreArray(oldValues, core)); } }
public static StackValue SetDataAtIndex(StackValue svArray, int index, StackValue svData, Core core) { Validity.Assert(svArray.optype == AddressType.ArrayPointer || svArray.optype == AddressType.String); if (svArray.optype == AddressType.String && svData.optype != AddressType.Char) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, RuntimeData.WarningMessage.kAssignNonCharacterToString); return(StackUtils.BuildNull()); } lock (core.Heap.cslock) { HeapElement arrayHeap = core.Heap.Heaplist[(int)svArray.opdata]; index = arrayHeap.ExpandByAcessingAt(index); StackValue oldValue = arrayHeap.SetValue(index, svData); return(oldValue); } }
/// <summary> /// array[index] = value. The array will be expanded if necessary. /// </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, int index, StackValue value, Core core) { Validity.Assert(StackUtils.IsArray(array) || StackUtils.IsString(array)); if (StackUtils.IsString(array) && value.optype != AddressType.Char) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, RuntimeData.WarningMessage.kAssignNonCharacterToString); return(StackUtils.BuildNull()); } lock (core.Heap.cslock) { HeapElement arrayHeap = GetHeapElement(array, core); index = arrayHeap.ExpandByAcessingAt(index); StackValue oldValue = arrayHeap.SetValue(index, value); return(oldValue); } }
public StackValue GetMemberData(int symbolindex, int scope) { int thisptr = (int)GetAtRelative(GetStackIndex(ProtoCore.DSASM.StackFrame.kFrameIndexThisPtr)).opdata; // Get the heapstck offset int offset = ClassTable.ClassNodes[scope].symbols.symbolList[symbolindex].index; if (null == Heap.Heaplist[thisptr].Stack || Heap.Heaplist[thisptr].Stack.Length == 0) { return(StackUtils.BuildNull()); } StackValue sv = Heap.Heaplist[thisptr].Stack[offset]; Validity.Assert(AddressType.Pointer == sv.optype || AddressType.ArrayPointer == sv.optype || AddressType.Invalid == sv.optype); // Not initialized yet if (sv.optype == AddressType.Invalid) { sv.optype = AddressType.Null; sv.opdata_d = sv.opdata = 0; return(sv); } else if (sv.optype == AddressType.ArrayPointer) { return(sv); } int nextPtr = (int)sv.opdata; Validity.Assert(nextPtr >= 0); if (null != Heap.Heaplist[nextPtr].Stack && Heap.Heaplist[nextPtr].Stack.Length > 0) { bool isActualData = AddressType.Pointer != Heap.Heaplist[nextPtr].Stack[0].optype && AddressType.ArrayPointer != Heap.Heaplist[nextPtr].Stack[0].optype && AddressType.Invalid != Heap.Heaplist[nextPtr].Stack[0].optype; // Invalid is an uninitialized member if (isActualData) { return(Heap.Heaplist[nextPtr].Stack[0]); } } return(sv); }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <param name="context"></param> /// <param name="dsi"></param> /// <param name="type"></param> /// <returns></returns> public override StackValue Marshal(object obj, ProtoCore.Runtime.Context context, Interpreter dsi, ProtoCore.Type type) { if (obj == null) { return(StackUtils.BuildNull()); } FFIObjectMarshler marshaler = null; StackValue retVal; Type objType = obj.GetType(); if (type.IsIndexable) { if (obj is System.Collections.ICollection) { System.Collections.ICollection collection = obj as System.Collections.ICollection; object[] array = new object[collection.Count]; collection.CopyTo(array, 0); return(PrimitiveMarshler.ConvertCSArrayToDSArray(this, array, context, dsi, type)); } else if (obj is System.Collections.IEnumerable) { System.Collections.IEnumerable enumerable = obj as System.Collections.IEnumerable; return(PrimitiveMarshler.ConvertCSArrayToDSArray(this, enumerable, context, dsi, type)); } } Array arr = obj as Array; if (null != arr) { return(PrimitiveMarshler.ConvertCSArrayToDSArray(this, arr, context, dsi, type)); } else if ((PrimitiveMarshler.IsPrimitiveDSType(type) || PrimitiveMarshler.IsPrimitiveObjectType(obj, type)) && mPrimitiveMarshalers.TryGetValue(objType, out marshaler)) { return(marshaler.Marshal(obj, context, dsi, type)); } else if (CLRObjectMap.TryGetValue(obj, out retVal)) { return(retVal); } return(CreateDSObject(obj, context, dsi)); }
public static bool RemoveKey(StackValue array, StackValue key, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(false); } HeapElement he = GetHeapElement(array, core); if (StackUtils.IsNumeric(key)) { long index = key.AsInt().opdata; if (index < 0) { index = index + he.VisibleSize; } if (index >= 0 && index < he.VisibleSize) { StackValue oldValue = he.Stack[index]; he.Stack[index] = StackUtils.BuildNull(); if (index == he.VisibleSize - 1) { he.VisibleSize -= 1; } return(true); } } else { if (he.Dict != null && he.Dict.ContainsKey(key)) { StackValue value = he.Dict[key]; GCUtils.GCRelease(key, core); GCUtils.GCRelease(value, core); he.Dict.Remove(key); return(true); } } return(false); }
private object ConvertReturnValue(object retVal, ProtoCore.Runtime.Context context, ProtoCore.DSASM.Interpreter dsi) { object returnValue = retVal; // these are arrays! if (mReturnType.IsIndexable) { // we have already asserted that these can be of rank 1 only, for now // IntPtr arrPtr = (IntPtr)retVal; if (arrPtr == IntPtr.Zero) { return(StackUtils.BuildNull()); } _Array arr = (_Array)Marshal.PtrToStructure(arrPtr, typeof(_Array)); var elem = arr.elements; if (mReturnType.Name == "double") { double[] elements = new double[arr.numElems]; Marshal.Copy(arr.elements, elements, 0, arr.numElems); // free up the memory Marshal.FreeCoTaskMem(arr.elements); Marshal.FreeCoTaskMem(arrPtr); returnValue = ConvertCSArrayToDSArray(elements, dsi); } else if (mReturnType.Name == "int") { int[] elements = new int[arr.numElems]; Marshal.Copy(arr.elements, elements, 0, arr.numElems); return(elements); } else { throw new ArgumentException(string.Format("FFI: unknown type {0} to marshall", mReturnType.Name)); } } return(returnValue); }
/// <summary> /// Copy an array and coerce its elements/values to target type /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue CopyArray(StackValue array, Type type, Core core) { Validity.Assert(StackUtils.IsArray(array)); if (!StackUtils.IsArray(array)) { return(StackUtils.BuildNull()); } HeapElement he = GetHeapElement(array, core); Validity.Assert(he != null); int elementSize = GetElementSize(array, core); StackValue[] elements = new StackValue[elementSize]; for (int i = 0; i < elementSize; i++) { StackValue coercedValue = TypeSystem.Coerce(he.Stack[i], type, core); GCUtils.GCRetain(coercedValue, core); elements[i] = coercedValue; } Dictionary <StackValue, StackValue> dict = null; if (he.Dict != null) { dict = new Dictionary <StackValue, StackValue>(new StackValueComparer(core)); foreach (var pair in he.Dict) { StackValue key = pair.Key; StackValue value = pair.Value; StackValue coercedValue = TypeSystem.Coerce(value, type, core); GCUtils.GCRetain(key, core); GCUtils.GCRetain(coercedValue, core); dict[key] = coercedValue; } } return(HeapUtils.StoreArray(elements, dict, core)); }
public static StackValue GetArrayElement(StackValue svPtr, List <StackValue> svDimList, Core core) { Validity.Assert(IsArray(svPtr)); HeapElement heapElem = null; StackValue svFinal = StackUtils.BuildNull(); foreach (StackValue sv in svDimList) { if (svPtr.optype != AddressType.ArrayPointer) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kOverIndexing, ProtoCore.RuntimeData.WarningMessage.kArrayOverIndexed); return(StackUtils.BuildNull()); } heapElem = core.Heap.Heaplist[(int)svPtr.opdata]; svPtr = StackUtils.GetValue(heapElem, (int)sv.opdata, core); svFinal = svPtr; } return(svFinal); }
/// <summary> /// = array[index1][index2][...][indexN], and /// indices = {index1, index2, ..., indexN} /// </summary> /// <param name="array"></param> /// <param name="indices"></param> /// <param name="core"></param> /// <returns></returns> public static StackValue GetValueFromIndices(StackValue array, List <StackValue> indices, Core core) { if (indices.Count == 0) { return(array); } else if (!StackUtils.IsArray(array) && !StackUtils.IsString(array)) { core.RuntimeStatus.LogWarning(WarningID.kOverIndexing, WarningMessage.kArrayOverIndexed); return(StackUtils.BuildNull()); } StackValue[][] zippedIndices = ArrayUtils.GetZippedIndices(indices, core); if (zippedIndices == null || zippedIndices.Length == 0) { return(StackUtils.BuildNull()); } StackValue[] values = new StackValue[zippedIndices.Length]; for (int i = 0; i < zippedIndices.Length; ++i) { values[i] = GetValueFromIndices(array, zippedIndices[i], core); } if (zippedIndices.Length > 1) { for (int i = 0; i < values.Length; ++i) { GCUtils.GCRelease(values[i], core); } return(HeapUtils.StoreArray(values, null, core)); } else { return(values[0]); } }
public StackValue GetStackData(int blockId, int symbolindex, int classscope, int offset = 0) { SymbolNode symbolNode = null; if (Constants.kInvalidIndex == classscope) { symbolNode = Executable.runtimeSymbols[blockId].symbolList[symbolindex]; } else { symbolNode = ClassTable.ClassNodes[classscope].symbols.symbolList[symbolindex]; } Validity.Assert(null != symbolNode); int n = GetRelative(offset, GetStackIndex(symbolNode)); if (n > Stack.Count - 1) { return(StackUtils.BuildNull()); } return(Stack[n]); }
public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi) { int nParamCount = mArgTypes.Length; int paramCount = mArgTypes.Length; int envSize = IsDNI ? 2 : 0; int totalParamCount = paramCount + envSize; List <Object> parameters = new List <object>(); List <ProtoCore.DSASM.StackValue> s = dsi.runtime.rmem.Stack; Object thisObject = null; FFIObjectMarshler marshaller = Module.GetMarshaller(dsi.runtime.Core); if (!ReflectionInfo.IsStatic) { try { thisObject = marshaller.UnMarshal(s.Last(), c, dsi, ReflectionInfo.DeclaringType); } catch (InvalidOperationException) { string message = String.Format(ProtoCore.RuntimeData.WarningMessage.kFFIFailedToObtainThisObject, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.RuntimeData.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; ProtoCore.DSASM.StackValue opArg = dsi.runtime.rmem.GetAtRelative(relative); try { Type paramType = paraminfos[i].ParameterType; object 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) { 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.RuntimeData.WarningID.kAccessViolation, ex.Message); return(null); } catch (InvalidOperationException) { string message = String.Format(ProtoCore.RuntimeData.WarningMessage.kFFIFailedToObtainObject, paraminfos[i].ParameterType.Name, ReflectionInfo.DeclaringType.Name, ReflectionInfo.Name); dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, message); return(null); } } object ret = null; StackValue dsRetValue = StackUtils.BuildNull(); 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.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.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.RuntimeData.WarningID.kInvalidArguments, ErrorString(exc)); } else if (exc is System.NullReferenceException) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ErrorString(null)); } else { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ErrorString(exc)); } } else { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ErrorString(ex)); } } catch (System.Reflection.TargetParameterCountException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.MethodAccessException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.InvalidOperationException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.NotSupportedException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.InnerException.Message); } dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kAccessViolation, ex.Message); } catch (System.ArgumentException ex) { if (ex.InnerException != null) { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kInvalidArguments, ErrorString(ex.InnerException)); } else { dsi.LogWarning(ProtoCore.RuntimeData.WarningID.kInvalidArguments, ErrorString(ex)); } } catch (Exception ex) { if (ex.InnerException != null) { dsi.LogSemanticError(ErrorString(ex.InnerException)); } dsi.LogSemanticError(ErrorString(ex)); } return(dsRetValue); }
public ExecutionMirror Execute(string code) { code = string.Format("{0} = {1};", Constants.kWatchResultVar, code); // TODO Jun: Move this initaliztion of the exe into a unified function //Core.ExprInterpreterExe = new Executable(); int blockId = ProtoCore.DSASM.Constants.kInvalidIndex; Core.Rmem.AlignStackForExprInterpreter(); //Initialize the watch stack and watchBaseOffset //The watchBaseOffset is used to indexing the watch variables and related temporary variables Core.watchBaseOffset = 0; Core.watchStack.Clear(); bool succeeded = Compile(code, out blockId); //Clear the warnings and errors so they will not continue impact the next compilation. //Fix IDE-662 Core.BuildStatus.Errors.Clear(); Core.BuildStatus.Warnings.Clear(); for (int i = 0; i < Core.watchBaseOffset; ++i) { Core.watchStack.Add(StackUtils.BuildNull()); } //Record the old function call depth //Fix IDE-523: part of error for watching non-existing member int oldFunctionCallDepth = Core.FunctionCallDepth; //Record the old start PC int oldStartPC = Core.startPC; if (succeeded) { //a2. Record the old start PC for restore instructions Core.startPC = Core.ExprInterpreterExe.instrStreamList[blockId].instrList.Count; Core.GenerateExprExeInstructions(blockId); //a3. Record the old running block int restoreBlock = Core.RunningBlock; Core.RunningBlock = blockId; //a4. Record the old debug entry PC and stack size of FileFepChosen int oldDebugEntryPC = Core.DebugProps.DebugEntryPC; //a5. Record the frame pointer for referencing to thisPtr Core.watchFramePointer = Core.Rmem.FramePointer; // The "Core.Bounce" below is gonna adjust the "FramePointer" // based on the current size of "Core.Rmem.Stack". All that is // good except that "Bounce" does not restore the previous value // of frame pointer after "bouncing back". Here we make a backup // of it and restore it right after the "Core.Bounce" call. // //Core.Executives[Core.CodeBlockList[Core.RunningBlock].language]. ProtoCore.Runtime.Context context = new ProtoCore.Runtime.Context(); try { ProtoCore.DSASM.StackFrame stackFrame = null; int locals = 0; StackValue sv = Core.Bounce(blockId, Core.startPC, context, stackFrame, locals, EventSink); // As Core.InterpreterProps stack member is pushed to every time the Expression Interpreter begins executing // it needs to be popped off at the end for stack alignment - pratapa Core.InterpreterProps.Pop(); } catch { } //r5. Restore frame pointer. Core.Rmem.FramePointer = Core.watchFramePointer; //r4. Restore the debug entry PC and stack size of FileFepChosen Core.DebugProps.DebugEntryPC = oldDebugEntryPC; //r3. Restore the running block Core.RunningBlock = restoreBlock; //r2. Restore the instructions in Core.ExprInterpreterExe int from = Core.startPC; int elems = Core.ExprInterpreterExe.iStreamCanvas.instrList.Count; Core.ExprInterpreterExe.instrStreamList[blockId].instrList.RemoveRange(from, elems); //Restore the start PC Core.startPC = oldStartPC; //Restore the function call depth //Fix IDE-523: part of error for watching non-existing member Core.FunctionCallDepth = oldFunctionCallDepth; //Clear the watchSymbolList foreach (SymbolNode node in Core.watchSymbolList) { if (ProtoCore.DSASM.Constants.kInvalidIndex == node.classScope) { Core.DSExecutable.runtimeSymbols[node.runtimeTableIndex].Remove(node); } else { Core.ClassTable.ClassNodes[node.classScope].symbols.Remove(node); } } } else { //Restore the start PC Core.startPC = oldStartPC; //Restore the function call depth //Fix IDE-523: part of error for watching non-existing member Core.FunctionCallDepth = oldFunctionCallDepth; //Clear the watchSymbolList foreach (SymbolNode node in Core.watchSymbolList) { if (ProtoCore.DSASM.Constants.kInvalidIndex == node.classScope) { Core.DSExecutable.runtimeSymbols[node.runtimeTableIndex].Remove(node); } else { Core.ClassTable.ClassNodes[node.classScope].symbols.Remove(node); } } // TODO: investigate why additional elements are added to the stack. Core.Rmem.RestoreStackForExprInterpreter(); throw new ProtoCore.Exceptions.CompileErrorsOccured(); } // TODO: investigate why additional elements are added to the stack. Core.Rmem.RestoreStackForExprInterpreter(); return(new ExecutionMirror(Core.CurrentExecutive.CurrentDSASMExec, Core)); }
/// <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 = StackUtils.BuildNull(); if (StackUtils.IsArray(target)) { //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 = StackUtils.BuildNull(); } 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 = new StackValue(); if (StackUtils.IsArray(target)) { //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 = StackUtils.BuildNull(); } 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 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 = StackUtils.BuildNull(); if (StackUtils.IsArray(target)) { //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 = StackUtils.BuildNull(); } 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 = StackUtils.BuildNull(); if (StackUtils.IsArray(target)) { //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 = StackUtils.BuildNull(); } 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); }
public static StackValue Coerce(StackValue sv, Type targetType, Core core) { //@TODO(Jun): FIX ME - abort coersion for default args if (sv.optype == AddressType.DefaultArg) { return(sv); } if (!( (int)sv.metaData.type == targetType.UID || (core.DSExecutable.classTable.ClassNodes[(int)sv.metaData.type].ConvertibleTo(targetType.UID)) || sv.optype == AddressType.ArrayPointer)) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, ProtoCore.RuntimeData.WarningMessage.kConvertNonConvertibleTypes); return(StackUtils.BuildNull()); } //if it's an array if (sv.optype == AddressType.ArrayPointer && !targetType.IsIndexable && targetType.rank != DSASM.Constants.kUndefinedRank)// && targetType.UID != (int)PrimitiveType.kTypeVar) { //This is an array rank reduction //this may only be performed in recursion and is illegal here string errorMessage = String.Format(ProtoCore.RuntimeData.WarningMessage.kConvertArrayToNonArray, core.TypeSystem.GetType(targetType.UID)); core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, errorMessage); return(StackUtils.BuildNull()); } if (sv.optype == AddressType.ArrayPointer && targetType.IsIndexable) { Validity.Assert(ArrayUtils.IsArray(sv)); //We're being asked to convert an array into an array //walk over the structure converting each othe elements if (targetType.UID == (int)PrimitiveType.kTypeVar && targetType.rank == DSASM.Constants.kArbitraryRank && core.Heap.IsTemporaryPointer(sv)) { return(sv); } HeapElement he = core.Heap.Heaplist[(int)sv.opdata]; StackValue[] newSubSVs = new StackValue[he.VisibleSize]; //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 != ProtoCore.DSASM.Constants.kArbitraryRank) { newTargetType.rank = targetType.rank - 1; newTargetType.IsIndexable = newTargetType.rank > 0; } else { if (ArrayUtils.GetMaxRankForArray(sv, core) == 1) { //Last unpacking newTargetType.rank = 0; newTargetType.IsIndexable = false; } else { newTargetType.rank = ProtoCore.DSASM.Constants.kArbitraryRank; newTargetType.IsIndexable = true; } } for (int i = 0; i < he.VisibleSize; i++) { StackValue coercedValue = Coerce(he.Stack[i], newTargetType, core); GCUtils.GCRetain(coercedValue, core); newSubSVs[i] = coercedValue; } StackValue newSV = HeapUtils.StoreArray(newSubSVs, core); return(newSV); } if (sv.optype != AddressType.ArrayPointer && sv.optype != AddressType.Null && 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.IsIndexable = false; newTargetType.Name = targetType.Name; newTargetType.rank = 0; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = HeapUtils.StoreArray(new StackValue[] { coercedValue }, core); 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.IsIndexable = true; newTargetType.Name = targetType.Name; newTargetType.rank = targetType.rank - 1; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = HeapUtils.StoreArray(new StackValue[] { coercedValue }, core); return(newSv); } } if (sv.optype == AddressType.Pointer) { 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.AsBoolean(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.AsDouble()); case (int)PrimitiveType.kTypeFunctionPointer: if (sv.metaData.type != (int)PrimitiveType.kTypeFunctionPointer) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToFunction); return(StackUtils.BuildNull()); } return(sv.ShallowClone()); 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) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, ProtoCore.RuntimeData.WarningMessage.kConvertDoubleToInt); } return(sv.AsInt()); } case (int)PrimitiveType.kTypeNull: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToNull); return(StackUtils.BuildNull()); } return(sv.ShallowClone()); } case (int)PrimitiveType.kTypePointer: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToPointer); return(StackUtils.BuildNull()); } StackValue ret = sv.ShallowClone(); return(ret); } 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 = ProtoCore.Utils.EncodingUtils.ConvertInt64ToCharacter(newSV.opdata); newSV = StackUtils.BuildString(ch.ToString(), core.Heap); } return(newSV); } case (int)PrimitiveType.kTypeVar: { return(sv); } case (int)PrimitiveType.kTypeArray: { HeapElement he = core.Heap.Heaplist[(int)sv.opdata]; StackValue[] newSubSVs = new StackValue[he.VisibleSize]; for (int i = 0; i < he.VisibleSize; i++) { StackValue coercedValue = Coerce(he.Stack[i], targetType, core); GCUtils.GCRetain(coercedValue, core); newSubSVs[i] = coercedValue; } StackValue newSV = HeapUtils.StoreArray(newSubSVs, core); return(newSV); } default: if (sv.optype == AddressType.Null) { return(StackUtils.BuildNull()); } else { throw new NotImplementedException("Requested coercion not implemented"); } } throw new NotImplementedException("Requested coercion not implemented"); }
public override StackValue Execute(ProtoCore.Runtime.Context c, List <StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { // ensure there is no data race, function resolution and execution happens in parallel // but for FFI we want it to be serial cause the code we are calling into may not cope // with parallelism. // // we are always looking and putting our function pointers in handler with each lang // so better lock for FFIHandler (being static) it will be good object to lock // lock (FFIHandlers) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); StackValue svThisPtr = stackFrame.GetAt(StackFrame.AbsoluteIndex.kThisPtr); StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.JILRecord.classIndex; int fi = activation.JILRecord.funcIndex; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)svBlockDecl.opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = core.Rmem.FramePointer; int locals = activation.JILRecord.locals; FFIHandler handler = FFIHandlers[activation.ModuleType]; FFIActivationRecord r = activation; string className = ""; if (activation.JILRecord.classIndex > 0) { className = core.DSExecutable.classTable.ClassNodes[activation.JILRecord.classIndex].name; } bool gcThisPtr = false; List <ProtoCore.Type> argTypes = new List <Type>(r.ParameterTypes); ProcedureNode fNode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != ci) { fNode = interpreter.runtime.exe.classTable.ClassNodes[ci].vtable.procList[fi]; } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != fNode && fNode.isAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = AddressType.Pointer == svThisPtr.optype && ProtoCore.DSASM.Constants.kInvalidPointer == (int)svThisPtr.opdata; if (isStaticCall) { thisPtrIndex = formalParameters.Count - 1; } argTypes.RemoveAt(thisPtrIndex); // Comment Jun: Execute() can handle a null this pointer. // But since we dont even need to to reach there if we dont have a valid this pointer, then just return null if (AddressType.Null == formalParameters[thisPtrIndex].optype) { core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kDereferencingNonPointer, ProtoCore.RuntimeData.WarningMessage.kDeferencingNonPointer); return(StackUtils.BuildNull()); } // These are the op types allowed. Validity.Assert(AddressType.Pointer == formalParameters[thisPtrIndex].optype || AddressType.DefaultArg == formalParameters[thisPtrIndex].optype); svThisPtr = formalParameters[thisPtrIndex]; gcThisPtr = true; formalParameters.RemoveAt(thisPtrIndex); } FFIFunctionPointer functionPointer = handler.GetFunctionPointer(r.ModuleName, className, r.FunctionName, argTypes, r.ReturnType); mFunctionPointer = Validate(functionPointer) ? functionPointer : null; mFunctionPointer.IsDNI = activation.IsDNI; if (mFunctionPointer == null) { return(ProtoCore.DSASM.StackUtils.BuildNull()); } List <object> ps = new List <object>(); //obsolete { interpreter.runtime.executingBlock = core.RunningBlock; activation.JILRecord.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } List <ProtoCore.DSASM.StackValue> registers = new List <DSASM.StackValue>(); interpreter.runtime.SaveRegisters(registers); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = 0; StackFrameType callerType = (StackFrameType)stackFrame.GetAt(StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; // FFI calls do not have execution states core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, ProtoCore.DSASM.StackFrameType.kTypeFunction, depth, framePointer, registers, locals, 0); //is there a way the current stack be passed across and back into the managed runtime by FFI calling back into the language? //e.g. DCEnv* carrying all the stack information? look at how vmkit does this. // = jilMain.Run(ActivationRecord.JILRecord.pc, null, true); //double[] tempArray = GetUnderlyingArray<double>(jilMain.runtime.rmem.stack); Object ret = mFunctionPointer.Execute(c, interpreter); StackValue op; if (ret == null) { op = StackUtils.BuildNull(); } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = new StackValue(); op.optype = AddressType.Int; op.opdata = (Int64)ret; } else if (ret is double) { op = new StackValue(); op.optype = AddressType.Double; op.opdata_d = (double)ret; } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } // gc the parameters if (gcThisPtr)// && core.Options.EnableThisPointerFunctionOverload) { // thisptr is sent as parameter, so need to gc it. // but when running in expression interpreter mode, do not GC because in DSASM.Executive.DecRefCounter() related GC functions, // the reference count will not be changed in expression interpreter mode. if (core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { interpreter.runtime.Core.Rmem.Heap.GCRelease(new StackValue[] { svThisPtr }, interpreter.runtime); } } interpreter.runtime.Core.Rmem.Heap.GCRelease(formalParameters.ToArray(), interpreter.runtime); // increment the reference counter of the return value interpreter.runtime.GCRetain(op); // Clear the FFI stack frame // FFI stack frames have no local variables interpreter.runtime.rmem.FramePointer = (int)interpreter.runtime.rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; interpreter.runtime.rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + formalParameters.Count); return(op); //DSASM.Mirror.ExecutionMirror.Unpack(op, core.heap, core); } } }