Exemplo n.º 1
0
 private FText()
 {
     ownsNativeAddress = true;
     nativeAddress     = FMemory.Malloc(FTextNative.StructSize);
     FMemory.Memzero(nativeAddress, FTextNative.StructSize);
     OwnsReference = true;// This assumes FText is initialized with a reference after this ctor
 }
Exemplo n.º 2
0
        public void AddPair(IntPtr keyPtr, IntPtr valuePtr)
        {
            IntPtr localKeyPropForCapture   = keyProp;
            IntPtr localValuePropForCapture = valueProp;

            HashDelegates.GetKeyHash keyHash = delegate(IntPtr elementKey)
            {
                return(Native_UProperty.GetValueTypeHash(localKeyPropForCapture, elementKey));
            };
            HashDelegates.Equality keyEquality = delegate(IntPtr a, IntPtr b)
            {
                return(Native_UProperty.Identical(localKeyPropForCapture, a, b, 0));
            };
            HashDelegates.ConstructAndAssign keyConstructAndAssign = delegate(IntPtr newElementKey)
            {
                if (Native_UProperty.HasAnyPropertyFlags(localKeyPropForCapture, EPropertyFlags.ZeroConstructor))
                {
                    FMemory.Memzero(newElementKey, Native_UProperty.GetSize(localKeyPropForCapture));
                }
                else
                {
                    Native_UProperty.InitializeValue(localKeyPropForCapture, newElementKey);
                }

                Native_UProperty.CopySingleValue(localKeyPropForCapture, newElementKey, keyPtr);
            };
            HashDelegates.ConstructAndAssign valueConstructAndAssign = delegate(IntPtr newElementValue)
            {
                if (Native_UProperty.HasAnyPropertyFlags(localValuePropForCapture, EPropertyFlags.ZeroConstructor))
                {
                    FMemory.Memzero(newElementValue, Native_UProperty.GetSize(localValuePropForCapture));
                }
                else
                {
                    Native_UProperty.InitializeValue(localValuePropForCapture, newElementValue);
                }

                Native_UProperty.CopySingleValue(localValuePropForCapture, newElementValue, valuePtr);
            };
            HashDelegates.Assign valueAssign = delegate(IntPtr existingElementValue)
            {
                Native_UProperty.CopySingleValue(localValuePropForCapture, existingElementValue, valuePtr);
            };
            HashDelegates.Destruct keyDestruct = delegate(IntPtr elementKey)
            {
                if (!Native_UProperty.HasAnyPropertyFlags(localKeyPropForCapture, EPropertyFlags.IsPlainOldData | EPropertyFlags.NoDestructor))
                {
                    Native_UProperty.DestroyValue(localKeyPropForCapture, elementKey);
                }
            };
            HashDelegates.Destruct valueDestruct = delegate(IntPtr elementValue)
            {
                if (!Native_UProperty.HasAnyPropertyFlags(localValuePropForCapture, EPropertyFlags.IsPlainOldData | EPropertyFlags.NoDestructor))
                {
                    Native_UProperty.DestroyValue(localValuePropForCapture, elementValue);
                }
            };
            map->Add(keyPtr, valuePtr, ref mapLayout, keyHash, keyEquality, keyConstructAndAssign, valueConstructAndAssign,
                     valueAssign, keyDestruct, valueDestruct);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Adds zeroed values to the end of the array (calls FMemory.Memzero on the memory range).
        /// </summary>
        /// <param name="count">The number of items to insert.</param>
        /// <returns>the indnex of the first newly added item</returns>
        public int AddZeroedValues(int count)
        {
            int    oldNum = array->Add(elementSize, count);
            IntPtr dest   = GetRawPtr();

            FMemory.Memzero(dest, count * elementSize);
            return(oldNum);
        }
Exemplo n.º 4
0
        private void ClearItems(int index, int count)
        {
            IntPtr dest = GetRawPtr(index);

            if (Native_UProperty.HasAnyPropertyFlags(innerProperty, EPropertyFlags.ZeroConstructor | EPropertyFlags.NoDestructor))
            {
                FMemory.Memzero(dest, count * elementSize);
            }
            else
            {
                for (int i = 0; i < count; i++, dest += elementSize)
                {
                    Native_UProperty.ClearValue(innerProperty, dest);
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Internal function to call into the property system to construct / initialize elements.
        /// </summary>
        /// <param name="index"First item to construct.></param>
        private void ConstructItem(int index)
        {
            bool zeroElement = Native_UProperty.HasAnyPropertyFlags(elementProp, EPropertyFlags.ZeroConstructor);

            IntPtr dest = GetElementPtrWithoutCheck(index);

            if (zeroElement)
            {
                // If any nested property needs zeroing, just pre-zero the whole space
                FMemory.Memzero(dest, setLayout.Size);
            }

            if (!zeroElement)
            {
                Native_UProperty.InitializeValue_InContainer(elementProp, dest);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Adds the element to the set, returning true if the element was added, or false if the element was already present
        /// </summary>
        public void AddElement(IntPtr elementToAdd)
        {
            IntPtr localElementPropForCapture = elementProp;

            HashDelegates.GetKeyHash elementHash = delegate(IntPtr elementKey)
            {
                return(Native_UProperty.GetValueTypeHash(localElementPropForCapture, elementKey));
            };
            HashDelegates.Equality elementEquality = delegate(IntPtr a, IntPtr b)
            {
                return(Native_UProperty.Identical(localElementPropForCapture, a, b, 0));
            };
            HashDelegates.Construct elementConstruct = delegate(IntPtr newElement)
            {
                if (Native_UProperty.HasAnyPropertyFlags(localElementPropForCapture, EPropertyFlags.ZeroConstructor))
                {
                    FMemory.Memzero(newElement, Native_UProperty.GetSize(localElementPropForCapture));
                }
                else
                {
                    Native_UProperty.InitializeValue(localElementPropForCapture, newElement);
                }

                Native_UProperty.CopySingleValue(localElementPropForCapture, newElement, elementToAdd);
            };
            HashDelegates.Destruct elementDestruct = delegate(IntPtr element)
            {
                if (!Native_UProperty.HasAnyPropertyFlags(localElementPropForCapture, EPropertyFlags.IsPlainOldData | EPropertyFlags.NoDestructor))
                {
                    Native_UProperty.DestroyValue(localElementPropForCapture, element);
                }
            };
            set->Add(
                elementToAdd,
                ref setLayout,
                elementHash,
                elementEquality,
                elementConstruct,
                elementDestruct);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Internal function to call into the property system to construct / initialize elements.
        /// </summary>
        /// <param name="index">First item to construct.</param>
        private void ConstructItem(int index)
        {
            bool zeroKey   = Native_UProperty.HasAnyPropertyFlags(keyProp, EPropertyFlags.ZeroConstructor);
            bool zeroValue = Native_UProperty.HasAnyPropertyFlags(valueProp, EPropertyFlags.ZeroConstructor);

            IntPtr dest = GetPairPtrWithoutCheck(index);

            if (zeroKey || zeroValue)
            {
                // If any nested property needs zeroing, just pre-zero the whole space
                FMemory.Memzero(dest, mapLayout.SetLayout.Size);
            }

            if (!zeroKey)
            {
                Native_UProperty.InitializeValue_InContainer(keyProp, dest);
            }

            if (!zeroValue)
            {
                Native_UProperty.InitializeValue_InContainer(valueProp, dest);
            }
        }
Exemplo n.º 8
0
 private void ZeroMemory()
 {
     FMemory.Memzero(ref this);
 }
Exemplo n.º 9
0
        /// <summary>
        /// Checks if the given UScriptStruct address is POD and has a zero constructor (initializes to zero).
        ///
        /// NOTE: A struct could be PlainOldData but unsafe to zero initialize due to having a non-zero constructor / EForceInit constructor.
        /// </summary>
        internal static bool IsPODZeroInit(IntPtr unrealStruct)
        {
            if (unrealStruct != IntPtr.Zero && Native_UObjectBaseUtility.IsA(unrealStruct, Classes.UScriptStruct))
            {
                EStructFlags structFlags = Native_UScriptStruct.Get_StructFlags(unrealStruct);

                IntPtr cppStructOps = Native_UScriptStruct.GetCppStructOps(unrealStruct);
                if (cppStructOps != IntPtr.Zero)
                {
                    bool isPlainOldData     = Native_ICppStructOps.IsPlainOldData(cppStructOps);
                    bool hasZeroConstructor = Native_ICppStructOps.HasZeroConstructor(cppStructOps);
                    bool hasNoopConstructor = Native_ICppStructOps.HasNoopConstructor(cppStructOps);

                    if (!hasZeroConstructor && structFlags.HasFlag(EStructFlags.ZeroConstructor))
                    {
                        // This struct flag could have been set in the zero constructor check in UScriptStruct::PrepareCppStructOps
                        hasZeroConstructor = true;
                    }

                    if (isPlainOldData && hasZeroConstructor && !hasNoopConstructor)
                    {
                        return(true);
                    }

                    if (isPlainOldData && !hasZeroConstructor)
                    {
                        if (hasNoopConstructor)
                        {
                            // The struct has a no-op constructor and takes EForceInit to init
                            return(false);
                        }

                        // This is a copy of a check made in UScriptStruct::PrepareCppStructOps to check if the struct constructs to zero
                        // if (CppStructOps->IsPlainOldData() && !CppStructOps->HasZeroConstructor()) { ... }

                        int    size   = Native_ICppStructOps.GetSize(cppStructOps);
                        IntPtr buffer = FMemory.Malloc(size);
                        FMemory.Memzero(buffer, size);
                        Native_ICppStructOps.Construct(cppStructOps, buffer);
                        Native_ICppStructOps.Construct(cppStructOps, buffer);// slightly more like to catch "internal counters" if we do this twice

                        bool isZeroConstruct = true;
                        unsafe
                        {
                            byte *bufferPtr = (byte *)buffer;
                            for (int i = 0; i < size; i++)
                            {
                                if (bufferPtr[i] != 0)
                                {
                                    isZeroConstruct = false;
                                    break;
                                }
                            }
                        }

                        FMemory.Free(buffer);

                        if (isZeroConstruct)
                        {
                            // "Native struct %s has DISCOVERED zero construction. Size = %d"
                            System.Diagnostics.Debugger.Break();
                            return(true);
                        }
                    }
                    return(false);
                }
                else
                {
                    // Only treat it as blittable if it is POD and has a zero constructor
                    return(structFlags.HasFlag(EStructFlags.IsPlainOldData | EStructFlags.ZeroConstructor));
                }
            }
            return(false);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Dynamically invokes the function
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public object DynamicInvoke(UObject obj, params object[] parameters)
        {
            if (parameters == null)
            {
                parameters = new object[0];
            }

            bool validParams = true;

            Dictionary <UProperty, Delegate> fromNativeParams = new Dictionary <UProperty, Delegate>();
            Dictionary <UProperty, Delegate> toNativeParams   = new Dictionary <UProperty, Delegate>();

            UProperty        returnValueProp = null;
            List <UProperty> paramProps      = new List <UProperty>();

            foreach (UProperty prop in GetProperties <UProperty>())
            {
                if (prop.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    if (prop.HasAnyPropertyFlags(EPropertyFlags.ReturnParm))
                    {
                        returnValueProp = prop;
                    }
                    else
                    {
                        paramProps.Add(prop);
                    }

                    Type paramType = UProperty.GetTypeFromProperty(prop);
                    if (paramType == null)
                    {
                        validParams = false;
                        break;
                    }

                    Delegate fromNative = MarshalingDelegateResolverSlow.GetFromNative(paramType);
                    Delegate toNative   = MarshalingDelegateResolverSlow.GetToNative(paramType);
                    if (fromNative == null || toNative == null)
                    {
                        validParams = false;
                        break;
                    }

                    fromNativeParams.Add(prop, fromNative);
                    toNativeParams.Add(prop, toNative);
                }
            }

            if (parameters.Length != paramProps.Count)
            {
                validParams = false;
            }

            if (!validParams)
            {
                return(null);
            }

            // Sort the parameters by offset, this is assumingly the correct thing to do?
            // - Otherwise we need to take the param names into this function. Or just not sort at all?
            //paramProps.Sort((x, y) => x.GetOffset_ForUFunction().CompareTo(y.GetOffset_ForUFunction()));

            object result = null;

            unsafe
            {
                int    paramsSize             = ParmsSize;
                byte * paramsBufferAllocation = stackalloc byte[ParmsSize];
                IntPtr paramsBuffer           = new IntPtr(paramsBufferAllocation);
                FMemory.Memzero(paramsBuffer, paramsSize);

                // Initialize default values for all parameters
                foreach (UProperty prop in GetProperties <UProperty>())
                {
                    if (prop.HasAnyPropertyFlags(EPropertyFlags.Parm))
                    {
                        Native.Native_UProperty.InitializeValue_InContainer(prop.Address, paramsBuffer);
                    }
                }

                // Copy the managed parameters to the buffer
                for (int i = 0; i < parameters.Length; i++)
                {
                    UProperty paramProp  = paramProps[i];
                    object    paramValue = parameters[i];
                    if (paramValue != null && (!paramProp.HasAnyPropertyFlags(EPropertyFlags.OutParm) ||
                                               paramProp.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm)))
                    {
                        toNativeParams[paramProp].DynamicInvoke(
                            paramsBuffer + paramProp.GetOffset_ForUFunction(), (int)0, paramProp.Address, paramValue);
                    }
                }

                // Invoke the function
                NativeReflection.InvokeFunction(obj.Address, Address, paramsBuffer, paramsSize);

                // Copy parameters / return value from the buffer
                for (int i = 0; i < parameters.Length; i++)
                {
                    UProperty paramProp = paramProps[i];
                    if (paramProp.HasAnyPropertyFlags(EPropertyFlags.OutParm))
                    {
                        parameters[i] = fromNativeParams[paramProp].DynamicInvoke(
                            paramsBuffer + paramProp.GetOffset_ForUFunction(), (int)0, paramProp.Address);
                    }
                }
                if (returnValueProp != null)
                {
                    result = fromNativeParams[returnValueProp].DynamicInvoke(
                        paramsBuffer + returnValueProp.GetOffset_ForUFunction(), (int)0, returnValueProp.Address);
                }

                // Destroy the memory for all of the parameters
                foreach (UProperty prop in GetProperties <UProperty>())
                {
                    if (prop.HasAnyPropertyFlags(EPropertyFlags.Parm))
                    {
                        Native.Native_UProperty.DestroyValue_InContainer(prop.Address, paramsBuffer);
                    }
                }
            }

            return(result);
        }
Exemplo n.º 11
0
            private unsafe void HandleInvokeFunctionFromBP(IntPtr obj, FFrame *stack, IntPtr result,
                                                           UFunction.FuncInvokerManaged managedFunctionInvoker)
            {
                // NOTE: ScriptCore.cpp uses PropertiesSize instead of ParamsSize. Is it ever any different? (it says alignment
                // may make them different) If it is different we should probably use PropertiesSize (including in generated code /
                // IL) as ScriptCore.cpp uses a memcpy of our memory.
                Debug.Assert(Native_UStruct.Get_PropertiesSize(stack->CurrentNativeFunction) ==
                             Native_UFunction.Get_ParmsSize(stack->CurrentNativeFunction));

                IntPtr function     = stack->CurrentNativeFunction;
                int    paramsSize   = Native_UFunction.Get_ParmsSize(function);
                int    numParams    = Native_UFunction.Get_NumParms(function);
                bool   hasOutParams = Native_UFunction.HasAnyFunctionFlags(function, EFunctionFlags.HasOutParms);

                IntPtr *outParamsBufferPtr = stackalloc IntPtr[numParams];

                byte * paramsBufferPtr = stackalloc byte[paramsSize];
                IntPtr paramsBuffer    = (IntPtr)paramsBufferPtr;

                // We could skip this memzero as stackalloc will (always?) zero memory even though the spec states
                // "The content of the newly allocated memory is undefined."
                // https://github.com/dotnet/coreclr/issues/1279
                FMemory.Memzero(paramsBuffer, paramsSize);

                if (hasOutParams)
                {
                    int paramIndex = 0;
                    foreach (IntPtr param in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        // Not required but using for Debug.Assert() when getting the value
                        stack->MostRecentPropertyAddress = IntPtr.Zero;

                        stack->Step(stack->Object, paramsBuffer + Native_UProperty.GetOffset_ForUFunction(param));
                        outParamsBufferPtr[paramIndex] = stack->MostRecentPropertyAddress;

                        if (Native_UProperty.HasAnyPropertyFlags(param, EPropertyFlags.ReturnParm))
                        {
                            // This should be UObject::execEndFunctionParms which will just do "stack->Code--;" for allowing
                            // the caller to use PFINISH aftwards
                            outParamsBufferPtr[paramIndex] = result;
                        }

                        paramIndex++;
                    }
                }
                else
                {
                    foreach (IntPtr param in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        stack->Step(stack->Object, paramsBuffer + Native_UProperty.GetOffset_ForUFunction(param));
                    }
                }
                stack->PFinish();// Skip EX_EndFunctionParms

                // Call the managed function invoker which will marshal the params from the native params buffer and then call the
                // target managed function
                managedFunctionInvoker(paramsBuffer, obj);

                // Copy out params from the temp buffer
                if (hasOutParams)
                {
                    int paramIndex = 0;
                    foreach (IntPtr paramProp in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        if (Native_UProperty.HasAnyPropertyFlags(paramProp, EPropertyFlags.OutParm))
                        {
                            Debug.Assert(outParamsBufferPtr[paramIndex] != IntPtr.Zero);

                            // - See "REMOVING the DestroyValue call" below.
                            // Destroy the existing memory (this assumed the existing memory is valid or at least memzerod)
                            //Native_UProperty.DestroyValue(paramProp, outParamsBufferPtr[paramIndex]);

                            // A raw memcpy should be OK since the managed invoker should have set this memory appropriately.
                            FMemory.Memcpy(outParamsBufferPtr[paramIndex],
                                           paramsBuffer + Native_UProperty.GetOffset_ForUFunction(paramProp),
                                           Native_UProperty.Get_ElementSize(paramProp));// Should be ArrayDim*ElementSize but ArrayDim should always be 1 for params
                        }
                        paramIndex++;
                    }
                }

                // Parameters are copied when calling stack->Step(). We are responsible for destroying non-blittable types
                // which were copied (FString, TArray, etc). For C++ this works out well due to the copy constructors etc.
                //
                // Example where an FString is constructed from stack->Step():
                // UObject::execStringConst(...) { *(FString*)RESULT_PARAM = (ANSICHAR*)Stack.Code; }
                //
                // For C# it might be better if we reimplemented all of the IMPLEMENT_VM_FUNCTION functions to reduce the amount
                // of copying as we currently need ANOTHER copy to get it from the temp buffer into a C# type (which is done
                // inside the managedFunctionInvoker function)
                foreach (IntPtr paramProp in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function,
                                                                                      EFieldIteratorType.Destructor, false))
                {
                    // When is this ever false? It seems to be checked in UObject::ProcessEvent()
                    // "Destroy local variables except function parameters." - used for BP locals?
                    Debug.Assert(Native_UProperty.IsInContainer(paramProp, paramsSize));

                    // Out params are copied to the memory maintained by the caller so only destroy "by value" parameters.
                    if (!Native_UProperty.HasAnyPropertyFlags(paramProp, EPropertyFlags.OutParm))
                    {
                        Native_UProperty.DestroyValue_InContainer(paramProp, paramsBuffer);
                    }
                }
            }
Exemplo n.º 12
0
 internal void ZeroMemory()
 {
     FMemory.Memzero(ref this);
 }