/*
+ * sgen-descriptor.h: GC descriptors describe object layout.
+
* Copyright 2001-2003 Ximian, Inc
* Copyright 2003-2010 Novell, Inc.
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2012 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MONO_SGEN_DESCRIPTOR_H__
#define __MONO_SGEN_DESCRIPTOR_H__
*/
#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_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 */
ROOT_DESC_TYPE_SHIFT = 3,
};
-enum {
- SIZE_DESC_FIXED_SIZE = 1, /* 30 bits size */
- SIZE_DESC_STRING = 2, /* nothing */
- SIZE_DESC_ARRAY = 3, /* 30 bits element size */
- SIZE_DESC_TYPE_SHIFT = 2,
- SIZE_DESC_TYPE_MASK = 0x3,
-};
+gsize* sgen_get_complex_descriptor (mword desc) MONO_INTERNAL;
+void* sgen_get_complex_descriptor_bitmap (mword desc) MONO_INTERNAL;
+MonoGCRootMarkFunc sgen_get_user_descriptor_func (mword desc) MONO_INTERNAL;
-gsize* mono_sgen_get_complex_descriptor (mword desc) MONO_INTERNAL;
-void* mono_sgen_get_complex_descriptor_bitmap (mword desc) MONO_INTERNAL;
-MonoGCRootMarkFunc mono_sgen_get_user_descriptor_func (mword desc) MONO_INTERNAL;
+static inline gboolean
+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;
-#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)
+ /*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) (sgen_gc_descr_has_references ((mword)((MonoVTable*)(vt))->gc_descr))
+#define SGEN_CLASS_HAS_REFERENCES(c) (sgen_gc_descr_has_references ((mword)(c)->gc_descr))
+#define SGEN_OBJECT_HAS_REFERENCES(o) (SGEN_VTABLE_HAS_REFERENCES (SGEN_LOAD_VTABLE ((o))))
/* 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__
#define PREFETCH(addr)
#endif
+#if defined(__GNUC__) && SIZEOF_VOID_P==4
+#define GNUC_BUILTIN_CTZ(bmap) __builtin_ctz(bmap)
+#elif defined(__GNUC__) && SIZEOF_VOID_P==8
+#define GNUC_BUILTIN_CTZ(bmap) __builtin_ctzl(bmap)
+#endif
+
/* code using these macros must define a HANDLE_PTR(ptr) macro that does the work */
#define OBJ_RUN_LEN_FOREACH_PTR(desc,obj) do { \
if ((desc) & 0xffff0000) { \
void **_objptr = (void**)(obj); \
_objptr += ((desc) >> 16) & 0xff; \
_objptr_end = _objptr + (((desc) >> 24) & 0xff); \
+ HANDLE_PTR (_objptr, (obj)); \
+ _objptr ++; \
while (_objptr < _objptr_end) { \
HANDLE_PTR (_objptr, (obj)); \
_objptr++; \
} \
} while (0)
+#if defined(__GNUC__)
+#define OBJ_BITMAP_FOREACH_PTR(desc,obj) do { \
+ /* there are pointers */ \
+ void **_objptr = (void**)(obj); \
+ gsize _bmap = (desc) >> 16; \
+ _objptr += OBJECT_HEADER_WORDS; \
+ { \
+ int _index = GNUC_BUILTIN_CTZ (_bmap); \
+ _objptr += _index; \
+ _bmap >>= (_index + 1); \
+ HANDLE_PTR (_objptr, (obj)); \
+ _objptr ++; \
+ } \
+ while (_bmap) { \
+ int _index = GNUC_BUILTIN_CTZ (_bmap); \
+ _objptr += _index; \
+ _bmap >>= (_index + 1); \
+ HANDLE_PTR (_objptr, (obj)); \
+ _objptr ++; \
+ } \
+ } while (0)
+#else
+#define OBJ_BITMAP_FOREACH_PTR(desc,obj) do { \
+ /* there are pointers */ \
+ void **_objptr = (void**)(obj); \
+ gsize _bmap = (desc) >> 16; \
+ _objptr += OBJECT_HEADER_WORDS; \
+ while (_bmap) { \
+ if ((_bmap & 1)) { \
+ HANDLE_PTR (_objptr, (obj)); \
+ } \
+ _bmap >>= 1; \
+ ++_objptr; \
+ } \
+ } while (0)
+#endif
+
/* a bitmap desc means that there are pointer references or we'd have
* choosen run-length, instead: add an assert to check.
*/
#define OBJ_COMPLEX_FOREACH_PTR(vt,obj) do { \
/* there are pointers */ \
void **_objptr = (void**)(obj); \
- gsize *bitmap_data = mono_sgen_get_complex_descriptor ((desc)); \
+ gsize *bitmap_data = sgen_get_complex_descriptor ((desc)); \
int bwords = (*bitmap_data) - 1; \
void **start_run = _objptr; \
bitmap_data++; \
/* this one is untested */
#define OBJ_COMPLEX_ARR_FOREACH_PTR(vt,obj) do { \
/* there are pointers */ \
- gsize *mbitmap_data = mono_sgen_get_complex_descriptor ((vt)->desc); \
+ gsize *mbitmap_data = sgen_get_complex_descriptor ((vt)->desc); \
int mbwords = (*mbitmap_data++) - 1; \
int el_size = mono_array_element_size (vt->klass); \
char *e_start = (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector); \
} while (0)
-#endif
\ No newline at end of file
+#endif