Пример #1
0
        public static void EncodeGCDesc <T>(ref T builder, TypeDesc type)
            where T : struct, ITargetBinaryWriter
        {
            int initialBuilderPosition = builder.CountBytes;

            if (type.IsArray)
            {
                TypeDesc elementType = ((ArrayType)type).ElementType;

                // 2 means m_pEEType and _numComponents. Syncblock is sort of appended at the end of the object layout in this case.
                int baseSize = 2 * builder.TargetPointerSize;

                if (type.IsMdArray)
                {
                    // Multi-dim arrays include upper and lower bounds for each rank
                    baseSize += 2 * sizeof(int) * ((ArrayType)type).Rank;
                }

                if (elementType.IsGCPointer)
                {
                    EncodeAllGCPointersArrayGCDesc(ref builder, baseSize);
                }
                else if (elementType.IsDefType)
                {
                    var elementDefType = (DefType)elementType;
                    if (elementDefType.ContainsGCPointers)
                    {
                        GCPointerMap pointerMap = GCPointerMap.FromInstanceLayout(elementDefType);
                        if (pointerMap.IsAllGCPointers)
                        {
                            EncodeAllGCPointersArrayGCDesc(ref builder, baseSize);
                        }
                        else
                        {
                            EncodeArrayGCDesc(ref builder, pointerMap, baseSize);
                        }
                    }
                }
            }
            else
            {
                var defType = (DefType)type;
                if (defType.ContainsGCPointers)
                {
                    // Computing the layout for the boxed version if this is a value type.
                    int offs = defType.IsValueType ? builder.TargetPointerSize : 0;

                    // Include syncblock
                    int objectSize = defType.InstanceByteCount.AsInt + offs + builder.TargetPointerSize;

                    EncodeStandardGCDesc(ref builder, GCPointerMap.FromInstanceLayout(defType), objectSize, offs);
                }
            }

            Debug.Assert(initialBuilderPosition + GetGCDescSize(type) == builder.CountBytes);
        }
Пример #2
0
        public void TestInstanceMap()
        {
            MetadataType classWithArrayFields = _testModule.GetType("GCPointerMap", "ClassWithArrayFields");
            MetadataType classWithStringField = _testModule.GetType("GCPointerMap", "ClassWithStringField");
            MetadataType mixedStruct          = _testModule.GetType("GCPointerMap", "MixedStruct");
            MetadataType structWithSameGCLayoutAsMixedStruct = _testModule.GetType("GCPointerMap", "StructWithSameGCLayoutAsMixedStruct");
            MetadataType doubleMixedStructLayout             = _testModule.GetType("GCPointerMap", "DoubleMixedStructLayout");
            MetadataType explicitlyFarPointer = _testModule.GetType("GCPointerMap", "ExplicitlyFarPointer");
            MetadataType struct32GcPointers   = _testModule.GetType("GCPointerMap", "Struct32GcPointers");

            {
                var map = GCPointerMap.FromInstanceLayout(classWithArrayFields);
                Assert.Equal(3, map.Size);
                Assert.Equal("011", map.ToString());
            }

            {
                var map = GCPointerMap.FromInstanceLayout(classWithStringField);
                Assert.Equal(4, map.Size);
                Assert.Equal("0010", map.ToString());
            }

            {
                var map = GCPointerMap.FromInstanceLayout(mixedStruct);
                Assert.Equal(5, map.Size);
                Assert.Equal("01001", map.ToString());
            }

            {
                var map1 = GCPointerMap.FromInstanceLayout(mixedStruct);
                var map2 = GCPointerMap.FromInstanceLayout(structWithSameGCLayoutAsMixedStruct);
                Assert.Equal(map1.Size, map2.Size);
                Assert.Equal(map1.ToString(), map2.ToString());
            }

            {
                var map = GCPointerMap.FromInstanceLayout(doubleMixedStructLayout);
                Assert.Equal(10, map.Size);
                Assert.Equal("0100101001", map.ToString());
            }

            {
                var map = GCPointerMap.FromInstanceLayout(explicitlyFarPointer);
                Assert.Equal(117, map.Size);
                Assert.Equal("100000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000001001", map.ToString());
            }

            {
                var map = GCPointerMap.FromInstanceLayout(struct32GcPointers);
                Assert.Equal(32, map.Size);
                Assert.Equal("11111111111111111111111111111111", map.ToString());
            }
        }
Пример #3
0
        /// <summary>
        /// Retrieves size of the GCDesc that describes the instance GC layout for the given type.
        /// </summary>
        public static int GetGCDescSize(TypeDesc type)
        {
            if (type.IsArray)
            {
                TypeDesc elementType = ((ArrayType)type).ElementType;
                if (elementType.IsGCPointer)
                {
                    // For efficiency this is special cased and encoded as one serie.
                    return(3 * type.Context.Target.PointerSize);
                }
                else if (elementType.IsDefType)
                {
                    var defType = (DefType)elementType;
                    if (defType.ContainsGCPointers)
                    {
                        GCPointerMap pointerMap = GCPointerMap.FromInstanceLayout(defType);
                        if (pointerMap.IsAllGCPointers)
                        {
                            // For efficiency this is special cased and encoded as one serie.
                            return(3 * type.Context.Target.PointerSize);
                        }
                        else
                        {
                            int numSeries = pointerMap.NumSeries;
                            Debug.Assert(numSeries > 0);
                            return((numSeries + 2) * type.Context.Target.PointerSize);
                        }
                    }
                }
            }
            else
            {
                var defType = (DefType)type;
                if (defType.ContainsGCPointers)
                {
                    int numSeries = GCPointerMap.FromInstanceLayout(defType).NumSeries;
                    Debug.Assert(numSeries > 0);
                    return((numSeries * 2 + 1) * type.Context.Target.PointerSize);
                }
            }

            return(0);
        }
