int first_set = -1, num_set = 0, last_set = -1, i;
mword desc = 0;
size_t stored_size = obj_size;
+
+ stored_size += SGEN_ALLOC_ALIGN - 1;
+ stored_size &= ~(SGEN_ALLOC_ALIGN - 1);
+
for (i = 0; i < numbits; ++i) {
if (bitmap [i / GC_BITS_PER_WORD] & ((gsize)1 << (i % GC_BITS_PER_WORD))) {
if (first_set < 0)
num_set++;
}
}
- /*
- * We don't encode the size of types that don't contain
- * references because they might not be aligned, i.e. the
- * bottom two bits might be set, which would clash with the
- * bits we need to encode the descriptor type. Since we don't
- * use the encoded size to skip objects, other than for
- * processing remsets, in which case only the positions of
- * references are relevant, this is not a problem.
- */
- if (first_set < 0)
- return (void*)DESC_TYPE_RUN_LENGTH;
- g_assert (!(stored_size & 0x3));
- if (stored_size <= SGEN_MAX_SMALL_OBJ_SIZE) {
+
+ if (first_set < 0) {
+ DEBUG (6, fprintf (gc_debug_file, "Ptrfree descriptor %p, size: %zd\n", (void*)desc, stored_size));
+ if (stored_size <= MAX_RUNLEN_OBJECT_SIZE)
+ return (void*)(DESC_TYPE_RUN_LENGTH | stored_size);
+ return (void*)DESC_TYPE_COMPLEX_PTRFREE;
+ }
+
+ g_assert (!(stored_size & 0x7));
+
+ if (stored_size <= MAX_RUNLEN_OBJECT_SIZE) {
/* check run-length encoding first: one byte offset, one byte number of pointers
* on 64 bit archs, we can have 3 runs, just one on 32.
* It may be better to use nibbles.
*/
- if (first_set < 0) {
- desc = DESC_TYPE_RUN_LENGTH | (stored_size << 1);
- DEBUG (6, fprintf (gc_debug_file, "Ptrfree descriptor %p, size: %zd\n", (void*)desc, stored_size));
- return (void*) desc;
- } else if (first_set < 256 && num_set < 256 && (first_set + num_set == last_set + 1)) {
+ if (first_set < 256 && num_set < 256 && (first_set + num_set == last_set + 1)) {
desc = DESC_TYPE_RUN_LENGTH | (stored_size << 1) | (first_set << 16) | (num_set << 24);
DEBUG (6, fprintf (gc_debug_file, "Runlen descriptor %p, size: %zd, first set: %d, num set: %d\n", (void*)desc, stored_size, first_set, num_set));
return (void*) desc;
mono_gc_make_descr_for_array (int vector, gsize *elem_bitmap, int numbits, size_t elem_size)
{
int first_set = -1, num_set = 0, last_set = -1, i;
- mword desc = vector? DESC_TYPE_VECTOR: DESC_TYPE_ARRAY;
+ mword desc = DESC_TYPE_VECTOR | (vector ? VECTOR_KIND_SZARRAY : VECTOR_KIND_ARRAY);
for (i = 0; i < numbits; ++i) {
if (elem_bitmap [i / GC_BITS_PER_WORD] & ((gsize)1 << (i % GC_BITS_PER_WORD))) {
if (first_set < 0)
num_set++;
}
}
- /* See comment at the definition of DESC_TYPE_RUN_LENGTH. */
- if (first_set < 0)
- return (void*)DESC_TYPE_RUN_LENGTH;
+
+ if (first_set < 0) {
+ if (elem_size <= MAX_ELEMENT_SIZE)
+ return (void*)(desc | VECTOR_SUBTYPE_PTRFREE | (elem_size << VECTOR_ELSIZE_SHIFT));
+ return (void*)DESC_TYPE_COMPLEX_PTRFREE;
+ }
+
if (elem_size <= MAX_ELEMENT_SIZE) {
desc |= elem_size << VECTOR_ELSIZE_SHIFT;
if (!num_set) {
*/
#define OBJECT_HEADER_WORDS (sizeof(MonoObject)/sizeof(gpointer))
#define LOW_TYPE_BITS 3
+#define MAX_RUNLEN_OBJECT_SIZE 0xFFFF
#define SMALL_BITMAP_SHIFT 16
#define SMALL_BITMAP_SIZE (GC_BITS_PER_WORD - SMALL_BITMAP_SHIFT)
#define VECTOR_INFO_SHIFT 14
+#define VECTOR_KIND_SHIFT 13
#define VECTOR_ELSIZE_SHIFT 3
#define LARGE_BITMAP_SIZE (GC_BITS_PER_WORD - LOW_TYPE_BITS)
#define MAX_ELEMENT_SIZE 0x3ff
#define VECTOR_SUBTYPE_RUN_LEN (DESC_TYPE_V_RUN_LEN << VECTOR_INFO_SHIFT)
#define VECTOR_SUBTYPE_BITMAP (DESC_TYPE_V_BITMAP << VECTOR_INFO_SHIFT)
+#define VECTOR_KIND_SZARRAY (DESC_TYPE_V_SZARRAY << VECTOR_KIND_SHIFT)
+#define VECTOR_KIND_ARRAY (DESC_TYPE_V_ARRAY << VECTOR_KIND_SHIFT)
+
/* objects are aligned to 8 bytes boundaries
* A descriptor is a pointer in MonoVTable, so 32 or 64 bits of size.
* The low 3 bits define the type of the descriptor. The other bits
* copy_object_no_checks(), without having to fetch the
* object's class.
*/
- DESC_TYPE_RUN_LENGTH = 1, /* 15 bits aligned byte size | 1-3 (offset, numptr) bytes tuples */
- DESC_TYPE_SMALL_BITMAP, /* 15 bits aligned byte size | 16-48 bit bitmap */
+ DESC_TYPE_RUN_LENGTH = 1, /* 16 bits aligned byte size | 1-3 (offset, numptr) bytes tuples */
+ DESC_TYPE_SMALL_BITMAP, /* 16 bits aligned byte size | 16-48 bit bitmap */
DESC_TYPE_COMPLEX, /* index for bitmap into complex_descriptors */
- DESC_TYPE_VECTOR, /* 10 bits element size | 1 bit array | 2 bits desc | element desc */
- DESC_TYPE_ARRAY, /* 10 bits element size | 1 bit array | 2 bits desc | element desc */
+ DESC_TYPE_VECTOR, /* 10 bits element size | 1 bit kind | 2 bits desc | element desc */
DESC_TYPE_LARGE_BITMAP, /* | 29-61 bitmap bits */
DESC_TYPE_COMPLEX_ARR, /* index for bitmap into complex_descriptors */
+ DESC_TYPE_COMPLEX_PTRFREE, /*Nothing, used to encode large ptr objects. */
+ /* values for array kind */
+ DESC_TYPE_V_SZARRAY = 0, /*vector with no bounds data */
+ DESC_TYPE_V_ARRAY = 1, /* array with bounds data */
/* subtypes for arrays and vectors */
DESC_TYPE_V_PTRFREE = 0,/* there are no refs: keep first so it has a zero value */
DESC_TYPE_V_REFS, /* all the array elements are refs */
MonoGCRootMarkFunc mono_sgen_get_user_descriptor_func (mword desc) MONO_INTERNAL;
-#define SGEN_VTABLE_HAS_REFERENCES(vt) (((MonoVTable*)(vt))->gc_descr != (void*)DESC_TYPE_RUN_LENGTH)
-#define SGEN_CLASS_HAS_REFERENCES(c) ((c)->gc_descr != (void*)DESC_TYPE_RUN_LENGTH)
+static inline gboolean
+mono_sgen_gc_descr_has_references (mword desc)
+{
+ /*Both string and fixed size objects are encoded using a zero run RUN_LEN*/
+ if ((desc & 0xffff0007) == DESC_TYPE_RUN_LENGTH)
+ return FALSE;
+
+ /*The array is ptr-free*/
+ if ((desc & 0xC007) == (DESC_TYPE_VECTOR | VECTOR_SUBTYPE_PTRFREE))
+ return FALSE;
+
+ if ((desc & 0x7) == DESC_TYPE_COMPLEX_PTRFREE)
+ return FALSE;
+
+ return TRUE;
+}
+
+#define SGEN_VTABLE_HAS_REFERENCES(vt) (mono_sgen_gc_descr_has_references ((mword)((MonoVTable*)(vt))->gc_descr))
+#define SGEN_CLASS_HAS_REFERENCES(c) (mono_sgen_gc_descr_has_references ((mword)(c)->gc_descr))
/* helper macros to scan and traverse objects, macros because we resue them in many functions */
#define OBJ_RUN_LEN_SIZE(size,desc,obj) do { \
- (size) = ((desc) & 0xfff8) >> 1; \
+ (size) = ((desc) & 0xfff8); \
} while (0)
#define OBJ_BITMAP_SIZE(size,desc,obj) do { \
- (size) = ((desc) & 0xfff8 >> 1); \
+ (size) = ((desc) & 0xfff8); \
} while (0)
#ifdef __GNUC__
if (!array_fill_vtable) {
static MonoClass klass;
static MonoVTable vtable;
+ gsize bmap;
MonoDomain *domain = mono_get_root_domain ();
g_assert (domain);
klass.name = "array_filler_type";
vtable.klass = &klass;
- vtable.gc_descr = NULL;
+ bmap = 0;
+ vtable.gc_descr = mono_gc_make_descr_for_array (TRUE, &bmap, 0, 1);
vtable.size_descr = mono_gc_compute_size_descr (&klass);
vtable.rank = 1;
SCAN_OBJECT_ACTION;
#undef SCAN
break;
- case DESC_TYPE_ARRAY:
case DESC_TYPE_VECTOR:
#define SCAN OBJ_VECTOR_FOREACH_PTR (desc, start)
#ifndef SCAN_OBJECT_NOSCAN
#undef SCAN
break;
#endif
+ case DESC_TYPE_COMPLEX_PTRFREE:
+ /*Nothing to do*/
+ SCAN_OBJECT_ACTION;
+ break;
default:
g_assert_not_reached ();
}