コード例 #1
0
    public void Alloc()
    {
        var o = GCHeap.AllocObject <List <int> >();

        o.Add(1);

        Assert.True(o.Count == 1);
        Assert.True(GCHeap.IsHeapPointer(o));
    }
コード例 #2
0
    public unsafe void GCTest()
    {
        var s   = "bar";
        var ptr = Mem.AddressOfHeap(s).ToPointer();

        Assert.True(GCHeap.IsHeapPointer(ptr));

        var p = new Point();

        Assert.False(GCHeap.IsHeapPointer(&p));

        Assert.True(GCHeap.IsHeapPointer(s));
    }
コード例 #3
0
ファイル: GC.cs プロジェクト: carriercomm/Proton-1
		private static void DeallocateHeap(GCHeap* pHeap)
		{
			// TODO: Thread-safety
			if (pHeap->Prev == null) HeapFirst = pHeap->Next;
			else pHeap->Prev->Next = pHeap->Next;
			if (pHeap->Next == null) HeapLast = pHeap->Prev;
			else pHeap->Next->Prev = pHeap->Prev;
			HeapAllocator.DeallocateHeap(pHeap);
		}
コード例 #4
0
        public GCHeapGraph(GCHeap heap)
            : base((int)heap.NumberOfObjects)
        {
            // TODO is basically nodes that have not had 'SetNode' done to them.  Thus the node index has been
            // allocated, but we have not processed the defintion of the node.
            // This list should NEVER contain duplicates (you should test if you already processed the node before
            // adding to this queue.
            Queue <NodeIndex> toDo = new Queue <NodeIndex>();

            // Create the root node.
            var root = new MemoryNodeBuilder(this, "[root]");

            // Create categories for the roots.
            var nodeForKind = new MemoryNodeBuilder[((int)GCRootKind.Max) + 1];

            var otherRoots = root.FindOrCreateChild("[other roots]");

            nodeForKind[(int)GCRootKind.LocalVar] = otherRoots.FindOrCreateChild("[unknown local vars]");
            for (int i = 0; i < nodeForKind.Length; i++)
            {
                if (nodeForKind[i] == null)
                {
                    nodeForKind[i] = otherRoots.FindOrCreateChild("[" + ((GCRootKind)i).ToString().ToLower() + " handles]");
                }
            }
            var unreachable = root.FindOrCreateChild("[unreachable but not yet collected]");

            foreach (var gcRoot in heap.Roots)
            {
                if (gcRoot.HeapReference == 0)
                {
                    continue;
                }

                // TODO FIX NOW condition should not be needed, should be able to assert it.
                if (!heap.IsInHeap(gcRoot.HeapReference))
                {
                    continue;
                }
                Debug.Assert(heap.IsInHeap(gcRoot.HeapReference));

                // Make a node for it, and notice if the root is already in the heap.
                var lastLimit  = NodeIndexLimit;
                var newNodeIdx = GetNodeIndex(gcRoot.HeapReference);

                var nodeForGcRoot = nodeForKind[(int)gcRoot.Kind];
                if (gcRoot.Type != null)
                {
                    var prefix = "other";
                    if (gcRoot.Kind == GCRootKind.StaticVar)
                    {
                        prefix = "static";
                    }
                    else if (gcRoot.Kind == GCRootKind.LocalVar)
                    {
                        prefix = "local";
                    }
                    var appDomainNode = root.FindOrCreateChild("[appdomain " + gcRoot.AppDomainName + "]");
                    var varKindNode   = appDomainNode.FindOrCreateChild("[" + prefix + " vars]");
                    var moduleName    = Path.GetFileNameWithoutExtension(gcRoot.Type.ModuleFilePath);
                    var moduleNode    = varKindNode.FindOrCreateChild("[" + prefix + " vars " + moduleName + "]");
                    var typeNode      = moduleNode.FindOrCreateChild("[" + prefix + " vars " + gcRoot.Type.Name + "]");
                    var name          = gcRoot.Type.Name + "+" + gcRoot.Name + " [" + prefix + " var]";
                    nodeForGcRoot = typeNode.FindOrCreateChild(name, gcRoot.Type.ModuleFilePath);

                    // TODO REMOVE
                    // if (nodeForGcRoot.Size == 0)
                    //    nodeForGcRoot.Size = 4;
                }

                // Give the user a bit more information about runtime internal handles
                if (gcRoot.Kind == GCRootKind.Pinning)
                {
                    var pinnedType = heap.GetObjectType(gcRoot.HeapReference);
                    if (pinnedType.Name == "System.Object []")
                    {
                        // Traverse pinned object arrays a bit 'manually' here so we tell the users they are likely handles.
                        var handleArray = new MemoryNodeBuilder(
                            this, "[likely runtime object array handle table]", pinnedType.ModuleFilePath, newNodeIdx);
                        handleArray.Size = pinnedType.GetSize(gcRoot.HeapReference);
                        nodeForGcRoot.AddChild(handleArray);

                        pinnedType.EnumerateRefsOfObjectCarefully(gcRoot.HeapReference, delegate(Address childRef, int childFieldOffset)
                        {
                            // Poor man's visited bit.  If we did not need to add a node, then we have visited it.
                            var childLastLimit = NodeIndexLimit;
                            var childNodeIdx   = GetNodeIndex(childRef);
                            if (childNodeIdx < childLastLimit)       // Already visited, simply add the child and move one
                            {
                                handleArray.AddChild(childNodeIdx);
                                return;
                            }

                            var childType = heap.GetObjectType(childRef);
                            if (childType.Name == "System.String")
                            {
                                // TODO FIX NOW:  Only want to morph the name if something else does not point at it.
                                var literal = new MemoryNodeBuilder(
                                    this, "[likely string literal]", childType.ModuleFilePath, childNodeIdx);
                                literal.Size = childType.GetSize(childRef);
                                handleArray.AddChild(literal);
                            }
                            else
                            {
                                handleArray.AddChild(childNodeIdx);
                                toDo.Enqueue(childNodeIdx);
                            }
                        });
                        continue;       // we are done processing this node.
                    }
                }

                nodeForGcRoot.AddChild(newNodeIdx);
                if (newNodeIdx >= lastLimit)      // have not been visited.
                {
                    toDo.Enqueue(newNodeIdx);
                }
            }

            root.AllocateTypeIndexes();

            // Create the necessary types.
            int memoryTypesStart = (int)NodeTypeIndexLimit;

            foreach (var type in heap.Types)
            {
                NodeTypeIndex nodeType = CreateType(type.Name, type.ModuleFilePath);
                Debug.Assert((int)nodeType == (int)type.Index + memoryTypesStart);
            }

            var children = new GrowableArray <NodeIndex>();

            while (toDo.Count > 0)
            {
                var nodeIndex = toDo.Dequeue();
                var objRef    = GetAddress(nodeIndex);

                children.Clear();
                GCHeapType objType = heap.GetObjectType(objRef);
                objType.EnumerateRefsOfObjectCarefully(objRef, delegate(Address childRef, int childFieldOffset)
                {
                    Debug.Assert(heap.IsInHeap(childRef));
                    var lastLimit    = NodeIndexLimit;
                    var childNodeIdx = GetNodeIndex(childRef);
                    children.Add(childNodeIdx);

                    // Poor man's visited bit.  If the index we just asked for is a new node, put it in the work queue
                    if (childNodeIdx >= lastLimit)
                    {
                        toDo.Enqueue(childNodeIdx);
                    }
                });

                int objSize = objType.GetSize(objRef);
                Debug.Assert(objSize > 0);
                SetNode(nodeIndex, (NodeTypeIndex)((int)objType.Index + memoryTypesStart), objSize, children);
            }

            long unreachableSize = (heap.TotalSize - TotalSize);

            unreachable.Size = (int)unreachableSize;
            if (unreachable.Size != unreachableSize)
            {
                unreachable.Size = int.MaxValue;        // TODO not correct on overflow
            }
            // We are done!
            RootIndex = root.Build();
            AllowReading();
        }
