Beispiel #1
0
        public static void EncodeStandardGCDesc <T>(ref T builder, GCPointerMap map, int size, int delta)
            where T : struct, ITargetBinaryWriter
        {
            Debug.Assert(size >= map.Size);

            int pointerSize = builder.TargetPointerSize;

            int numSeries = 0;

            for (int cellIndex = map.Size - 1; cellIndex >= 0; cellIndex--)
            {
                if (map[cellIndex])
                {
                    numSeries++;

                    int seriesSize = pointerSize;

                    while (cellIndex > 0 && map[cellIndex - 1])
                    {
                        seriesSize += pointerSize;
                        cellIndex--;
                    }

                    builder.EmitNaturalInt(seriesSize - size);
                    builder.EmitNaturalInt(cellIndex * pointerSize + delta);
                }
            }

            Debug.Assert(numSeries > 0);
            builder.EmitNaturalInt(numSeries);
        }
Beispiel #2
0
        public void TestThreadStaticMap()
        {
            MetadataType mixedThreadStaticClass = _testModule.GetType("GCPointerMap", "MixedThreadStaticClass");
            var          map = GCPointerMap.FromThreadStaticLayout(mixedThreadStaticClass);

            Assert.Equal(map.Size, 14);
            Assert.Equal("00010010100110", map.ToString());
        }
        public void TestStaticMap()
        {
            MetadataType mixedStaticClass = _testModule.GetType("GCPointerMap", "MixedStaticClass");
            var          map = GCPointerMap.FromStaticLayout(mixedStaticClass);

            Assert.Equal(12, map.Size);
            Assert.Equal("010100101001", map.ToString());
        }
Beispiel #4
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);
        }
Beispiel #5
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());
            }
        }
Beispiel #6
0
        private static void EncodeArrayGCDesc <T>(ref T builder, GCPointerMap map, int baseSize)
            where T : struct, ITargetBinaryWriter
        {
            // NOTE: This format cannot properly represent element types with sizes >= 64k bytes.
            //       We guard it with an assert, but it is the responsibility of the code using this
            //       to cap array component sizes. EEType only has a UInt16 field for component sizes too.

            int numSeries = 0;
            int leadingNonPointerCount = 0;

            int pointerSize = builder.TargetPointerSize;

            for (int cellIndex = 0; cellIndex < map.Size && !map[cellIndex]; cellIndex++)
            {
                leadingNonPointerCount++;
            }

            int nonPointerCount = leadingNonPointerCount;

            for (int cellIndex = map.Size - 1; cellIndex >= leadingNonPointerCount; cellIndex--)
            {
                if (map[cellIndex])
                {
                    numSeries++;

                    int pointerCount = 1;
                    while (cellIndex > leadingNonPointerCount && map[cellIndex - 1])
                    {
                        cellIndex--;
                        pointerCount++;
                    }

                    Debug.Assert(pointerCount < 64 * 1024);
                    builder.EmitHalfNaturalInt((short)pointerCount);

                    Debug.Assert(nonPointerCount * pointerSize < 64 * 1024);
                    builder.EmitHalfNaturalInt((short)(nonPointerCount * pointerSize));

                    nonPointerCount = 0;
                }
                else
                {
                    nonPointerCount++;
                }
            }

            Debug.Assert(numSeries > 0);
            builder.EmitNaturalInt(baseSize + leadingNonPointerCount * pointerSize);
            builder.EmitNaturalInt(-numSeries);
        }
Beispiel #7
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);
        }
 public GCStaticEETypeNode(TargetDetails target, GCPointerMap gcMap)
 {
     _gcMap  = gcMap;
     _target = target;
 }
Beispiel #9
0
 public ISymbolNode GCStaticEEType(GCPointerMap gcMap)
 {
     return(_GCStaticEETypes.GetOrAdd(gcMap));
 }
Beispiel #10
0
        private ISymbolNode GetGCStaticEETypeNode(NodeFactory factory)
        {
            GCPointerMap map = GCPointerMap.FromStaticLayout(_type);

            return(factory.GCStaticEEType(map));
        }
Beispiel #11
0
 public GCStaticDescNode(MetadataType type, bool isThreadStatic)
 {
     _type           = type;
     _gcMap          = isThreadStatic ? GCPointerMap.FromThreadStaticLayout(type) : GCPointerMap.FromStaticLayout(type);
     _isThreadStatic = isThreadStatic;
 }
Beispiel #12
0
 public GCStaticDescNode(MetadataType type)
 {
     _type  = type;
     _gcMap = GCPointerMap.FromStaticLayout(type);
 }
Beispiel #13
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);
            }
        }
Beispiel #14
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);
            }
        }