Пример #4
0
        private static void EncodeTypeLayout(ObjectDataSignatureBuilder dataBuilder, TypeDesc type)
        {
            Debug.Assert(type.IsValueType);
            MetadataType defType = (MetadataType)type;

            int pointerSize = type.Context.Target.PointerSize;
            int size        = defType.InstanceFieldSize.AsInt;
            int alignment   = GetClassAlignmentRequirement(defType);
            ReadyToRunTypeLayoutFlags flags = ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_Alignment | ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_GCLayout;

            if (alignment == pointerSize)
            {
                flags |= ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_Alignment_Native;
            }

            if (!defType.ContainsGCPointers)
            {
                flags |= ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_GCLayout_Empty;
            }

            if (defType.IsHomogeneousAggregate)
            {
                flags |= ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_HFA;
            }

            dataBuilder.EmitUInt((uint)flags);
            dataBuilder.EmitUInt((uint)size);

            if (defType.IsHomogeneousAggregate)
            {
                CorElementType elementType = (defType.ValueTypeShapeCharacteristics & ValueTypeShapeCharacteristics.AggregateMask) switch
                {
                    ValueTypeShapeCharacteristics.Float32Aggregate => CorElementType.ELEMENT_TYPE_R4,
                    ValueTypeShapeCharacteristics.Float64Aggregate => CorElementType.ELEMENT_TYPE_R8,
                    ValueTypeShapeCharacteristics.Vector64Aggregate => CorElementType.ELEMENT_TYPE_R8,
                    // See MethodTable::GetHFAType
                    ValueTypeShapeCharacteristics.Vector128Aggregate => CorElementType.ELEMENT_TYPE_VALUETYPE,
                    _ => CorElementType.Invalid
                };
                dataBuilder.EmitUInt((uint)elementType);
            }

            if (alignment != pointerSize)
            {
                dataBuilder.EmitUInt((uint)alignment);
            }

            if (defType.ContainsGCPointers)
            {
                // Encode the GC pointer map
                GCPointerMap gcMap = GCPointerMap.FromInstanceLayout(defType);

                byte[] encodedGCRefMap = new byte[(size / pointerSize + 7) / 8];
                int    bitIndex        = 0;
                foreach (bool bit in gcMap)
                {
                    if (bit)
                    {
                        encodedGCRefMap[bitIndex / 8] |= (byte)(1 << (bitIndex & 7));
                    }

                    ++bitIndex;
                }

                dataBuilder.EmitBytes(encodedGCRefMap);
            }
        }
Пример #5
0
        private static void EncodeTypeLayout(ObjectDataSignatureBuilder dataBuilder, TypeDesc type)
        {
            Debug.Assert(type.IsValueType);
            MetadataType defType = (MetadataType)type;

            int pointerSize = type.Context.Target.PointerSize;
            int size        = defType.InstanceFieldSize.AsInt;
            int alignment   = GetClassAlignmentRequirement(defType);
            ReadyToRunTypeLayoutFlags flags = ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_Alignment | ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_GCLayout;

            if (alignment == pointerSize)
            {
                flags |= ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_Alignment_Native;
            }

            if (!defType.ContainsGCPointers)
            {
                flags |= ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_GCLayout_Empty;
            }

            if (defType.IsHfa)
            {
                flags |= ReadyToRunTypeLayoutFlags.READYTORUN_LAYOUT_HFA;
            }

            dataBuilder.EmitUInt((uint)flags);
            dataBuilder.EmitUInt((uint)size);

            if (defType.IsHfa)
            {
                switch (defType.HfaElementType.Category)
                {
                case TypeFlags.Single:
                    dataBuilder.EmitUInt((uint)CorElementType.ELEMENT_TYPE_R4);
                    break;

                case TypeFlags.Double:
                    dataBuilder.EmitUInt((uint)CorElementType.ELEMENT_TYPE_R8);
                    break;
                }
            }

            if (alignment != pointerSize)
            {
                dataBuilder.EmitUInt((uint)alignment);
            }

            if (defType.ContainsGCPointers)
            {
                // Encode the GC pointer map
                GCPointerMap gcMap = GCPointerMap.FromInstanceLayout(defType);

                byte[] encodedGCRefMap = new byte[(size / pointerSize + 7) / 8];
                int    bitIndex        = 0;
                foreach (bool bit in gcMap)
                {
                    if (bit)
                    {
                        encodedGCRefMap[bitIndex / 8] |= (byte)(1 << (bitIndex & 7));
                    }

                    ++bitIndex;
                }

                dataBuilder.EmitBytes(encodedGCRefMap);
            }
        }