コード例 #5
0
    public static string Dump <T>(ref T value, DumpOptions options, InspectorOptions options2)
    {
        switch (options)
        {
        case DumpOptions.Info:
            //

            var addrTable = new ConsoleTable("Addresses", "");

            var addr = Mem.AddressOf(ref value);
            addrTable.AddRow("Address", addr);

            if (Mem.TryGetAddressOfHeap(value, out var heap))
            {
                addrTable.AddRow("Address (heap)", heap);
            }

            addrTable.Write(ConsoleTableFormat.Minimal);

            //

            var infoTable = new ConsoleTable("Sizes", "");

            infoTable.AddRow("Intrinsic", Mem.SizeOf <T>());
            infoTable.AddRow("Auto", Mem.SizeOf(value, SizeOfOptions.Auto));

            infoTable.Write(ConsoleTableFormat.Minimal);

            //

            var propTable = new ConsoleTable("Runtime info", "");

            propTable.AddRow("Pinnable", RuntimeProperties.IsPinnable(value));
            propTable.AddRow("Blittable", RuntimeProperties.IsBlittable(value));
            propTable.AddRow("Boxed", RuntimeProperties.IsBoxed(value));
            propTable.AddRow("Nil", RuntimeProperties.IsDefault(value));
            propTable.AddRow("Uninitialized", RuntimeProperties.IsNullMemory(value));


            propTable.AddRow("In GC heap", GCHeap.IsHeapPointer(Mem.AddressOfData(ref value)));

            return(propTable.ToMinimalString());

        case DumpOptions.Sizes:
            var layoutTable = new ConsoleTable("Size Type", "Value");

            var options1 = Enum.GetValues <SizeOfOptions>().ToList();

            options1.Remove(SizeOfOptions.Heap);


            foreach (var option in options1)
            {
                var sizeOf = Mem.SizeOf(value, option);

                if (sizeOf == Native.INVALID)
                {
                    continue;
                }

                layoutTable.AddRow(Enum.GetName(option), sizeOf);
            }

            var mt = value.GetMetaType();

            if (!mt.RuntimeType.IsValueType)
            {
                layoutTable.AddRow(nameof(SizeOfOptions.Heap), Mem.SizeOf(value, SizeOfOptions.Heap));
            }

            return(layoutTable.ToString());

        case DumpOptions.Layout:
            var layoutTable1 = new ConsoleTable();

            var flags = EnumHelper.GetSetFlags(options2);

            if (options2 == InspectorOptions.All)
            {
                flags.Remove(InspectorOptions.All);
            }

            layoutTable1.AddColumn(flags.Select(Enum.GetName));


            // Rewrite options

            options2 = default;

            foreach (var flag in flags)
            {
                options2 |= flag;
            }

            var mt1    = value.GetMetaType();
            var fields = mt1.Fields.Where(x => !x.IsStatic);

            int s = Mem.SizeOf(value, SizeOfOptions.Auto);
            var p = Mem.AddressOf(ref value);


            foreach (var metaField in fields)
            {
                var rowValues = new List <object>();


                if (options2.HasFlag(InspectorOptions.Offset))
                {
                    rowValues.Add($"{metaField.Offset:X}");
                }

                if (options2.HasFlag(InspectorOptions.Size))
                {
                    rowValues.Add(metaField.Size);
                }

                if (options2.HasFlag(InspectorOptions.Type))
                {
                    rowValues.Add(metaField.FieldType.Name);
                }

                if (options2.HasFlag(InspectorOptions.Name))
                {
                    rowValues.Add(metaField.Name);
                }

                if (options2.HasFlag(InspectorOptions.Address))
                {
                    var addr1 = Mem.AddressOfData(ref value) + metaField.Offset;
                    rowValues.Add(addr1.ToString());
                }

                if (options2.HasFlag(InspectorOptions.Value))
                {
                    object fieldVal;

                    if (!mt1.RuntimeType.IsConstructedGenericType)
                    {
                        fieldVal = metaField.Info.GetValue(value);
                    }
                    else
                    {
                        fieldVal = "?";
                    }

                    rowValues.Add($"{fieldVal}");
                }

                layoutTable1.AddRow(rowValues.ToArray());
            }


            if (value is string str)
            {
                for (int i = 1; i < str.Length; i++)
                {
                    char c          = str[i];
                    var  rowValues  = new List <object>();
                    int  offsetBase = (i * sizeof(char));

                    if (options2.HasFlag(InspectorOptions.Offset))
                    {
                        rowValues.Add($"{offsetBase + RuntimeProperties.StringOverhead - sizeof(char):X}");
                    }

                    if (options2.HasFlag(InspectorOptions.Size))
                    {
                        rowValues.Add(sizeof(char));
                    }

                    if (options2.HasFlag(InspectorOptions.Type))
                    {
                        rowValues.Add(nameof(Char));
                    }

                    if (options2.HasFlag(InspectorOptions.Name))
                    {
                        rowValues.Add($"Char #{i + 1}");
                    }

                    if (options2.HasFlag(InspectorOptions.Address))
                    {
                        if (Mem.TryGetAddressOfHeap(value, OffsetOptions.StringData, out var addr2))
                        {
                            addr2 += offsetBase;
                            rowValues.Add(addr2.ToString());
                        }
                    }

                    if (options2.HasFlag(InspectorOptions.Value))
                    {
                        rowValues.Add($"{c}");
                    }

                    layoutTable1.AddRow(rowValues.ToArray());
                }
            }


            return(layoutTable1.ToString());

        default:
            throw new ArgumentOutOfRangeException(nameof(options));
        }
    }
コード例 #6
0
ファイル: Benchmarks.cs プロジェクト: Decimation/Novus
 public bool test1()
 {
     return(GCHeap.IsHeapPointer("foo"));
 }