X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fsgen%2Fsgen-copy-object.h;h=bb97e4a681689a2000318aeed0de938f8d8bfff6;hb=HEAD;hp=2b7bc60670a3751b20566b5c35f100d1b0d8ecf8;hpb=e137ff6f7e2594d3ce96b4c74b528d26cc80e11d;p=mono.git diff --git a/mono/sgen/sgen-copy-object.h b/mono/sgen/sgen-copy-object.h index 2b7bc60670a..bb97e4a6816 100644 --- a/mono/sgen/sgen-copy-object.h +++ b/mono/sgen/sgen-copy-object.h @@ -1,22 +1,33 @@ -/* - * sgen-copy-object.h: This is where objects are copied. +/** + * \file + * This is where objects are copied. * * Copyright 2001-2003 Ximian, Inc * 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; + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +/* + * Defines + * + * GCObject* copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue) + * + * which allocates new space for `obj`, copies it there, forwards `obj` to its new location, + * and enqueues the copy into `queue`. + * + * To be defined by the includer: + * + * COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION(vt, obj, objsize, has_refs) * - * 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. + * Allocates space for promoting object `obj`, with size `objsize`, and initizializes the + * vtable with `vt`. `has_refs` indicates whether the object contains references. * - * 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. + * collector_pin_object(obj, queue) + * + * Called when no space for `obj` could be allocated. It must pin `obj` and enqueue it into + * `queue` for scanning. */ extern guint64 stat_copy_object_called_nursery; @@ -29,13 +40,11 @@ extern guint64 stat_nursery_copy_object_failed_pinned; extern guint64 stat_slots_allocated_in_vain; /* - * Copies an object and enqueues it if a queue is given. - * * This function can be used even if the vtable of obj is not valid * anymore, which is the case in the parallel collector. */ static MONO_ALWAYS_INLINE void -par_copy_object_no_checks (char *destination, GCVTable vt, void *obj, mword objsize, SgenGrayQueue *queue) +par_copy_object_no_checks (char *destination, GCVTable vt, void *obj, mword objsize) { sgen_client_pre_copy_checks (destination, vt, obj, objsize); binary_protocol_copy (obj, destination, vt, objsize); @@ -47,14 +56,10 @@ par_copy_object_no_checks (char *destination, GCVTable vt, void *obj, mword objs SGEN_ASSERT (9, sgen_vtable_get_descriptor (vt), "vtable %p has no gc descriptor", vt); sgen_client_update_copied_object (destination, vt, obj, objsize); - obj = destination; - if (queue) { - SGEN_LOG (9, "Enqueuing gray object %p (%s)", obj, sgen_client_vtable_get_name (vt)); - GRAY_OBJECT_ENQUEUE (queue, (GCObject *)obj, sgen_vtable_get_descriptor (vt)); - } } /* + * Copies an object and enqueues it if a queue is given. * This can return OBJ itself on OOM. */ static MONO_NEVER_INLINE GCObject * @@ -63,7 +68,6 @@ copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue) GCVTable vt = SGEN_LOAD_VTABLE_UNCHECKED (obj); gboolean has_references = SGEN_VTABLE_HAS_REFERENCES (vt); mword objsize = SGEN_ALIGN_UP (sgen_client_par_object_get_size (vt, obj)); - /* FIXME: Does this not mark the newly allocated object? */ void *destination = COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION (vt, obj, objsize, has_references); if (G_UNLIKELY (!destination)) { @@ -73,14 +77,68 @@ copy_object_no_checks (GCObject *obj, SgenGrayQueue *queue) return obj; } - if (!has_references) - queue = NULL; - - par_copy_object_no_checks ((char *)destination, vt, obj, objsize, queue); - /* FIXME: mark mod union cards if necessary */ + par_copy_object_no_checks ((char *)destination, vt, obj, objsize); /* set the forwarding pointer */ SGEN_FORWARD_OBJECT (obj, destination); + if (has_references) { + SGEN_LOG (9, "Enqueuing gray object %p (%s)", destination, sgen_client_vtable_get_name (vt)); + GRAY_OBJECT_ENQUEUE_SERIAL (queue, (GCObject *)destination, sgen_vtable_get_descriptor (vt)); + } + return (GCObject *)destination; } + +#if defined(COPY_OR_MARK_PARALLEL) +static MONO_NEVER_INLINE GCObject * +copy_object_no_checks_par (GCObject *obj, SgenGrayQueue *queue) +{ + mword vtable_word = *(mword*)obj; + GCObject *destination; + + destination = (GCObject*) SGEN_VTABLE_IS_FORWARDED (vtable_word); + + if (!destination) { + GCVTable vt = (GCVTable) vtable_word; + GCObject *final_destination; + /* + * At this point we know vt is not tagged and we shouldn't access the vtable through obj + * since it could get copied at any time by another thread. + */ + gboolean has_references = SGEN_VTABLE_HAS_REFERENCES (vt); + mword objsize = SGEN_ALIGN_UP (sgen_client_par_object_get_size (vt, obj)); + destination = COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION (vt, obj, objsize, has_references); + + par_copy_object_no_checks ((char*)destination, vt, obj, objsize); + + /* FIXME we might need a membar here so other threads see the vtable before we forward */ + + /* set the forwarding pointer */ + SGEN_FORWARD_OBJECT_PAR (obj, destination, final_destination); + + if (destination == final_destination) { + /* In a racing case, only the worker that allocated the object enqueues it */ + if (has_references) { + SGEN_LOG (9, "Enqueuing gray object %p (%s)", destination, sgen_client_vtable_get_name (vt)); + GRAY_OBJECT_ENQUEUE_PARALLEL (queue, (GCObject *)destination, sgen_vtable_get_descriptor (vt)); + } + } else { + /* + * Unlikely case. Clear the allocated object so it doesn't confuse nursery + * card table scanning, since it can contain old invalid refs. + * FIXME make sure it is not a problem if another threads scans it while we clear + */ + mono_gc_bzero_aligned (destination, objsize); + destination = final_destination; + } + } + + return destination; +} +#endif + +#undef COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION +#undef COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION +#undef collector_pin_object +#undef COPY_OR_MARK_PARALLEL