Skip to content

Commit

Permalink
Fix issue when SMT Table expands to larger than one page
Browse files Browse the repository at this point in the history
  • Loading branch information
quajak committed Sep 12, 2023
1 parent 8a5a120 commit 9b9f04c
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 144 deletions.
12 changes: 12 additions & 0 deletions Docs/articles/Internals/object.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Object

## Memory Layout

Each object is allocated with a header of three ints. The first int is the type of the object, the second int is the instance type of object (normal, boxed, array etc) and the third is the size in memory.

## Garbage Collector Information

The garbage collector itself also alloctes its own header of 1 int (2 ushort). The first ushort is the allocated size of the object while the second tracks the GC information.
The GC information is made up of a 1bit flag (the lowest bit) used to track if the GC has hit the object during the sweep phase already and the upper 7 bits count how many static references there are to the object.

Combined in memory we have the foramt | ushort: memory size | ushort: gc info | uint: object type | uint: instance type | uint: object size | variable: object data |
5 changes: 3 additions & 2 deletions Tests/Cosmos.TestRunner.Core/Engine.Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private void RunProcess(string aProcess, string aWorkingDirectory, string aArgum
}
else
{
xErrorReceived($"Error invoking '{aProcess}'.");
xErrorReceived($"Error invoking '{aProcess}'.");
}
}
}
Expand Down Expand Up @@ -223,7 +223,8 @@ private void RunIL2CPU(string kernelFileName, string outputFile)
"OutputFilename:" + outputFile,
"EnableLogging:True",
"EmitDebugSymbols:True",
"IgnoreDebugStubAttribute:False"
"IgnoreDebugStubAttribute:False",
"AllowComments:True"
};

xArgs.AddRange(xReferences.Select(r => "References:" + r));
Expand Down
15 changes: 14 additions & 1 deletion Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ public class Kernel : Sys.Kernel

protected override void BeforeRun()
{
Console.WriteLine("Cosmos booted successfully. Starting Type tests now please wait...");
}

private void TestVTablesImpl()
Expand Down Expand Up @@ -212,6 +211,12 @@ public void RealMethodsTest()
Heap.Collect();
nowAllocated = HeapSmall.GetAllocatedObjectCount();
Assert.AreEqual(allocated, nowAllocated, "TestMethod7 does not leak string objects");

allocated = HeapSmall.GetAllocatedObjectCount();
TestMethod8();
Heap.Collect();
nowAllocated = HeapSmall.GetAllocatedObjectCount();
Assert.AreEqual(allocated, nowAllocated, "TestMethod8 does not leak any objects");
}

void TestMethod6()
Expand All @@ -228,6 +233,14 @@ void TestMethod7()
}
}

void TestMethod8()
{
for (int i = 0; i < 100000; i++)
{
new object();
}
}

#endregion

protected override void Run()
Expand Down
86 changes: 48 additions & 38 deletions source/Cosmos.Core/Memory/Heap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,32 +178,37 @@ public static int Collect()

// Small objects
// we go one size at a time
var rootSMTPtr = HeapSmall.SMT->First;
while (rootSMTPtr != null)
SMTPage* SMTPage = HeapSmall.SMT;
while (SMTPage != null)
{
uint size = rootSMTPtr->Size;
uint objectSize = size + HeapSmall.PrefixItemBytes;
uint objectsPerPage = RAT.PageSize / objectSize;
RootSMTBlock* rootSMTPtr = SMTPage->First;
while (rootSMTPtr != null)
{
uint size = rootSMTPtr->Size;
uint objectSize = size + HeapSmall.PrefixItemBytes;
uint objectsPerPage = RAT.PageSize / objectSize;

SMTBlock* smtBlock = rootSMTPtr->First;
SMTBlock* smtBlock = rootSMTPtr->First;

while (smtBlock != null)
{
byte* pagePtr = smtBlock->PagePtr;
for (int i = 0; i < objectsPerPage; i++)
while (smtBlock != null)
{

if (*(ushort*)(pagePtr + i * objectSize + sizeof(ushort)) > 1) // 0 means not found and 1 means marked
// after the start of the object we first have one ushort of object size and then the ushort of gc info so + 2 == sizeof(ushort)
byte* pagePtr = smtBlock->PagePtr;
for (int i = 0; i < objectsPerPage; i++)
{
MarkAndSweepObject(pagePtr + i * objectSize + HeapSmall.PrefixItemBytes);

if (*(ushort*)(pagePtr + i * objectSize + sizeof(ushort)) > 1) // 0 means not found and 1 means marked
// after the start of the object we first have one ushort of object size and then the ushort of gc info so + 2 == sizeof(ushort)
{
MarkAndSweepObject(pagePtr + i * objectSize + HeapSmall.PrefixItemBytes);
}
}

smtBlock = smtBlock->NextBlock;
}

smtBlock = smtBlock->NextBlock;
rootSMTPtr = rootSMTPtr->LargerSize;
}

rootSMTPtr = rootSMTPtr->LargerSize;
SMTPage = SMTPage->Next;
}

// Mark and sweep objects from stack
Expand Down Expand Up @@ -245,37 +250,42 @@ public static int Collect()

// Small objects
// we go one size at a time
rootSMTPtr = HeapSmall.SMT->First;
while (rootSMTPtr != null)
SMTPage = HeapSmall.SMT;
while (SMTPage != null)
{
uint size = rootSMTPtr->Size;
uint objectSize = size + HeapSmall.PrefixItemBytes;
uint objectsPerPage = RAT.PageSize / objectSize;
RootSMTBlock* rootSMTPtr = SMTPage->First;
while (rootSMTPtr != null)
{
uint size = rootSMTPtr->Size;
uint objectSize = size + HeapSmall.PrefixItemBytes;
uint objectsPerPage = RAT.PageSize / objectSize;

SMTBlock* smtBlock = rootSMTPtr->First;
SMTBlock* smtBlock = rootSMTPtr->First;

while (smtBlock != null)
{
byte* pagePtr = smtBlock->PagePtr;
for (int i = 0; i < objectsPerPage; i++)
while (smtBlock != null)
{
if (*(ushort*)(pagePtr + i * objectSize) != 0)
byte* pagePtr = smtBlock->PagePtr;
for (int i = 0; i < objectsPerPage; i++)
{
if (*((ushort*)(pagePtr + i * objectSize) + 1) == 0)
if (*(ushort*)(pagePtr + i * objectSize) != 0)
{
Free(pagePtr + i * objectSize + HeapSmall.PrefixItemBytes);
freed += 1;
}
else
{
*((ushort*)(pagePtr + i * objectSize) + 1) &= (ushort)~ObjectGCStatus.Hit;
if (*((ushort*)(pagePtr + i * objectSize) + 1) == 0)
{
Free(pagePtr + i * objectSize + HeapSmall.PrefixItemBytes);
freed += 1;
}
else
{
*((ushort*)(pagePtr + i * objectSize) + 1) &= (ushort)~ObjectGCStatus.Hit;
}
}
}
smtBlock = smtBlock->NextBlock;
}
smtBlock = smtBlock->NextBlock;
}

rootSMTPtr = rootSMTPtr->LargerSize;
rootSMTPtr = rootSMTPtr->LargerSize;
}
SMTPage = SMTPage->Next;
}

//Enable interrupts back
Expand Down
Loading

0 comments on commit 9b9f04c

Please sign in to comment.