mono_handle_new_interior (gpointer rawptr, const char *owner) #endif { MonoThreadInfo *info = mono_thread_info_current (); HandleStack *handles = (HandleStack *)info->handle_stack; HandleChunk *top = handles->interior; #ifdef MONO_HANDLE_TRACK_SP mono_handle_chunk_leak_check (handles); #endif g_assert (top); /* * Don't extend the chunk now, interior handles are * only used for icall arguments, they shouldn't * overflow. */ g_assert (top->size < OBJECTS_PER_HANDLES_CHUNK); int idx = top->size; gpointer *objslot = &top->elems [idx].o; *objslot = NULL; mono_memory_write_barrier (); top->size++; mono_memory_write_barrier (); *objslot = rawptr; SET_OWNER (top,idx); SET_SP (handles, top, idx); return objslot; }
mono_handle_new (MonoObject *obj, MonoThreadInfo *info, const char *owner) #endif { info = info ? info : mono_thread_info_current (); HandleStack *handles = info->handle_stack; HandleChunk *top = handles->top; #ifdef MONO_HANDLE_TRACK_SP mono_handle_chunk_leak_check (handles); #endif retry: if (G_LIKELY (top->size < OBJECTS_PER_HANDLES_CHUNK)) { int idx = top->size; gpointer* objslot = &top->elems [idx].o; /* can be interrupted anywhere here, so: * 1. make sure the new slot is null * 2. make the new slot scannable (increment size) * 3. put a valid object in there * * (have to do 1 then 3 so that if we're interrupted * between 1 and 2, the object is still live) */ *objslot = NULL; SET_OWNER (top,idx); SET_SP (handles, top, idx); mono_memory_write_barrier (); top->size++; mono_memory_write_barrier (); *objslot = obj; return objslot; } if (G_LIKELY (top->next)) { top->next->size = 0; /* make sure size == 0 is visible to a GC thread before it sees the new top */ mono_memory_write_barrier (); top = top->next; handles->top = top; goto retry; } HandleChunk *new_chunk = new_handle_chunk (); new_chunk->size = 0; new_chunk->prev = top; new_chunk->next = NULL; /* make sure size == 0 before new chunk is visible */ mono_memory_write_barrier (); top->next = new_chunk; handles->top = new_chunk; goto retry; }