summaryrefslogtreecommitdiff
path: root/src/gc/gcdesc.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc/gcdesc.h')
-rw-r--r--src/gc/gcdesc.h263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/gc/gcdesc.h b/src/gc/gcdesc.h
new file mode 100644
index 0000000000..7cc132a640
--- /dev/null
+++ b/src/gc/gcdesc.h
@@ -0,0 +1,263 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//
+// GC Object Pointer Location Series Stuff
+//
+
+
+
+#ifndef _GCDESC_H_
+#define _GCDESC_H_
+
+#ifdef BIT64
+typedef uint32_t HALF_SIZE_T;
+#else // BIT64
+typedef uint16_t HALF_SIZE_T;
+#endif
+
+
+typedef size_t *JSlot;
+
+
+//
+// These two classes make up the apparatus with which the object references
+// within an object can be found.
+//
+// CGCDescSeries:
+//
+// The CGCDescSeries class describes a series of object references within an
+// object by describing the size of the series (which has an adjustment which
+// will be explained later) and the starting point of the series.
+//
+// The series size is adjusted when the map is created by subtracting the
+// GetBaseSize() of the object. On retieval of the size the total size
+// of the object is added back. For non-array objects the total object
+// size is equal to the base size, so this returns the same value. For
+// array objects this will yield the size of the data portion of the array.
+// Since arrays containing object references will contain ONLY object references
+// this is a fast way of handling arrays and normal objects without a
+// conditional test
+//
+//
+//
+// CGCDesc:
+//
+// The CGCDesc is a collection of CGCDescSeries objects to describe all the
+// different runs of pointers in a particular object. <TODO> [add more on the strange
+// way the CGCDesc grows backwards in memory behind the MethodTable]
+//</TODO>
+
+struct val_serie_item
+{
+ HALF_SIZE_T nptrs;
+ HALF_SIZE_T skip;
+ void set_val_serie_item (HALF_SIZE_T nptrs, HALF_SIZE_T skip)
+ {
+ this->nptrs = nptrs;
+ this->skip = skip;
+ }
+};
+
+struct val_array_series
+{
+ val_serie_item items[1];
+ size_t m_startOffset;
+ size_t m_count;
+};
+
+typedef DPTR(class CGCDescSeries) PTR_CGCDescSeries;
+typedef DPTR(class MethodTable) PTR_MethodTable;
+class CGCDescSeries
+{
+public:
+ union
+ {
+ size_t seriessize; // adjusted length of series (see above) in bytes
+ val_serie_item val_serie[1]; //coded serie for value class array
+ };
+
+ size_t startoffset;
+
+ size_t GetSeriesCount ()
+ {
+ return seriessize/sizeof(JSlot);
+ }
+
+ void SetSeriesCount (size_t newcount)
+ {
+ seriessize = newcount * sizeof(JSlot);
+ }
+
+ void IncSeriesCount (size_t increment = 1)
+ {
+ seriessize += increment * sizeof(JSlot);
+ }
+
+ size_t GetSeriesSize ()
+ {
+ return seriessize;
+ }
+
+ void SetSeriesSize (size_t newsize)
+ {
+ seriessize = newsize;
+ }
+
+ void SetSeriesValItem (val_serie_item item, int index)
+ {
+ val_serie [index] = item;
+ }
+
+ void SetSeriesOffset (size_t newoffset)
+ {
+ startoffset = newoffset;
+ }
+
+ size_t GetSeriesOffset ()
+ {
+ return startoffset;
+ }
+};
+
+
+
+
+
+typedef DPTR(class CGCDesc) PTR_CGCDesc;
+class CGCDesc
+{
+ // Don't construct me, you have to hand me a ptr to the *top* of my storage in Init.
+ CGCDesc () {}
+
+ //
+ // NOTE: for alignment reasons, NumSeries is stored as a size_t.
+ // This makes everything nicely 8-byte aligned on IA64.
+ //
+public:
+ static size_t ComputeSize (size_t NumSeries)
+ {
+ _ASSERTE (ptrdiff_t(NumSeries) > 0);
+
+ return sizeof(size_t) + NumSeries*sizeof(CGCDescSeries);
+ }
+
+ // For value type array
+ static size_t ComputeSizeRepeating (size_t NumSeries)
+ {
+ _ASSERTE (ptrdiff_t(NumSeries) > 0);
+
+ return sizeof(size_t) + sizeof(CGCDescSeries) +
+ (NumSeries-1)*sizeof(val_serie_item);
+ }
+
+#ifndef DACCESS_COMPILE
+ static void Init (void* mem, size_t NumSeries)
+ {
+ *((size_t*)mem-1) = NumSeries;
+ }
+
+ static void InitValueClassSeries (void* mem, size_t NumSeries)
+ {
+ *((ptrdiff_t*)mem-1) = -((ptrdiff_t)NumSeries);
+ }
+#endif
+
+ static PTR_CGCDesc GetCGCDescFromMT (MethodTable * pMT)
+ {
+ // If it doesn't contain pointers, there isn't a GCDesc
+ PTR_MethodTable mt(pMT);
+
+ _ASSERTE(mt->ContainsPointersOrCollectible());
+
+ return PTR_CGCDesc(mt);
+ }
+
+ size_t GetNumSeries ()
+ {
+ return *(PTR_size_t(PTR_CGCDesc(this))-1);
+ }
+
+ // Returns lowest series in memory.
+ // Cannot be used for valuetype arrays
+ PTR_CGCDescSeries GetLowestSeries ()
+ {
+ _ASSERTE (ptrdiff_t(GetNumSeries()) > 0);
+ return PTR_CGCDescSeries(PTR_uint8_t(PTR_CGCDesc(this))
+ - ComputeSize(GetNumSeries()));
+ }
+
+ // Returns highest series in memory.
+ PTR_CGCDescSeries GetHighestSeries ()
+ {
+ return PTR_CGCDescSeries(PTR_size_t(PTR_CGCDesc(this))-1)-1;
+ }
+
+ // Returns number of immediate pointers this object has.
+ // size is only used if you have an array of value types.
+#ifndef DACCESS_COMPILE
+ static size_t GetNumPointers (MethodTable* pMT, size_t ObjectSize, size_t NumComponents)
+ {
+ size_t NumOfPointers = 0;
+ CGCDesc* map = GetCGCDescFromMT(pMT);
+ CGCDescSeries* cur = map->GetHighestSeries();
+ ptrdiff_t cnt = (ptrdiff_t) map->GetNumSeries();
+
+ if (cnt > 0)
+ {
+ CGCDescSeries* last = map->GetLowestSeries();
+ while (cur >= last)
+ {
+ NumOfPointers += (cur->GetSeriesSize() + ObjectSize) / sizeof(JSlot);
+ cur--;
+ }
+ }
+ else
+ {
+ /* Handle the repeating case - array of valuetypes */
+ for (ptrdiff_t __i = 0; __i > cnt; __i--)
+ {
+ NumOfPointers += cur->val_serie[__i].nptrs;
+ }
+
+ NumOfPointers *= NumComponents;
+ }
+
+ return NumOfPointers;
+ }
+#endif
+
+ // Size of the entire slot map.
+ size_t GetSize ()
+ {
+ ptrdiff_t numSeries = (ptrdiff_t) GetNumSeries();
+ if (numSeries < 0)
+ {
+ return ComputeSizeRepeating(-numSeries);
+ }
+ else
+ {
+ return ComputeSize(numSeries);
+ }
+ }
+
+ uint8_t *GetStartOfGCData()
+ {
+ return ((uint8_t *)this) - GetSize();
+ }
+
+private:
+
+ BOOL IsValueClassSeries()
+ {
+ return ((ptrdiff_t) GetNumSeries()) < 0;
+ }
+
+};
+
+#define MAX_SIZE_FOR_VALUECLASS_IN_ARRAY 0xffff
+#define MAX_PTRS_FOR_VALUECLASSS_IN_ARRAY 0xffff
+
+
+#endif // _GCDESC_H_