Esempio n. 1
0
        /// <summary>
        /// Internal function to call into the property system to destruct elements.
        /// </summary>
        private void DestructItems(int index, int count)
        {
            if (count <= 0)
            {
                return;
            }

            bool destroyElements = !Native_UProperty.HasAnyPropertyFlags(elementProp, EPropertyFlags.IsPlainOldData | EPropertyFlags.NoDestructor);

            if (destroyElements)
            {
                int    stride     = setLayout.Size;
                IntPtr elementPtr = GetElementPtrWithoutCheck(index);

                for (; count != 0; ++index)
                {
                    if (IsValidIndex(index))
                    {
                        Native_UProperty.DestroyValue_InContainer(elementProp, elementPtr);
                        --count;
                    }
                    elementPtr += stride;
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Internal function to call into the property system to destruct elements.
        /// </summary>
        private void DestructItems(int index, int count)
        {
            if (count <= 0)
            {
                return;
            }

            bool destroyKeys   = !Native_UProperty.HasAnyPropertyFlags(keyProp, EPropertyFlags.IsPlainOldData | EPropertyFlags.NoDestructor);
            bool destroyValues = !Native_UProperty.HasAnyPropertyFlags(valueProp, EPropertyFlags.IsPlainOldData | EPropertyFlags.NoDestructor);

            if (destroyKeys || destroyValues)
            {
                int    stride  = mapLayout.SetLayout.Size;
                IntPtr pairPtr = GetPairPtr(index);
                if (destroyKeys)
                {
                    if (destroyValues)
                    {
                        for (; count != 0; ++index)
                        {
                            if (IsValidIndex(index))
                            {
                                Native_UProperty.DestroyValue_InContainer(keyProp, pairPtr);
                                Native_UProperty.DestroyValue_InContainer(valueProp, pairPtr);
                                --count;
                            }
                            pairPtr += stride;
                        }
                    }
                    else
                    {
                        for (; count != 0; ++index)
                        {
                            if (IsValidIndex(index))
                            {
                                Native_UProperty.DestroyValue_InContainer(keyProp, pairPtr);
                                --count;
                            }
                            pairPtr += stride;
                        }
                    }
                }
                else
                {
                    for (; count != 0; ++index)
                    {
                        if (IsValidIndex(index))
                        {
                            Native_UProperty.DestroyValue_InContainer(valueProp, pairPtr);
                            --count;
                        }
                        pairPtr += stride;
                    }
                }
            }
        }
Esempio n. 3
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);
                    }
                }
            }