You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -43,7 +43,6 @@ monosgen_sources = \
|
||||
sgen-los.c \
|
||||
sgen-major-copy-object.h \
|
||||
sgen-marksweep-drain-gray-stack.h \
|
||||
sgen-marksweep-scan-object-concurrent.h \
|
||||
sgen-marksweep.c \
|
||||
sgen-memory-governor.c \
|
||||
sgen-memory-governor.h \
|
||||
@@ -55,6 +54,8 @@ monosgen_sources = \
|
||||
sgen-pinning.h \
|
||||
sgen-pointer-queue.c \
|
||||
sgen-pointer-queue.h \
|
||||
sgen-array-list.h \
|
||||
sgen-array-list.c \
|
||||
sgen-protocol-def.h \
|
||||
sgen-protocol.c \
|
||||
sgen-protocol.h \
|
||||
|
||||
@@ -117,6 +117,7 @@ am__objects_1 = libmonosgen_static_la-sgen-alloc.lo \
|
||||
libmonosgen_static_la-sgen-pinning-stats.lo \
|
||||
libmonosgen_static_la-sgen-pinning.lo \
|
||||
libmonosgen_static_la-sgen-pointer-queue.lo \
|
||||
libmonosgen_static_la-sgen-array-list.lo \
|
||||
libmonosgen_static_la-sgen-protocol.lo \
|
||||
libmonosgen_static_la-sgen-qsort.lo \
|
||||
libmonosgen_static_la-sgen-simple-nursery.lo \
|
||||
@@ -150,6 +151,7 @@ am__objects_3 = libmonosgen_la-sgen-alloc.lo \
|
||||
libmonosgen_la-sgen-pinning-stats.lo \
|
||||
libmonosgen_la-sgen-pinning.lo \
|
||||
libmonosgen_la-sgen-pointer-queue.lo \
|
||||
libmonosgen_la-sgen-array-list.lo \
|
||||
libmonosgen_la-sgen-protocol.lo libmonosgen_la-sgen-qsort.lo \
|
||||
libmonosgen_la-sgen-simple-nursery.lo \
|
||||
libmonosgen_la-sgen-split-nursery.lo \
|
||||
@@ -315,8 +317,6 @@ NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OPROFILE_CFLAGS = @OPROFILE_CFLAGS@
|
||||
OPROFILE_LIBS = @OPROFILE_LIBS@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
@@ -457,7 +457,6 @@ monosgen_sources = \
|
||||
sgen-los.c \
|
||||
sgen-major-copy-object.h \
|
||||
sgen-marksweep-drain-gray-stack.h \
|
||||
sgen-marksweep-scan-object-concurrent.h \
|
||||
sgen-marksweep.c \
|
||||
sgen-memory-governor.c \
|
||||
sgen-memory-governor.h \
|
||||
@@ -469,6 +468,8 @@ monosgen_sources = \
|
||||
sgen-pinning.h \
|
||||
sgen-pointer-queue.c \
|
||||
sgen-pointer-queue.h \
|
||||
sgen-array-list.h \
|
||||
sgen-array-list.c \
|
||||
sgen-protocol-def.h \
|
||||
sgen-protocol.c \
|
||||
sgen-protocol.h \
|
||||
@@ -547,6 +548,7 @@ distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_la-sgen-alloc.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_la-sgen-array-list.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_la-sgen-cardtable.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_la-sgen-debug.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_la-sgen-descriptor.Plo@am__quote@
|
||||
@@ -571,6 +573,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_la-sgen-thread-pool.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_la-sgen-workers.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_static_la-sgen-alloc.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_static_la-sgen-array-list.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_static_la-sgen-cardtable.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_static_la-sgen-debug.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmonosgen_static_la-sgen-descriptor.Plo@am__quote@
|
||||
@@ -745,6 +748,13 @@ libmonosgen_static_la-sgen-pointer-queue.lo: sgen-pointer-queue.c
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_static_la_CFLAGS) $(CFLAGS) -c -o libmonosgen_static_la-sgen-pointer-queue.lo `test -f 'sgen-pointer-queue.c' || echo '$(srcdir)/'`sgen-pointer-queue.c
|
||||
|
||||
libmonosgen_static_la-sgen-array-list.lo: sgen-array-list.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_static_la_CFLAGS) $(CFLAGS) -MT libmonosgen_static_la-sgen-array-list.lo -MD -MP -MF $(DEPDIR)/libmonosgen_static_la-sgen-array-list.Tpo -c -o libmonosgen_static_la-sgen-array-list.lo `test -f 'sgen-array-list.c' || echo '$(srcdir)/'`sgen-array-list.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmonosgen_static_la-sgen-array-list.Tpo $(DEPDIR)/libmonosgen_static_la-sgen-array-list.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sgen-array-list.c' object='libmonosgen_static_la-sgen-array-list.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_static_la_CFLAGS) $(CFLAGS) -c -o libmonosgen_static_la-sgen-array-list.lo `test -f 'sgen-array-list.c' || echo '$(srcdir)/'`sgen-array-list.c
|
||||
|
||||
libmonosgen_static_la-sgen-protocol.lo: sgen-protocol.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_static_la_CFLAGS) $(CFLAGS) -MT libmonosgen_static_la-sgen-protocol.lo -MD -MP -MF $(DEPDIR)/libmonosgen_static_la-sgen-protocol.Tpo -c -o libmonosgen_static_la-sgen-protocol.lo `test -f 'sgen-protocol.c' || echo '$(srcdir)/'`sgen-protocol.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmonosgen_static_la-sgen-protocol.Tpo $(DEPDIR)/libmonosgen_static_la-sgen-protocol.Plo
|
||||
@@ -913,6 +923,13 @@ libmonosgen_la-sgen-pointer-queue.lo: sgen-pointer-queue.c
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_la_CFLAGS) $(CFLAGS) -c -o libmonosgen_la-sgen-pointer-queue.lo `test -f 'sgen-pointer-queue.c' || echo '$(srcdir)/'`sgen-pointer-queue.c
|
||||
|
||||
libmonosgen_la-sgen-array-list.lo: sgen-array-list.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_la_CFLAGS) $(CFLAGS) -MT libmonosgen_la-sgen-array-list.lo -MD -MP -MF $(DEPDIR)/libmonosgen_la-sgen-array-list.Tpo -c -o libmonosgen_la-sgen-array-list.lo `test -f 'sgen-array-list.c' || echo '$(srcdir)/'`sgen-array-list.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmonosgen_la-sgen-array-list.Tpo $(DEPDIR)/libmonosgen_la-sgen-array-list.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sgen-array-list.c' object='libmonosgen_la-sgen-array-list.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_la_CFLAGS) $(CFLAGS) -c -o libmonosgen_la-sgen-array-list.lo `test -f 'sgen-array-list.c' || echo '$(srcdir)/'`sgen-array-list.c
|
||||
|
||||
libmonosgen_la-sgen-protocol.lo: sgen-protocol.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmonosgen_la_CFLAGS) $(CFLAGS) -MT libmonosgen_la-sgen-protocol.lo -MD -MP -MF $(DEPDIR)/libmonosgen_la-sgen-protocol.Tpo -c -o libmonosgen_la-sgen-protocol.lo `test -f 'sgen-protocol.c' || echo '$(srcdir)/'`sgen-protocol.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmonosgen_la-sgen-protocol.Tpo $(DEPDIR)/libmonosgen_la-sgen-protocol.Plo
|
||||
|
||||
@@ -3,18 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2015 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
|
||||
#ifndef __MONO_METADATA_GCINTERNALAGNOSTIC_H__
|
||||
|
||||
@@ -10,18 +10,7 @@
|
||||
* Copyright 2011 Xamarin, Inc.
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -79,6 +68,9 @@ static __thread char *tlab_temp_end;
|
||||
static __thread char *tlab_real_end;
|
||||
/* Used by the managed allocator/wbarrier */
|
||||
static __thread char **tlab_next_addr MONO_ATTR_USED;
|
||||
#ifndef SGEN_WITHOUT_MONO
|
||||
static __thread volatile int *in_critical_region_addr MONO_ATTR_USED;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KW_THREAD
|
||||
@@ -101,10 +93,10 @@ alloc_degraded (GCVTable vtable, size_t size, gboolean for_mature)
|
||||
if (!for_mature) {
|
||||
sgen_client_degraded_allocation (size);
|
||||
SGEN_ATOMIC_ADD_P (degraded_mode, size);
|
||||
sgen_ensure_free_space (size);
|
||||
sgen_ensure_free_space (size, GENERATION_OLD);
|
||||
} else {
|
||||
if (sgen_need_major_collection (size))
|
||||
sgen_perform_collection (size, GENERATION_OLD, "mature allocation failure", !for_mature);
|
||||
sgen_perform_collection (size, GENERATION_OLD, "mature allocation failure", !for_mature, TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +164,7 @@ sgen_alloc_obj_nolock (GCVTable vtable, size_t size)
|
||||
|
||||
if (collect_before_allocs) {
|
||||
if (((current_alloc % collect_before_allocs) == 0) && nursery_section) {
|
||||
sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE);
|
||||
sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE, TRUE);
|
||||
if (!degraded_mode && sgen_can_alloc_size (size) && real_size <= SGEN_MAX_SMALL_OBJ_SIZE) {
|
||||
// FIXME:
|
||||
g_assert_not_reached ();
|
||||
@@ -208,11 +200,6 @@ sgen_alloc_obj_nolock (GCVTable vtable, size_t size)
|
||||
if (G_LIKELY (new_next < TLAB_TEMP_END)) {
|
||||
/* Fast path */
|
||||
|
||||
/*
|
||||
* FIXME: We might need a memory barrier here so the change to tlab_next is
|
||||
* visible before the vtable store.
|
||||
*/
|
||||
|
||||
CANARIFY_ALLOC(p,real_size);
|
||||
SGEN_LOG (6, "Allocated object %p, vtable: %p (%s), size: %zd", p, vtable, sgen_client_vtable_get_name (vtable), size);
|
||||
binary_protocol_alloc (p , vtable, size, sgen_client_get_provenance ());
|
||||
@@ -271,7 +258,7 @@ sgen_alloc_obj_nolock (GCVTable vtable, size_t size)
|
||||
* always loop we will loop endlessly in the case of
|
||||
* OOM).
|
||||
*/
|
||||
sgen_ensure_free_space (real_size);
|
||||
sgen_ensure_free_space (real_size, GENERATION_NURSERY);
|
||||
if (!degraded_mode)
|
||||
p = (void **)sgen_nursery_alloc (size);
|
||||
}
|
||||
@@ -288,7 +275,7 @@ sgen_alloc_obj_nolock (GCVTable vtable, size_t size)
|
||||
p = (void **)sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
|
||||
if (!p) {
|
||||
/* See comment above in similar case. */
|
||||
sgen_ensure_free_space (tlab_size);
|
||||
sgen_ensure_free_space (tlab_size, GENERATION_NURSERY);
|
||||
if (!degraded_mode)
|
||||
p = (void **)sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
|
||||
}
|
||||
@@ -426,8 +413,6 @@ sgen_alloc_obj (GCVTable vtable, size_t size)
|
||||
if (!SGEN_CAN_ALIGN_UP (size))
|
||||
return NULL;
|
||||
|
||||
#ifndef DISABLE_CRITICAL_REGION
|
||||
|
||||
if (G_UNLIKELY (has_per_allocation_action)) {
|
||||
static int alloc_count;
|
||||
int current_alloc = InterlockedIncrement (&alloc_count);
|
||||
@@ -439,7 +424,7 @@ sgen_alloc_obj (GCVTable vtable, size_t size)
|
||||
if (collect_before_allocs) {
|
||||
if (((current_alloc % collect_before_allocs) == 0) && nursery_section) {
|
||||
LOCK_GC;
|
||||
sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE);
|
||||
sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE, TRUE);
|
||||
UNLOCK_GC;
|
||||
}
|
||||
}
|
||||
@@ -452,12 +437,10 @@ sgen_alloc_obj (GCVTable vtable, size_t size)
|
||||
return res;
|
||||
}
|
||||
EXIT_CRITICAL_REGION;
|
||||
#endif
|
||||
|
||||
LOCK_GC;
|
||||
res = sgen_alloc_obj_nolock (vtable, size);
|
||||
UNLOCK_GC;
|
||||
if (G_UNLIKELY (!res))
|
||||
sgen_client_out_of_memory (size);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -521,6 +504,9 @@ sgen_init_tlab_info (SgenThreadInfo* info)
|
||||
|
||||
#ifdef HAVE_KW_THREAD
|
||||
tlab_next_addr = &tlab_next;
|
||||
#ifndef SGEN_WITHOUT_MONO
|
||||
in_critical_region_addr = &info->client_info.in_critical_region;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -545,13 +531,15 @@ sgen_init_allocator (void)
|
||||
#if defined(HAVE_KW_THREAD) && !defined(SGEN_WITHOUT_MONO)
|
||||
int tlab_next_addr_offset = -1;
|
||||
int tlab_temp_end_offset = -1;
|
||||
|
||||
int in_critical_region_addr_offset = -1;
|
||||
|
||||
MONO_THREAD_VAR_OFFSET (tlab_next_addr, tlab_next_addr_offset);
|
||||
MONO_THREAD_VAR_OFFSET (tlab_temp_end, tlab_temp_end_offset);
|
||||
MONO_THREAD_VAR_OFFSET (in_critical_region_addr, in_critical_region_addr_offset);
|
||||
|
||||
mono_tls_key_set_offset (TLS_KEY_SGEN_TLAB_NEXT_ADDR, tlab_next_addr_offset);
|
||||
mono_tls_key_set_offset (TLS_KEY_SGEN_TLAB_TEMP_END, tlab_temp_end_offset);
|
||||
mono_tls_key_set_offset (TLS_KEY_SGEN_IN_CRITICAL_REGION_ADDR, in_critical_region_addr_offset);
|
||||
#endif
|
||||
|
||||
#ifdef HEAVY_STATISTICS
|
||||
|
||||
@@ -5,88 +5,33 @@
|
||||
* Copyright 2003-2010 Novell, Inc.
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
#ifndef __MONO_SGENARCHDEP_H__
|
||||
#define __MONO_SGENARCHDEP_H__
|
||||
|
||||
#include <mono/utils/mono-context.h>
|
||||
|
||||
/*
|
||||
* Define either USE_MONO_CTX, or
|
||||
* ARCH_SIGCTX_SP/ARCH_SIGCTX_IP/ARCH_STORE_REGS/ARCH_COPY_SIGCTX_REGS.
|
||||
* Define ARCH_NUM_REGS to be the number of general registers in MonoContext, or the
|
||||
* number of registers stored by ARCH_STORE_REGS.
|
||||
*/
|
||||
|
||||
#if defined(MONO_CROSS_COMPILE)
|
||||
|
||||
#define REDZONE_SIZE 0
|
||||
|
||||
#define ARCH_NUM_REGS 0
|
||||
#define ARCH_STORE_REGS(ptr)
|
||||
#define ARCH_SIGCTX_SP(ctx) NULL
|
||||
#define ARCH_SIGCTX_IP(ctx) NULL
|
||||
#define ARCH_COPY_SIGCTX_REGS(a,ctx)
|
||||
|
||||
#elif defined(TARGET_X86)
|
||||
|
||||
#define REDZONE_SIZE 0
|
||||
|
||||
#define ARCH_NUM_REGS 8
|
||||
|
||||
#ifndef MONO_ARCH_HAS_MONO_CONTEXT
|
||||
#error 0
|
||||
#endif
|
||||
|
||||
#define USE_MONO_CTX
|
||||
|
||||
#elif defined(TARGET_AMD64)
|
||||
|
||||
#define REDZONE_SIZE 128
|
||||
|
||||
#define ARCH_NUM_REGS 16
|
||||
#define USE_MONO_CTX
|
||||
|
||||
#elif defined(TARGET_POWERPC)
|
||||
|
||||
#define REDZONE_SIZE 224
|
||||
|
||||
#define ARCH_NUM_REGS 32
|
||||
#ifdef __APPLE__
|
||||
#define ARCH_STORE_REGS(ptr) \
|
||||
__asm__ __volatile__( \
|
||||
"stmw r0, 0(%0)\n" \
|
||||
: \
|
||||
: "b" (ptr) \
|
||||
)
|
||||
#else
|
||||
#define ARCH_STORE_REGS(ptr) \
|
||||
__asm__ __volatile__( \
|
||||
"stmw 0, 0(%0)\n" \
|
||||
: \
|
||||
: "b" (ptr) \
|
||||
)
|
||||
#endif
|
||||
#define ARCH_SIGCTX_SP(ctx) (UCONTEXT_REG_Rn((ctx), 1))
|
||||
#define ARCH_SIGCTX_IP(ctx) (UCONTEXT_REG_NIP((ctx)))
|
||||
#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { \
|
||||
int __i; \
|
||||
for (__i = 0; __i < 32; ++__i) \
|
||||
((a)[__i]) = (gpointer) UCONTEXT_REG_Rn((ctx), __i); \
|
||||
} while (0)
|
||||
|
||||
/* MS_BLOCK_SIZE must be a multiple of the system pagesize, which for some
|
||||
architectures is 64k. */
|
||||
#if defined(TARGET_POWERPC) || defined(TARGET_POWERPC64)
|
||||
@@ -97,10 +42,6 @@
|
||||
#elif defined(TARGET_ARM)
|
||||
|
||||
#define REDZONE_SIZE 0
|
||||
#define USE_MONO_CTX
|
||||
|
||||
/* We dont store ip, sp */
|
||||
#define ARCH_NUM_REGS 14
|
||||
|
||||
#elif defined(TARGET_ARM64)
|
||||
|
||||
@@ -111,99 +52,19 @@
|
||||
#else
|
||||
#error "Not implemented."
|
||||
#endif
|
||||
#define USE_MONO_CTX
|
||||
#define ARCH_NUM_REGS 31
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
#define REDZONE_SIZE 0
|
||||
|
||||
#define USE_MONO_CTX
|
||||
#define ARCH_NUM_REGS 32
|
||||
|
||||
#elif defined(__s390x__)
|
||||
|
||||
#define REDZONE_SIZE 0
|
||||
|
||||
#define USE_MONO_CTX
|
||||
#define ARCH_NUM_REGS 16
|
||||
|
||||
#elif defined(__sparc__)
|
||||
|
||||
#define REDZONE_SIZE 0
|
||||
|
||||
/* Don't bother with %g0 (%r0), it's always hard-coded to zero */
|
||||
#define ARCH_NUM_REGS 15
|
||||
#ifdef __sparcv9
|
||||
#define ARCH_STORE_REGS(ptr) \
|
||||
__asm__ __volatile__( \
|
||||
"st %%g1,[%0]\n\t" \
|
||||
"st %%g2,[%0+0x08]\n\t" \
|
||||
"st %%g3,[%0+0x10]\n\t" \
|
||||
"st %%g4,[%0+0x18]\n\t" \
|
||||
"st %%g5,[%0+0x20]\n\t" \
|
||||
"st %%g6,[%0+0x28]\n\t" \
|
||||
"st %%g7,[%0+0x30]\n\t" \
|
||||
"st %%o0,[%0+0x38]\n\t" \
|
||||
"st %%o1,[%0+0x40]\n\t" \
|
||||
"st %%o2,[%0+0x48]\n\t" \
|
||||
"st %%o3,[%0+0x50]\n\t" \
|
||||
"st %%o4,[%0+0x58]\n\t" \
|
||||
"st %%o5,[%0+0x60]\n\t" \
|
||||
"st %%o6,[%0+0x68]\n\t" \
|
||||
"st %%o7,[%0+0x70]\n\t" \
|
||||
: \
|
||||
: "r" (ptr) \
|
||||
: "memory" \
|
||||
)
|
||||
#else
|
||||
#define ARCH_STORE_REGS(ptr) \
|
||||
__asm__ __volatile__( \
|
||||
"st %%g1,[%0]\n\t" \
|
||||
"st %%g2,[%0+0x04]\n\t" \
|
||||
"st %%g3,[%0+0x08]\n\t" \
|
||||
"st %%g4,[%0+0x0c]\n\t" \
|
||||
"st %%g5,[%0+0x10]\n\t" \
|
||||
"st %%g6,[%0+0x14]\n\t" \
|
||||
"st %%g7,[%0+0x18]\n\t" \
|
||||
"st %%o0,[%0+0x1c]\n\t" \
|
||||
"st %%o1,[%0+0x20]\n\t" \
|
||||
"st %%o2,[%0+0x24]\n\t" \
|
||||
"st %%o3,[%0+0x28]\n\t" \
|
||||
"st %%o4,[%0+0x2c]\n\t" \
|
||||
"st %%o5,[%0+0x30]\n\t" \
|
||||
"st %%o6,[%0+0x34]\n\t" \
|
||||
"st %%o7,[%0+0x38]\n\t" \
|
||||
: \
|
||||
: "r" (ptr) \
|
||||
: "memory" \
|
||||
)
|
||||
#endif
|
||||
|
||||
#ifndef REG_SP
|
||||
#define REG_SP REG_O6
|
||||
#endif
|
||||
|
||||
#define ARCH_SIGCTX_SP(ctx) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_SP])
|
||||
#define ARCH_SIGCTX_IP(ctx) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_PC])
|
||||
#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { \
|
||||
(a)[0] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G1]); \
|
||||
(a)[1] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G2]); \
|
||||
(a)[2] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G3]); \
|
||||
(a)[3] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G4]); \
|
||||
(a)[4] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G5]); \
|
||||
(a)[5] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G6]); \
|
||||
(a)[6] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_G7]); \
|
||||
(a)[7] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O0]); \
|
||||
(a)[8] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O1]); \
|
||||
(a)[9] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O2]); \
|
||||
(a)[10] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O3]); \
|
||||
(a)[11] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O4]); \
|
||||
(a)[12] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O5]); \
|
||||
(a)[13] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O6]); \
|
||||
(a)[14] = (gpointer) (((ucontext_t *)(ctx))->uc_mcontext.gregs [REG_O7]); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __MONO_SGENARCHDEP_H__ */
|
||||
|
||||
213
mono/sgen/sgen-array-list.c
Normal file
213
mono/sgen/sgen-array-list.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* sgen-array-list.c: A pointer array list that doesn't require reallocs
|
||||
*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SGEN_GC
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mono/sgen/sgen-gc.h"
|
||||
#include "mono/sgen/sgen-array-list.h"
|
||||
|
||||
static void
|
||||
sgen_array_list_grow (SgenArrayList *array, guint32 old_capacity)
|
||||
{
|
||||
const guint32 new_bucket = sgen_array_list_index_bucket (old_capacity);
|
||||
const guint32 growth = sgen_array_list_bucket_size (new_bucket);
|
||||
const guint32 new_capacity = old_capacity + growth;
|
||||
const guint32 new_bucket_size = sizeof (**array->entries) * growth;
|
||||
gpointer *entries;
|
||||
if (array->capacity >= new_capacity)
|
||||
return;
|
||||
if (array->mem_type != -1)
|
||||
entries = (gpointer*) sgen_alloc_internal_dynamic (new_bucket_size, array->mem_type, TRUE);
|
||||
else
|
||||
entries = (gpointer*) g_malloc0 (new_bucket_size);
|
||||
if (array->bucket_alloc_callback)
|
||||
array->bucket_alloc_callback (entries, new_bucket_size, TRUE);
|
||||
/*
|
||||
* The zeroing of the newly allocated bucket must be complete before storing
|
||||
* the new bucket pointer.
|
||||
*/
|
||||
mono_memory_write_barrier ();
|
||||
if (InterlockedCompareExchangePointer ((volatile gpointer *)&array->entries [new_bucket], entries, NULL) == NULL) {
|
||||
/*
|
||||
* It must not be the case that we succeeded in setting the bucket
|
||||
* pointer, while someone else succeeded in changing the capacity.
|
||||
*/
|
||||
if (InterlockedCompareExchange ((volatile gint32 *)&array->capacity, new_capacity, old_capacity) != old_capacity)
|
||||
g_assert_not_reached ();
|
||||
array->slot_hint = old_capacity;
|
||||
return;
|
||||
}
|
||||
/* Someone beat us to the allocation. */
|
||||
if (array->bucket_alloc_callback)
|
||||
array->bucket_alloc_callback (entries, new_bucket_size, FALSE);
|
||||
if (array->mem_type != -1)
|
||||
sgen_free_internal_dynamic (entries, new_bucket_size, array->mem_type);
|
||||
else
|
||||
g_free (entries);
|
||||
}
|
||||
|
||||
static guint32
|
||||
sgen_array_list_find_unset (SgenArrayList *array, guint32 capacity)
|
||||
{
|
||||
if (!array->is_slot_set_func) {
|
||||
guint32 next_slot = array->next_slot;
|
||||
/* We can't lookup empty slots, use next_slot */
|
||||
if (next_slot < capacity)
|
||||
return next_slot;
|
||||
} else {
|
||||
guint32 slot_hint = array->slot_hint;
|
||||
guint32 index;
|
||||
volatile gpointer *slot;
|
||||
|
||||
SGEN_ARRAY_LIST_FOREACH_SLOT_RANGE(array, slot_hint, capacity, slot, index) {
|
||||
if (!array->is_slot_set_func (slot))
|
||||
return index;
|
||||
} SGEN_ARRAY_LIST_END_FOREACH_SLOT_RANGE;
|
||||
|
||||
SGEN_ARRAY_LIST_FOREACH_SLOT_RANGE (array, 0, slot_hint, slot, index) {
|
||||
if (!array->is_slot_set_func (slot))
|
||||
return index;
|
||||
} SGEN_ARRAY_LIST_END_FOREACH_SLOT_RANGE;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
sgen_array_list_update_next_slot (SgenArrayList *array, guint32 new_index)
|
||||
{
|
||||
if (!array->set_slot_func) {
|
||||
/*
|
||||
* If we don't have a custom setter it means we don't have thread
|
||||
* safety requirements.
|
||||
*/
|
||||
if (new_index >= array->next_slot)
|
||||
array->next_slot = new_index + 1;
|
||||
} else {
|
||||
guint32 old_next_slot;
|
||||
/* Thread safe update */
|
||||
do {
|
||||
old_next_slot = array->next_slot;
|
||||
if (new_index < old_next_slot)
|
||||
break;
|
||||
} while (InterlockedCompareExchange ((volatile gint32 *)&array->next_slot, new_index + 1, old_next_slot) != old_next_slot);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extension for the array list that allows fast allocation and index based fetching
|
||||
* of long lived memory of various sizes, without the need of realloc. Not thread safe.
|
||||
*/
|
||||
guint32
|
||||
sgen_array_list_alloc_block (SgenArrayList *array, guint32 slots_to_add)
|
||||
{
|
||||
guint32 new_index = array->next_slot;
|
||||
guint32 old_capacity = array->capacity;
|
||||
|
||||
/* FIXME Don't allocate arrays that will be skipped */
|
||||
/* There are no empty arrays between next_slot and capacity because we allocate incrementally */
|
||||
while ((old_capacity - new_index) < slots_to_add) {
|
||||
sgen_array_list_grow (array, old_capacity);
|
||||
new_index = old_capacity;
|
||||
old_capacity = array->capacity;
|
||||
}
|
||||
|
||||
SGEN_ASSERT (0, sgen_array_list_index_bucket (new_index) == sgen_array_list_index_bucket (new_index + slots_to_add - 1),
|
||||
"We failed to allocate a continuous block of slots");
|
||||
|
||||
array->next_slot = new_index + slots_to_add;
|
||||
/* The slot address will point to the allocated memory */
|
||||
return new_index;
|
||||
}
|
||||
|
||||
guint32
|
||||
sgen_array_list_add (SgenArrayList *array, gpointer ptr, int data, gboolean increase_size_before_set)
|
||||
{
|
||||
guint32 index, capacity;
|
||||
volatile gpointer *slot;
|
||||
|
||||
if (!array->capacity)
|
||||
sgen_array_list_grow (array, 0);
|
||||
retry:
|
||||
capacity = array->capacity;
|
||||
index = sgen_array_list_find_unset (array, capacity);
|
||||
if (index == -1) {
|
||||
sgen_array_list_grow (array, capacity);
|
||||
goto retry;
|
||||
}
|
||||
array->slot_hint = index;
|
||||
|
||||
if (increase_size_before_set) {
|
||||
sgen_array_list_update_next_slot (array, index);
|
||||
mono_memory_write_barrier ();
|
||||
}
|
||||
|
||||
slot = sgen_array_list_get_slot (array, index);
|
||||
if (array->set_slot_func) {
|
||||
if (!array->set_slot_func (slot, ptr, data))
|
||||
goto retry;
|
||||
} else {
|
||||
*slot = ptr;
|
||||
}
|
||||
|
||||
if (!increase_size_before_set) {
|
||||
mono_memory_write_barrier ();
|
||||
sgen_array_list_update_next_slot (array, index);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes all NULL pointers from the array. Not thread safe
|
||||
*/
|
||||
void
|
||||
sgen_array_list_remove_nulls (SgenArrayList *array)
|
||||
{
|
||||
guint32 start = 0;
|
||||
volatile gpointer *slot;
|
||||
|
||||
SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) {
|
||||
if (*slot)
|
||||
*sgen_array_list_get_slot (array, start++) = *slot;
|
||||
} SGEN_ARRAY_LIST_END_FOREACH_SLOT;
|
||||
|
||||
mono_memory_write_barrier ();
|
||||
array->next_slot = start;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does a linear search through the pointer array to find `ptr`. Returns the index if
|
||||
* found, otherwise (guint32)-1.
|
||||
*/
|
||||
guint32
|
||||
sgen_array_list_find (SgenArrayList *array, gpointer ptr)
|
||||
{
|
||||
volatile gpointer *slot;
|
||||
|
||||
SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) {
|
||||
if (*slot == ptr)
|
||||
return __index;
|
||||
} SGEN_ARRAY_LIST_END_FOREACH_SLOT;
|
||||
return (guint32)-1;
|
||||
}
|
||||
|
||||
#endif
|
||||
137
mono/sgen/sgen-array-list.h
Normal file
137
mono/sgen/sgen-array-list.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* sgen-array-list.h: A pointer array that doesn't use reallocs.
|
||||
*
|
||||
* Copyright (C) 2016 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_ARRAY_LIST_H__
|
||||
#define __MONO_SGEN_ARRAY_LIST_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#define SGEN_ARRAY_LIST_BUCKETS (32)
|
||||
#define SGEN_ARRAY_LIST_MIN_BUCKET_BITS (5)
|
||||
#define SGEN_ARRAY_LIST_MIN_BUCKET_SIZE (1 << SGEN_ARRAY_LIST_MIN_BUCKET_BITS)
|
||||
|
||||
typedef void (*SgenArrayListBucketAllocCallback) (gpointer *bucket, guint32 new_bucket_size, gboolean alloc);
|
||||
typedef gboolean (*SgenArrayListIsSlotSetFunc) (volatile gpointer *slot);
|
||||
typedef gboolean (*SgenArrayListSetSlotFunc) (volatile gpointer *slot, gpointer ptr, int data);
|
||||
|
||||
/*
|
||||
* 'entries' is an array of pointers to buckets of increasing size. The first
|
||||
* bucket has size 'MIN_BUCKET_SIZE', and each bucket is twice the size of the
|
||||
* previous, i.e.:
|
||||
*
|
||||
* |-------|-- MIN_BUCKET_SIZE
|
||||
* [0] -> xxxxxxxx
|
||||
* [1] -> xxxxxxxxxxxxxxxx
|
||||
* [2] -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
* ...
|
||||
*
|
||||
* 'slot_hint' denotes the position of the last allocation, so that the
|
||||
* whole array needn't be searched on every allocation.
|
||||
*
|
||||
* The size of the spine, 'SGEN_ARRAY_LIST_BUCKETS', is chosen so
|
||||
* that the maximum number of entries is no less than G_MAXUINT32.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
volatile gpointer *volatile entries [SGEN_ARRAY_LIST_BUCKETS];
|
||||
volatile guint32 capacity;
|
||||
volatile guint32 slot_hint;
|
||||
volatile guint32 next_slot;
|
||||
SgenArrayListBucketAllocCallback bucket_alloc_callback;
|
||||
SgenArrayListIsSlotSetFunc is_slot_set_func;
|
||||
SgenArrayListSetSlotFunc set_slot_func;
|
||||
int mem_type; /* sgen internal mem type or -1 for malloc allocation */
|
||||
} SgenArrayList;
|
||||
|
||||
/*
|
||||
* Computes floor(log2(index + MIN_BUCKET_SIZE)) - 1, giving the index
|
||||
* of the bucket containing a slot.
|
||||
*/
|
||||
static inline guint32
|
||||
sgen_array_list_index_bucket (guint32 index)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return CHAR_BIT * sizeof (index) - __builtin_clz (index + SGEN_ARRAY_LIST_MIN_BUCKET_SIZE) - 1 - SGEN_ARRAY_LIST_MIN_BUCKET_BITS;
|
||||
#else
|
||||
guint count = 0;
|
||||
index += SGEN_ARRAY_LIST_MIN_BUCKET_SIZE;
|
||||
while (index) {
|
||||
++count;
|
||||
index >>= 1;
|
||||
}
|
||||
return count - 1 - SGEN_ARRAY_LIST_MIN_BUCKET_BITS;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline guint32
|
||||
sgen_array_list_bucket_size (guint32 index)
|
||||
{
|
||||
return 1 << (index + SGEN_ARRAY_LIST_MIN_BUCKET_BITS);
|
||||
}
|
||||
|
||||
static inline void
|
||||
sgen_array_list_bucketize (guint32 index, guint32 *bucket, guint32 *offset)
|
||||
{
|
||||
*bucket = sgen_array_list_index_bucket (index);
|
||||
*offset = index - sgen_array_list_bucket_size (*bucket) + SGEN_ARRAY_LIST_MIN_BUCKET_SIZE;
|
||||
}
|
||||
|
||||
static inline volatile gpointer *
|
||||
sgen_array_list_get_slot (SgenArrayList *array, guint32 index)
|
||||
{
|
||||
guint32 bucket, offset;
|
||||
|
||||
SGEN_ASSERT (0, index < array->capacity, "Why are we accessing an entry that is not allocated");
|
||||
|
||||
sgen_array_list_bucketize (index, &bucket, &offset);
|
||||
return &(array->entries [bucket] [offset]);
|
||||
}
|
||||
|
||||
#define SGEN_ARRAY_LIST_INIT(bucket_alloc_callback, is_slot_set_func, set_slot_func, mem_type) { { NULL }, 0, 0, 0, (bucket_alloc_callback), (is_slot_set_func), (set_slot_func), (mem_type) }
|
||||
|
||||
#define SGEN_ARRAY_LIST_FOREACH_SLOT(array, slot) { \
|
||||
guint32 __bucket, __offset; \
|
||||
const guint32 __max_bucket = sgen_array_list_index_bucket ((array)->capacity); \
|
||||
guint32 __index = 0; \
|
||||
const guint32 __next_slot = (array)->next_slot; \
|
||||
for (__bucket = 0; __bucket < __max_bucket; ++__bucket) { \
|
||||
volatile gpointer *__entries = (array)->entries [__bucket]; \
|
||||
for (__offset = 0; __offset < sgen_array_list_bucket_size (__bucket); ++__offset, ++__index) { \
|
||||
if (__index >= __next_slot) \
|
||||
break; \
|
||||
slot = &__entries [__offset];
|
||||
|
||||
#define SGEN_ARRAY_LIST_END_FOREACH_SLOT } } }
|
||||
|
||||
#define SGEN_ARRAY_LIST_FOREACH_SLOT_RANGE(array, begin, end, slot, index) { \
|
||||
for (index = (begin); index < (end); index++) { \
|
||||
guint32 __bucket, __offset; \
|
||||
volatile gpointer *__entries; \
|
||||
sgen_array_list_bucketize (index, &__bucket, &__offset); \
|
||||
__entries = (array)->entries [__bucket]; \
|
||||
slot = &__entries [__offset];
|
||||
|
||||
#define SGEN_ARRAY_LIST_END_FOREACH_SLOT_RANGE } }
|
||||
|
||||
guint32 sgen_array_list_alloc_block (SgenArrayList *array, guint32 slots_to_add);
|
||||
guint32 sgen_array_list_add (SgenArrayList *array, gpointer ptr, int data, gboolean increase_size_before_set);
|
||||
guint32 sgen_array_list_find (SgenArrayList *array, gpointer ptr);
|
||||
void sgen_array_list_remove_nulls (SgenArrayList *array);
|
||||
|
||||
#endif
|
||||
@@ -9,18 +9,7 @@
|
||||
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -119,19 +108,13 @@ sgen_card_table_wbarrier_value_copy (gpointer dest, gpointer src, int count, siz
|
||||
{
|
||||
size_t size = count * element_size;
|
||||
|
||||
#ifdef DISABLE_CRITICAL_REGION
|
||||
LOCK_GC;
|
||||
#else
|
||||
TLAB_ACCESS_INIT;
|
||||
ENTER_CRITICAL_REGION;
|
||||
#endif
|
||||
|
||||
mono_gc_memmove_atomic (dest, src, size);
|
||||
sgen_card_table_mark_range ((mword)dest, size);
|
||||
#ifdef DISABLE_CRITICAL_REGION
|
||||
UNLOCK_GC;
|
||||
#else
|
||||
|
||||
EXIT_CRITICAL_REGION;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -139,20 +122,14 @@ sgen_card_table_wbarrier_object_copy (GCObject* obj, GCObject *src)
|
||||
{
|
||||
size_t size = sgen_client_par_object_get_size (SGEN_LOAD_VTABLE_UNCHECKED (obj), obj);
|
||||
|
||||
#ifdef DISABLE_CRITICAL_REGION
|
||||
LOCK_GC;
|
||||
#else
|
||||
TLAB_ACCESS_INIT;
|
||||
ENTER_CRITICAL_REGION;
|
||||
#endif
|
||||
|
||||
mono_gc_memmove_aligned ((char*)obj + SGEN_CLIENT_OBJECT_HEADER_SIZE, (char*)src + SGEN_CLIENT_OBJECT_HEADER_SIZE,
|
||||
size - SGEN_CLIENT_OBJECT_HEADER_SIZE);
|
||||
sgen_card_table_mark_range ((mword)obj, size);
|
||||
#ifdef DISABLE_CRITICAL_REGION
|
||||
UNLOCK_GC;
|
||||
#else
|
||||
|
||||
EXIT_CRITICAL_REGION;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -354,6 +331,29 @@ sgen_card_table_update_mod_union (guint8 *dest, char *obj, mword obj_size, size_
|
||||
*out_num_cards = num_cards;
|
||||
}
|
||||
|
||||
/* Preclean cards and saves the cards that need to be scanned afterwards in cards_preclean */
|
||||
void
|
||||
sgen_card_table_preclean_mod_union (guint8 *cards, guint8 *cards_preclean, size_t num_cards)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
memcpy (cards_preclean, cards, num_cards);
|
||||
for (i = 0; i < num_cards; i++) {
|
||||
if (cards_preclean [i]) {
|
||||
cards [i] = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* When precleaning we need to make sure the card cleaning
|
||||
* takes place before the object is scanned. If we don't
|
||||
* do this we could finish scanning the object and, before
|
||||
* the cleaning of the card takes place, another thread
|
||||
* could dirty the object, mark the mod_union card only for
|
||||
* us to clean it back, without scanning the object again.
|
||||
*/
|
||||
mono_memory_barrier ();
|
||||
}
|
||||
|
||||
#ifdef SGEN_HAVE_OVERLAPPING_CARDS
|
||||
|
||||
static void
|
||||
@@ -438,11 +438,11 @@ sgen_card_table_scan_remsets (ScanCopyContext ctx)
|
||||
sgen_card_table_clear_cards ();
|
||||
#endif
|
||||
SGEN_TV_GETTIME (atv);
|
||||
sgen_get_major_collector ()->scan_card_table (FALSE, ctx);
|
||||
sgen_get_major_collector ()->scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx);
|
||||
SGEN_TV_GETTIME (btv);
|
||||
last_major_scan_time = SGEN_TV_ELAPSED (atv, btv);
|
||||
major_card_scan_time += last_major_scan_time;
|
||||
sgen_los_scan_card_table (FALSE, ctx);
|
||||
sgen_los_scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx);
|
||||
SGEN_TV_GETTIME (atv);
|
||||
last_los_scan_time = SGEN_TV_ELAPSED (btv, atv);
|
||||
los_card_scan_time += last_los_scan_time;
|
||||
@@ -489,11 +489,11 @@ sgen_card_table_dump_obj_card (GCObject *object, size_t size, void *dummy)
|
||||
#endif
|
||||
|
||||
void
|
||||
sgen_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, gboolean mod_union, ScanCopyContext ctx)
|
||||
sgen_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, ScanCopyContext ctx)
|
||||
{
|
||||
HEAVY_STAT (++large_objects);
|
||||
|
||||
if (sgen_client_cardtable_scan_object (obj, block_obj_size, cards, mod_union, ctx))
|
||||
if (sgen_client_cardtable_scan_object (obj, block_obj_size, cards, ctx))
|
||||
return;
|
||||
|
||||
HEAVY_STAT (++bloby_objects);
|
||||
|
||||
@@ -2,24 +2,7 @@
|
||||
* Copyright 2001-2003 Ximian, Inc
|
||||
* Copyright 2003-2010 Novell, Inc.
|
||||
*
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
#ifndef __MONO_SGEN_CARD_TABLE_INLINES_H__
|
||||
#define __MONO_SGEN_CARD_TABLE_INLINES_H__
|
||||
@@ -31,7 +14,7 @@ void sgen_card_table_reset_region (mword start, mword end);
|
||||
void* sgen_card_table_align_pointer (void *ptr);
|
||||
void sgen_card_table_mark_range (mword address, mword size);
|
||||
void sgen_cardtable_scan_object (GCObject *obj, mword obj_size, guint8 *cards,
|
||||
gboolean mod_union, ScanCopyContext ctx);
|
||||
ScanCopyContext ctx);
|
||||
|
||||
gboolean sgen_card_table_get_card_data (guint8 *dest, mword address, mword cards);
|
||||
|
||||
@@ -40,6 +23,7 @@ void sgen_card_table_free_mod_union (guint8 *mod_union, char *obj, mword obj_siz
|
||||
|
||||
void sgen_card_table_update_mod_union_from_cards (guint8 *dest, guint8 *start_card, size_t num_cards);
|
||||
void sgen_card_table_update_mod_union (guint8 *dest, char *obj, mword obj_size, size_t *out_num_cards);
|
||||
void sgen_card_table_preclean_mod_union (guint8 *cards, guint8 *cards_preclean, size_t num_cards);
|
||||
|
||||
guint8* sgen_get_card_table_configuration (int *shift_bits, gpointer *mask);
|
||||
|
||||
|
||||
@@ -3,18 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2014 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
|
||||
#include "mono/sgen/sgen-pointer-queue.h"
|
||||
@@ -105,7 +94,7 @@ void sgen_client_ensure_weak_gchandles_accessible (void);
|
||||
* parts of the object based on which cards are marked, do so and return TRUE. Otherwise,
|
||||
* return FALSE.
|
||||
*/
|
||||
gboolean sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, gboolean mod_union, ScanCopyContext ctx);
|
||||
gboolean sgen_client_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, ScanCopyContext ctx);
|
||||
|
||||
/*
|
||||
* Called after nursery objects have been pinned. No action is necessary.
|
||||
@@ -140,14 +129,6 @@ void sgen_client_degraded_allocation (size_t size);
|
||||
*/
|
||||
void sgen_client_total_allocated_heap_changed (size_t allocated_heap_size);
|
||||
|
||||
/*
|
||||
* Called when an object allocation fails. The suggested action is to abort the program.
|
||||
*
|
||||
* FIXME: Don't we want to return a BOOL here that indicates whether to retry the
|
||||
* allocation?
|
||||
*/
|
||||
void sgen_client_out_of_memory (size_t size);
|
||||
|
||||
/*
|
||||
* If the client has registered any internal memory types, this must return a string
|
||||
* describing the given type. Only used for debugging.
|
||||
@@ -193,7 +174,7 @@ void sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gbool
|
||||
* single-threaded programs this is a nop.
|
||||
*/
|
||||
void sgen_client_stop_world (int generation);
|
||||
void sgen_client_restart_world (int generation, GGTimingInfo *timing);
|
||||
void sgen_client_restart_world (int generation, gint64 *stw_time);
|
||||
|
||||
/*
|
||||
* Must return FALSE. The bridge is not supported outside of Mono.
|
||||
@@ -216,12 +197,6 @@ void sgen_client_bridge_register_finalized_object (GCObject *object);
|
||||
void sgen_client_mark_togglerefs (char *start, char *end, ScanCopyContext ctx);
|
||||
void sgen_client_clear_togglerefs (char *start, char *end, ScanCopyContext ctx);
|
||||
|
||||
/*
|
||||
* Called after collections, reporting the amount of time they took. No action is
|
||||
* necessary.
|
||||
*/
|
||||
void sgen_client_log_timing (GGTimingInfo *info, mword last_major_num_sections, mword last_los_memory_usage);
|
||||
|
||||
/*
|
||||
* Called to handle `MONO_GC_PARAMS` and `MONO_GC_DEBUG` options. The `handle` functions
|
||||
* must return TRUE if they have recognized and processed the option, FALSE otherwise.
|
||||
|
||||
@@ -6,18 +6,7 @@
|
||||
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
#ifndef __MONO_SGENCONF_H__
|
||||
#define __MONO_SGENCONF_H__
|
||||
@@ -190,12 +179,6 @@ typedef mword SgenDescriptor;
|
||||
*/
|
||||
#define SGEN_DEFAULT_ALLOWANCE_HEAP_SIZE_RATIO 0.33
|
||||
|
||||
/*
|
||||
* How much more we allow the heap to grow, relative to the allowance, while doing
|
||||
* a concurrent collection, before forcing its finish.
|
||||
*/
|
||||
#define SGEN_DEFAULT_CONCURRENT_HEAP_ALLOWANCE_RATIO 0.25
|
||||
|
||||
/*
|
||||
* Default ratio of memory we want to release in a major collection in relation to the the current heap size.
|
||||
*
|
||||
|
||||
@@ -5,18 +5,7 @@
|
||||
* Copyright 2003-2010 Novell, Inc.
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
|
||||
extern guint64 stat_copy_object_called_nursery;
|
||||
|
||||
@@ -10,18 +10,7 @@
|
||||
* Copyright 2011 Xamarin, Inc.
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -504,10 +493,10 @@ static void
|
||||
find_pinning_ref_from_thread (char *obj, size_t size)
|
||||
{
|
||||
#ifndef SGEN_WITHOUT_MONO
|
||||
int j;
|
||||
char *endobj = obj + size;
|
||||
|
||||
FOREACH_THREAD (info) {
|
||||
mword *ctxstart, *ctxcurrent, *ctxend;
|
||||
char **start = (char**)info->client_info.stack_start;
|
||||
if (info->client_info.skip || info->client_info.gc_disabled)
|
||||
continue;
|
||||
@@ -517,15 +506,11 @@ find_pinning_ref_from_thread (char *obj, size_t size)
|
||||
start++;
|
||||
}
|
||||
|
||||
for (j = 0; j < ARCH_NUM_REGS; ++j) {
|
||||
#ifdef USE_MONO_CTX
|
||||
mword w = ((mword*)&info->client_info.ctx) [j];
|
||||
#else
|
||||
mword w = (mword)&info->client_info.regs [j];
|
||||
#endif
|
||||
for (ctxstart = ctxcurrent = (mword*) &info->client_info.ctx, ctxend = (mword*) (&info->client_info.ctx + 1); ctxcurrent < ctxend; ctxcurrent ++) {
|
||||
mword w = *ctxcurrent;
|
||||
|
||||
if (w >= (mword)obj && w < (mword)obj + size)
|
||||
SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, j, info, (gpointer)mono_thread_info_get_tid (info));
|
||||
SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, (int) (ctxcurrent - ctxstart), info, (gpointer)mono_thread_info_get_tid (info));
|
||||
}
|
||||
} FOREACH_THREAD_END
|
||||
#endif
|
||||
@@ -1007,9 +992,11 @@ check_reference_for_xdomain (GCObject **ptr, GCObject *obj, MonoDomain *domain)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ref->vtable->klass == mono_defaults.string_class)
|
||||
str = mono_string_to_utf8 ((MonoString*)ref);
|
||||
else
|
||||
if (ref->vtable->klass == mono_defaults.string_class) {
|
||||
MonoError error;
|
||||
str = mono_string_to_utf8_checked ((MonoString*)ref, &error);
|
||||
mono_error_cleanup (&error);
|
||||
} else
|
||||
str = NULL;
|
||||
g_print ("xdomain reference in %p (%s.%s) at offset %d (%s) to %p (%s.%s) (%s) - pointed to by:\n",
|
||||
obj, obj->vtable->klass->name_space, obj->vtable->klass->name,
|
||||
|
||||
@@ -6,18 +6,7 @@
|
||||
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
#include "config.h"
|
||||
#ifdef HAVE_SGEN_GC
|
||||
@@ -44,6 +33,7 @@
|
||||
|
||||
#include "mono/sgen/sgen-gc.h"
|
||||
#include "mono/sgen/gc-internal-agnostic.h"
|
||||
#include "mono/sgen/sgen-array-list.h"
|
||||
|
||||
#define MAX_USER_DESCRIPTORS 16
|
||||
|
||||
@@ -51,9 +41,7 @@
|
||||
#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
|
||||
static gsize* complex_descriptors = NULL;
|
||||
static int complex_descriptors_size = 0;
|
||||
static int complex_descriptors_next = 0;
|
||||
static SgenArrayList complex_descriptors = SGEN_ARRAY_LIST_INIT (NULL, NULL, NULL, INTERNAL_MEM_COMPLEX_DESCRIPTORS);
|
||||
static SgenUserRootMarkFunc user_descriptors [MAX_USER_DESCRIPTORS];
|
||||
static int user_descriptors_next = 0;
|
||||
static SgenDescriptor all_ref_root_descrs [32];
|
||||
@@ -67,43 +55,50 @@ static int
|
||||
alloc_complex_descriptor (gsize *bitmap, int numbits)
|
||||
{
|
||||
int nwords, res, i;
|
||||
volatile gpointer *slot;
|
||||
gsize *descriptor;
|
||||
|
||||
SGEN_ASSERT (0, sizeof (gsize) == sizeof (mword), "We expect gsize and mword to have same size");
|
||||
|
||||
numbits = ALIGN_TO (numbits, GC_BITS_PER_WORD);
|
||||
nwords = numbits / GC_BITS_PER_WORD + 1;
|
||||
|
||||
sgen_gc_lock ();
|
||||
res = complex_descriptors_next;
|
||||
/* linear search, so we don't have duplicates with domain load/unload
|
||||
* this should not be performance critical or we'd have bigger issues
|
||||
* (the number and size of complex descriptors should be small).
|
||||
*/
|
||||
for (i = 0; i < complex_descriptors_next; ) {
|
||||
if (complex_descriptors [i] == nwords) {
|
||||
SGEN_ARRAY_LIST_FOREACH_SLOT (&complex_descriptors, slot) {
|
||||
gsize first_word = *(gsize*)slot;
|
||||
if (first_word == 0) {
|
||||
/* Unused slots should be 0 so we simply skip them */
|
||||
continue;
|
||||
} else if (first_word == nwords) {
|
||||
int j, found = TRUE;
|
||||
for (j = 0; j < nwords - 1; ++j) {
|
||||
if (complex_descriptors [i + 1 + j] != bitmap [j]) {
|
||||
if (((gsize*)slot) [j + 1] != bitmap [j]) {
|
||||
found = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
sgen_gc_unlock ();
|
||||
return i;
|
||||
return __index;
|
||||
}
|
||||
}
|
||||
i += (int)complex_descriptors [i];
|
||||
}
|
||||
if (complex_descriptors_next + nwords > complex_descriptors_size) {
|
||||
int new_size = complex_descriptors_size * 2 + nwords;
|
||||
complex_descriptors = (gsize *)g_realloc (complex_descriptors, new_size * sizeof (gsize));
|
||||
complex_descriptors_size = new_size;
|
||||
}
|
||||
SGEN_LOG (6, "Complex descriptor %d, size: %d (total desc memory: %d)", res, nwords, complex_descriptors_size);
|
||||
complex_descriptors_next += nwords;
|
||||
complex_descriptors [res] = nwords;
|
||||
/* Skip the bitmap words */
|
||||
__index += (guint32)(first_word - 1);
|
||||
__offset += (guint32)(first_word - 1);
|
||||
} SGEN_ARRAY_LIST_END_FOREACH_SLOT;
|
||||
|
||||
res = sgen_array_list_alloc_block (&complex_descriptors, nwords);
|
||||
|
||||
SGEN_LOG (6, "Complex descriptor %d, size: %d (total desc memory: %d)", res, nwords, complex_descriptors.capacity);
|
||||
descriptor = (gsize*)sgen_array_list_get_slot (&complex_descriptors, res);
|
||||
descriptor [0] = nwords;
|
||||
for (i = 0; i < nwords - 1; ++i) {
|
||||
complex_descriptors [res + 1 + i] = bitmap [i];
|
||||
SGEN_LOG (6, "\tvalue: %p", (void*)complex_descriptors [res + 1 + i]);
|
||||
descriptor [1 + i] = bitmap [i];
|
||||
SGEN_LOG (6, "\tvalue: %p", (void*)descriptor [1 + i]);
|
||||
}
|
||||
sgen_gc_unlock ();
|
||||
return res;
|
||||
@@ -112,7 +107,7 @@ alloc_complex_descriptor (gsize *bitmap, int numbits)
|
||||
gsize*
|
||||
sgen_get_complex_descriptor (SgenDescriptor desc)
|
||||
{
|
||||
return complex_descriptors + (desc >> LOW_TYPE_BITS);
|
||||
return (gsize*) sgen_array_list_get_slot (&complex_descriptors, desc >> LOW_TYPE_BITS);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -123,10 +118,7 @@ mono_gc_make_descr_for_object (gsize *bitmap, int numbits, size_t obj_size)
|
||||
{
|
||||
int first_set = -1, num_set = 0, last_set = -1, i;
|
||||
SgenDescriptor desc = 0;
|
||||
size_t stored_size = obj_size;
|
||||
|
||||
stored_size += SGEN_ALLOC_ALIGN - 1;
|
||||
stored_size &= ~(SGEN_ALLOC_ALIGN - 1);
|
||||
size_t stored_size = SGEN_ALIGN_UP (obj_size);
|
||||
|
||||
for (i = 0; i < numbits; ++i) {
|
||||
if (bitmap [i / GC_BITS_PER_WORD] & ((gsize)1 << (i % GC_BITS_PER_WORD))) {
|
||||
@@ -200,7 +192,7 @@ mono_gc_make_descr_for_array (int vector, gsize *elem_bitmap, int numbits, size_
|
||||
}
|
||||
/* Note: we also handle structs with just ref fields */
|
||||
if (num_set * sizeof (gpointer) == elem_size) {
|
||||
return desc | VECTOR_SUBTYPE_REFS | ((gssize)(-1) << 16);
|
||||
return desc | VECTOR_SUBTYPE_REFS | ((gsize)(-1) << 16);
|
||||
}
|
||||
/* FIXME: try run-len first */
|
||||
/* Note: we can't skip the object header here, because it's not present */
|
||||
@@ -325,7 +317,7 @@ sgen_make_user_root_descriptor (SgenUserRootMarkFunc marker)
|
||||
void*
|
||||
sgen_get_complex_descriptor_bitmap (SgenDescriptor desc)
|
||||
{
|
||||
return complex_descriptors + (desc >> ROOT_DESC_TYPE_SHIFT);
|
||||
return (void*) sgen_array_list_get_slot (&complex_descriptors, desc >> ROOT_DESC_TYPE_SHIFT);
|
||||
}
|
||||
|
||||
SgenUserRootMarkFunc
|
||||
|
||||
@@ -7,18 +7,7 @@
|
||||
*
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
#ifndef __MONO_SGEN_DESCRIPTOR_H__
|
||||
#define __MONO_SGEN_DESCRIPTOR_H__
|
||||
@@ -226,7 +215,7 @@ sgen_gc_descr_has_references (SgenDescriptor desc)
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define OBJ_COMPLEX_FOREACH_PTR(vt,obj) do { \
|
||||
#define OBJ_COMPLEX_FOREACH_PTR(desc,obj) do { \
|
||||
/* there are pointers */ \
|
||||
void **_objptr = (void**)(obj); \
|
||||
gsize *bitmap_data = sgen_get_complex_descriptor ((desc)); \
|
||||
|
||||
@@ -10,18 +10,7 @@
|
||||
* Copyright 2011 Xamarin, Inc.
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -451,7 +440,7 @@ add_stage_entry (int num_entries, volatile gint32 *next_entry, StageEntry *entri
|
||||
* This seems like a good value. Determined by timing
|
||||
* sgen-weakref-stress.exe.
|
||||
*/
|
||||
g_usleep (200);
|
||||
mono_thread_info_usleep (200);
|
||||
HEAVY_STAT (++stat_wait_for_processing);
|
||||
}
|
||||
continue;
|
||||
@@ -568,30 +557,27 @@ sgen_object_register_for_finalization (GCObject *obj, void *user_data)
|
||||
}
|
||||
|
||||
/* LOCKING: requires that the GC lock is held */
|
||||
static int
|
||||
finalizers_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, GCObject **out_array, int out_size, SgenHashTable *hash_table)
|
||||
static void
|
||||
finalize_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, SgenHashTable *hash_table)
|
||||
{
|
||||
GCObject *object;
|
||||
gpointer dummy G_GNUC_UNUSED;
|
||||
int count;
|
||||
|
||||
if (no_finalize || !out_size || !out_array)
|
||||
return 0;
|
||||
count = 0;
|
||||
if (no_finalize)
|
||||
return;
|
||||
SGEN_HASH_TABLE_FOREACH (hash_table, GCObject *, object, gpointer, dummy) {
|
||||
object = tagged_object_get_object (object);
|
||||
|
||||
if (predicate (object, user_data)) {
|
||||
/* remove and put in out_array */
|
||||
SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
|
||||
out_array [count ++] = object;
|
||||
SGEN_LOG (5, "Collecting object for finalization: %p (%s) (%d)", object, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (object)), sgen_hash_table_num_entries (hash_table));
|
||||
if (count == out_size)
|
||||
return count;
|
||||
continue;
|
||||
sgen_queue_finalization_entry (object);
|
||||
SGEN_LOG (5, "Enqueuing object for finalization: %p (%s) (%d)", object, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (object)), sgen_hash_table_num_entries (hash_table));
|
||||
}
|
||||
|
||||
if (sgen_suspend_finalizers)
|
||||
break;
|
||||
} SGEN_HASH_TABLE_FOREACH_END;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -610,21 +596,14 @@ finalizers_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, G
|
||||
* @out_array me be on the stack, or registered as a root, to allow the GC to know the
|
||||
* objects are still alive.
|
||||
*/
|
||||
int
|
||||
sgen_gather_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, GCObject **out_array, int out_size)
|
||||
void
|
||||
sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data)
|
||||
{
|
||||
int result;
|
||||
|
||||
LOCK_GC;
|
||||
sgen_process_fin_stage_entries ();
|
||||
result = finalizers_with_predicate (predicate, user_data, (GCObject**)out_array, out_size, &minor_finalizable_hash);
|
||||
if (result < out_size) {
|
||||
result += finalizers_with_predicate (predicate, user_data, (GCObject**)out_array + result, out_size - result,
|
||||
&major_finalizable_hash);
|
||||
}
|
||||
finalize_with_predicate (predicate, user_data, &minor_finalizable_hash);
|
||||
finalize_with_predicate (predicate, user_data, &major_finalizable_hash);
|
||||
UNLOCK_GC;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1 +1 @@
|
||||
14605014e14187566c4a9854c7dc2a1d6914fb34
|
||||
2a1cd09094a18072d2cc366ab4c686942eee3913
|
||||
@@ -6,18 +6,7 @@
|
||||
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
#ifndef __MONO_SGENGC_H__
|
||||
#define __MONO_SGENGC_H__
|
||||
@@ -146,12 +135,16 @@ extern int current_collection_generation;
|
||||
|
||||
extern unsigned int sgen_global_stop_count;
|
||||
|
||||
#define SGEN_ALIGN_UP_TO(val,align) (((val) + (align - 1)) & ~(align - 1))
|
||||
#define SGEN_ALIGN_DOWN_TO(val,align) ((val) & ~(align - 1))
|
||||
|
||||
#define SGEN_ALLOC_ALIGN 8
|
||||
#define SGEN_ALLOC_ALIGN_BITS 3
|
||||
|
||||
/* s must be non-negative */
|
||||
#define SGEN_CAN_ALIGN_UP(s) ((s) <= SIZE_MAX - (SGEN_ALLOC_ALIGN - 1))
|
||||
#define SGEN_ALIGN_UP(s) (((s)+(SGEN_ALLOC_ALIGN-1)) & ~(SGEN_ALLOC_ALIGN-1))
|
||||
#define SGEN_ALIGN_UP(s) SGEN_ALIGN_UP_TO(s, SGEN_ALLOC_ALIGN)
|
||||
#define SGEN_ALIGN_DOWN(s) SGEN_ALIGN_DOWN_TO(s, SGEN_ALLOC_ALIGN)
|
||||
|
||||
#if SIZEOF_VOID_P == 4
|
||||
#define ONE_P 1
|
||||
@@ -285,6 +278,8 @@ void sgen_check_section_scan_starts (GCMemSection *section);
|
||||
|
||||
void sgen_conservatively_pin_objects_from (void **start, void **end, void *start_nursery, void *end_nursery, int pin_type);
|
||||
|
||||
gboolean sgen_gc_initialized (void);
|
||||
|
||||
/* Keep in sync with description_for_type() in sgen-internal.c! */
|
||||
enum {
|
||||
INTERNAL_MEM_PIN_QUEUE,
|
||||
@@ -322,6 +317,8 @@ enum {
|
||||
INTERNAL_MEM_CARDTABLE_MOD_UNION,
|
||||
INTERNAL_MEM_BINARY_PROTOCOL,
|
||||
INTERNAL_MEM_TEMPORARY,
|
||||
INTERNAL_MEM_LOG_ENTRY,
|
||||
INTERNAL_MEM_COMPLEX_DESCRIPTORS,
|
||||
INTERNAL_MEM_FIRST_CLIENT
|
||||
};
|
||||
|
||||
@@ -403,12 +400,14 @@ gboolean sgen_is_worker_thread (MonoNativeThreadId thread);
|
||||
typedef void (*CopyOrMarkObjectFunc) (GCObject**, SgenGrayQueue*);
|
||||
typedef void (*ScanObjectFunc) (GCObject *obj, SgenDescriptor desc, SgenGrayQueue*);
|
||||
typedef void (*ScanVTypeFunc) (GCObject *full_object, char *start, SgenDescriptor desc, SgenGrayQueue* BINARY_PROTOCOL_ARG (size_t size));
|
||||
typedef void (*ScanPtrFieldFunc) (GCObject *obj, GCObject **ptr, SgenGrayQueue* queue);
|
||||
typedef gboolean (*DrainGrayStackFunc) (SgenGrayQueue *queue);
|
||||
|
||||
typedef struct {
|
||||
CopyOrMarkObjectFunc copy_or_mark_object;
|
||||
ScanObjectFunc scan_object;
|
||||
ScanVTypeFunc scan_vtype;
|
||||
ScanPtrFieldFunc scan_ptr_field;
|
||||
/* Drain stack optimized for the above functions */
|
||||
DrainGrayStackFunc drain_gray_stack;
|
||||
/*FIXME add allocation function? */
|
||||
@@ -533,6 +532,7 @@ typedef struct {
|
||||
GCObject* (*alloc_for_promotion) (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references);
|
||||
|
||||
SgenObjectOperations serial_ops;
|
||||
SgenObjectOperations serial_ops_with_concurrent_major;
|
||||
|
||||
void (*prepare_to_space) (char *to_space_bitmap, size_t space_bitmap_size);
|
||||
void (*clear_fragments) (void);
|
||||
@@ -553,7 +553,8 @@ void sgen_split_nursery_init (SgenMinorCollector *collector);
|
||||
/* Updating references */
|
||||
|
||||
#ifdef SGEN_CHECK_UPDATE_REFERENCE
|
||||
gboolean sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId some_thread) MONO_INTERNAL;
|
||||
gboolean sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId some_thread);
|
||||
|
||||
static inline void
|
||||
sgen_update_reference (GCObject **p, GCObject *o, gboolean allow_null)
|
||||
{
|
||||
@@ -591,6 +592,12 @@ typedef struct
|
||||
size_t num_unique_scanned_objects;
|
||||
} ScannedObjectCounts;
|
||||
|
||||
typedef enum {
|
||||
CARDTABLE_SCAN_GLOBAL = 0,
|
||||
CARDTABLE_SCAN_MOD_UNION = 1,
|
||||
CARDTABLE_SCAN_MOD_UNION_PRECLEAN = CARDTABLE_SCAN_MOD_UNION | 2,
|
||||
} CardTableScanType;
|
||||
|
||||
typedef struct _SgenMajorCollector SgenMajorCollector;
|
||||
struct _SgenMajorCollector {
|
||||
size_t section_size;
|
||||
@@ -620,7 +627,7 @@ struct _SgenMajorCollector {
|
||||
void (*free_non_pinned_object) (GCObject *obj, size_t size);
|
||||
void (*pin_objects) (SgenGrayQueue *queue);
|
||||
void (*pin_major_object) (GCObject *obj, SgenGrayQueue *queue);
|
||||
void (*scan_card_table) (gboolean mod_union, ScanCopyContext ctx);
|
||||
void (*scan_card_table) (CardTableScanType scan_type, ScanCopyContext ctx);
|
||||
void (*iterate_live_block_ranges) (sgen_cardtable_block_callback callback);
|
||||
void (*update_cardtable_mod_union) (void);
|
||||
void (*init_to_space) (void);
|
||||
@@ -780,8 +787,9 @@ void sgen_process_fin_stage_entries (void);
|
||||
gboolean sgen_have_pending_finalizers (void);
|
||||
void sgen_object_register_for_finalization (GCObject *obj, void *user_data);
|
||||
|
||||
int sgen_gather_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, GCObject **out_array, int out_size);
|
||||
void sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data);
|
||||
void sgen_remove_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, int generation);
|
||||
void sgen_set_suspend_finalizers (void);
|
||||
|
||||
void sgen_register_disappearing_link (GCObject *obj, void **link, gboolean track, gboolean in_gc);
|
||||
|
||||
@@ -798,9 +806,9 @@ enum {
|
||||
void sgen_pin_object (GCObject *object, SgenGrayQueue *queue);
|
||||
void sgen_set_pinned_from_failed_allocation (mword objsize);
|
||||
|
||||
void sgen_ensure_free_space (size_t size);
|
||||
void sgen_ensure_free_space (size_t size, int generation);
|
||||
void sgen_gc_collect (int generation);
|
||||
void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish);
|
||||
void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish, gboolean stw);
|
||||
|
||||
int sgen_gc_collection_count (int generation);
|
||||
/* FIXME: what exactly does this return? */
|
||||
@@ -809,17 +817,8 @@ size_t sgen_gc_get_total_heap_allocation (void);
|
||||
|
||||
/* STW */
|
||||
|
||||
typedef struct {
|
||||
int generation;
|
||||
const char *reason;
|
||||
gboolean is_overflow;
|
||||
gint64 total_time;
|
||||
gint64 stw_time;
|
||||
gint64 bridge_time;
|
||||
} GGTimingInfo;
|
||||
|
||||
void sgen_stop_world (int generation);
|
||||
void sgen_restart_world (int generation, GGTimingInfo *timing);
|
||||
void sgen_restart_world (int generation);
|
||||
gboolean sgen_is_world_stopped (void);
|
||||
|
||||
gboolean sgen_set_allow_synchronous_major (gboolean flag);
|
||||
@@ -839,6 +838,7 @@ struct _LOSObject {
|
||||
|
||||
extern LOSObject *los_object_list;
|
||||
extern mword los_memory_usage;
|
||||
extern mword los_memory_usage_total;
|
||||
|
||||
void sgen_los_free_object (LOSObject *obj);
|
||||
void* sgen_los_alloc_large_inner (GCVTable vtable, size_t size);
|
||||
@@ -846,7 +846,7 @@ void sgen_los_sweep (void);
|
||||
gboolean sgen_ptr_is_in_los (char *ptr, char **start);
|
||||
void sgen_los_iterate_objects (IterateObjectCallbackFunc cb, void *user_data);
|
||||
void sgen_los_iterate_live_block_ranges (sgen_cardtable_block_callback callback);
|
||||
void sgen_los_scan_card_table (gboolean mod_union, ScanCopyContext ctx);
|
||||
void sgen_los_scan_card_table (CardTableScanType scan_type, ScanCopyContext ctx);
|
||||
void sgen_los_update_cardtable_mod_union (void);
|
||||
void sgen_los_count_cards (long long *num_total_cards, long long *num_marked_cards);
|
||||
gboolean sgen_los_is_valid_object (char *object);
|
||||
@@ -950,7 +950,9 @@ extern int default_nursery_size;
|
||||
extern guint32 tlab_size;
|
||||
extern NurseryClearPolicy nursery_clear_policy;
|
||||
extern gboolean sgen_try_free_some_memory;
|
||||
|
||||
extern mword total_promoted_size;
|
||||
extern mword total_allocated_major;
|
||||
extern volatile gboolean sgen_suspend_finalizers;
|
||||
extern MonoCoopMutex gc_mutex;
|
||||
|
||||
/* Nursery helpers. */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,18 +5,7 @@
|
||||
* Copyright 2003-2010 Novell, Inc.
|
||||
* 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.
|
||||
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
*/
|
||||
#include "config.h"
|
||||
#ifdef HAVE_SGEN_GC
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user