+ free_handle_chunk (c);
+ free_handle_chunk (stack->interior);
+ free_handle_stack (stack);
+}
+
+void
+mono_handle_stack_free_domain (HandleStack *stack, MonoDomain *domain)
+{
+ /* Called by the GC while clearing out objects of the given domain from the heap. */
+ /* If there are no handles-related bugs, there is nothing to do: if a
+ * thread accessed objects from the domain it was aborted, so any
+ * threads left alive cannot have any handles that point into the
+ * unloading domain. However if there is a handle leak, the handle stack is not */
+ if (!stack)
+ return;
+ /* Root domain only unloaded when mono is shutting down, don't need to check anything */
+ if (domain == mono_get_root_domain () || mono_runtime_is_shutting_down ())
+ return;
+ HandleChunk *cur = stack->bottom;
+ HandleChunk *last = stack->top;
+ if (!cur)
+ return;
+ while (cur) {
+ for (int idx = 0; idx < cur->size; ++idx) {
+ HandleChunkElem *elem = &cur->elems[idx];
+ if (!elem->o)
+ continue;
+ g_assert (mono_object_domain (elem->o) != domain);
+ }
+ if (cur == last)
+ break;
+ cur = cur->next;
+ }
+ /* We don't examine the interior pointers here because the GC treats
+ * them conservatively and anyway we don't have enough information here to
+ * find the object's vtable.
+ */
+}
+
+static void
+check_handle_stack_monotonic (HandleStack *stack)
+{
+ /* check that every allocated handle in the current handle stack is at no higher in the native stack than its predecessors */
+#ifdef MONO_HANDLE_TRACK_SP
+ HandleChunk *cur = stack->bottom;
+ HandleChunk *last = stack->top;
+ if (!cur)
+ return;
+ HandleChunkElem *prev = NULL;
+ gboolean monotonic = TRUE;
+ while (cur) {
+ for (int i = 0;i < cur->size; ++i) {
+ HandleChunkElem *elem = chunk_element (cur, i);
+ if (prev && elem->alloc_sp < prev->alloc_sp) {
+ monotonic = FALSE;
+ g_warning ("Handle %p (object %p) (allocated from \"%s\") is was allocated deeper in the call stack than its successor (allocated from \"%s\").", prev, prev->o,
+#ifdef MONO_HANDLE_TRACK_OWNER
+ prev->owner,
+ elem->owner
+#else
+ "unknown owner",
+ "unknown owner"
+#endif
+ );
+
+ }
+ prev = elem;
+ }
+ if (cur == last)
+ break;
+ cur = cur->next;
+ }
+ g_assert (monotonic);
+#endif