mono_gc_run_finalize (void * obj, void * data)
{
  sizetype data.0;
  int suspend_finalizers.1;
  struct MonoVTable * D.21222;
  struct MonoClass * D.21223;
  struct MonoClass * D.21224;
  int D.21227;
  unsigned char D.21230;
  int finalizing_root_domain.2;
  struct MonoImage * D.21236;
  struct MonoImage * D.21237;
  int D.20868;
  int iftmp.3;
  int D.20867;
  const char[14] * D.21243;
  unsigned char D.21244;
  int D.21245;
  unsigned char D.21246;
  int D.21247;
  _Bool D.21248;
  _Bool D.21249;
  _Bool D.21250;
  const unsigned char * D.21253;
  unsigned char D.21254;
  int D.21255;
  const unsigned char * D.21256;
  unsigned char D.21257;
  int D.21258;
  _Bool D.21259;
  _Bool D.21260;
  const unsigned char * D.21263;
  unsigned char D.21264;
  int D.21265;
  const unsigned char * D.21266;
  unsigned char D.21267;
  int D.21268;
  _Bool D.21269;
  _Bool D.21270;
  const unsigned char * D.21273;
  unsigned char D.21274;
  int D.21275;
  const unsigned char * D.21276;
  unsigned char D.21277;
  int D.21278;
  const char * D.21280;
  int D.21285;
  struct MonoDomain * D.21288;
  unsigned char D.21289;
  unsigned char D.21290;
  void * D.21293;
  int D.21296;
  void * D.21301;
  struct MonoClass * D.21304;
  struct MonoMethod * D.21305;
  void * D.21306;
  struct MonoObject * exc.4;
  struct MonoObject * exc;
  struct MonoObject * o;
  struct MonoMethod * finalizer;
  struct MonoDomain * caller_domain;
  struct MonoDomain * domain;
  struct MonoObject * (*RuntimeInvokeFunction) (struct MonoObject *, void * *, struct MonoObject * *, void *) runtime_invoke;

  try
    {
      exc = 0B;
      finalizer = 0B;
      caller_domain = mono_domain_get ();
      data.0 = (sizetype) data;
      o = obj + data.0;
      suspend_finalizers.1 = suspend_finalizers;
      if (suspend_finalizers.1 != 0) goto <D.21220>; else goto <D.21221>;
      <D.21220>:
      return;
      <D.21221>:
      D.21222 = o->vtable;
      domain = D.21222->domain;
      object_register_finalizer (obj, 0B);
      D.21222 = o->vtable;
      D.21223 = D.21222->klass;
      D.21224 = mono_defaults.internal_thread_class;
      if (D.21223 == D.21224) goto <D.21225>; else goto <D.21226>;
      <D.21225>:
      {
        struct MonoInternalThread * t;

        t = o;
        D.21227 = mono_gc_is_finalizer_internal_thread (t);
        if (D.21227 != 0) goto <D.21228>; else goto <D.21229>;
        <D.21228>:
        return;
        <D.21229>:
        D.21230 = t->threadpool_thread;
        if (D.21230 != 0) goto <D.21231>; else goto <D.21232>;
        <D.21231>:
        finalizing_root_domain.2 = finalizing_root_domain;
        if (finalizing_root_domain.2 != 0) goto <D.21234>; else goto <D.21235>;
        <D.21234>:
        add_thread_to_finalize (t);
        return;
        <D.21235>:
        <D.21232>:
      }
      <D.21226>:
      D.21222 = o->vtable;
      D.21223 = D.21222->klass;
      D.21236 = D.21223->image;
      D.21237 = mono_defaults.corlib;
      if (D.21236 == D.21237) goto <D.21238>; else goto <D.21239>;
      <D.21238>:
      {
        size_t __s1_len;
        size_t __s2_len;

        __s2_len = 13;
        if (__s2_len <= 3) goto <D.21241>; else goto <D.21242>;
        <D.21241>:
        {
          const unsigned char * __s2;
          int __result;

          D.21222 = o->vtable;
          D.21223 = D.21222->klass;
          __s2 = D.21223->name;
          D.21243 = "DynamicMethod";
          D.21244 = MEM[(const unsigned char *)D.21243];
          D.21245 = (int) D.21244;
          D.21246 = *__s2;
          D.21247 = (int) D.21246;
          __result = D.21245 - D.21247;
          {
            D.21248 = __s2_len != 0;
            D.21249 = __result == 0;
            D.21250 = D.21248 & D.21249;
            if (D.21250 != 0) goto <D.21251>; else goto <D.21252>;
            <D.21251>:
            D.21253 = &MEM[(void *)"DynamicMethod" + 1B];
            D.21254 = *D.21253;
            D.21255 = (int) D.21254;
            D.21256 = __s2 + 1;
            D.21257 = *D.21256;
            D.21258 = (int) D.21257;
            __result = D.21255 - D.21258;
            D.21259 = __s2_len > 1;
            D.21249 = __result == 0;
            D.21260 = D.21259 & D.21249;
            if (D.21260 != 0) goto <D.21261>; else goto <D.21262>;
            <D.21261>:
            D.21263 = &MEM[(void *)"DynamicMethod" + 2B];
            D.21264 = *D.21263;
            D.21265 = (int) D.21264;
            D.21266 = __s2 + 2;
            D.21267 = *D.21266;
            D.21268 = (int) D.21267;
            __result = D.21265 - D.21268;
            D.21269 = __s2_len > 2;
            D.21249 = __result == 0;
            D.21270 = D.21269 & D.21249;
            if (D.21270 != 0) goto <D.21271>; else goto <D.21272>;
            <D.21271>:
            D.21273 = &MEM[(void *)"DynamicMethod" + 3B];
            D.21274 = *D.21273;
            D.21275 = (int) D.21274;
            D.21276 = __s2 + 3;
            D.21277 = *D.21276;
            D.21278 = (int) D.21277;
            __result = D.21275 - D.21278;
            <D.21272>:
            <D.21262>:
            <D.21252>:
          }
          D.20867 = __result;
        }
        iftmp.3 = -D.20867;
        goto <D.21279>;
        <D.21242>:
        D.21222 = o->vtable;
        D.21223 = D.21222->klass;
        D.21280 = D.21223->name;
        iftmp.3 = __builtin_strcmp (D.21280, "DynamicMethod");
        <D.21279>:
        D.20868 = iftmp.3;
      }
      if (D.20868 == 0) goto <D.21281>; else goto <D.21282>;
      <D.21281>:
      finalizing_root_domain.2 = finalizing_root_domain;
      if (finalizing_root_domain.2 != 0) goto <D.21283>; else goto <D.21284>;
      <D.21283>:
      return;
      <D.21284>:
      <D.21282>:
      <D.21239>:
      D.21285 = mono_runtime_get_no_exec ();
      if (D.21285 != 0) goto <D.21286>; else goto <D.21287>;
      <D.21286>:
      return;
      <D.21287>:
      D.21222 = o->vtable;
      D.21288 = D.21222->domain;
      mono_domain_set_internal (D.21288);
      D.21222 = o->vtable;
      D.21223 = D.21222->klass;
      D.21289 = BIT_FIELD_REF <*D.21223, 8, 184>;
      D.21290 = D.21289 & 1;
      if (D.21290 != 0) goto <D.21291>; else goto <D.21292>;
      <D.21291>:
      {
        struct MonoDelegate * del;

        del = o;
        D.21293 = del->delegate_trampoline;
        if (D.21293 != 0B) goto <D.21294>; else goto <D.21295>;
        <D.21294>:
        mono_delegate_free_ftnptr (o);
        <D.21295>:
        mono_domain_set_internal (caller_domain);
        return;
      }
      <D.21292>:
      D.21222 = o->vtable;
      D.21223 = D.21222->klass;
      finalizer = mono_class_get_finalizer (D.21223);
      D.21296 = mono_marshal_free_ccw (o);
      if (D.21296 != 0) goto <D.21297>; else goto <D.21298>;
      <D.21297>:
      if (finalizer == 0B) goto <D.21299>; else goto <D.21300>;
      <D.21299>:
      mono_domain_set_internal (caller_domain);
      return;
      <D.21300>:
      <D.21298>:
      D.21301 = domain->finalize_runtime_invoke;
      if (D.21301 == 0B) goto <D.21302>; else goto <D.21303>;
      <D.21302>:
      {
        struct MonoMethod * invoke;

        D.21304 = mono_defaults.object_class;
        D.21305 = mono_class_get_method_from_name_flags (D.21304, "Finalize", 0, 0);
        invoke = mono_marshal_get_runtime_invoke (D.21305, 1);
        D.21306 = mono_compile_method (invoke);
        domain->finalize_runtime_invoke = D.21306;
      }
      <D.21303>:
      D.21301 = domain->finalize_runtime_invoke;
      runtime_invoke = (struct MonoObject * (*RuntimeInvokeFunction) (struct MonoObject *, void * *, struct MonoObject * *, void *)) D.21301;
      D.21222 = o->vtable;
      mono_runtime_class_init (D.21222);
      if (0 != 0) goto <D.21307>; else goto <D.21308>;
      <D.21307>:
      <D.21308>:
      runtime_invoke (o, 0B, &exc, 0B);
      exc.4 = exc;
      if (exc.4 != 0B) goto <D.21310>; else goto <D.21311>;
      <D.21310>:
      exc.4 = exc;
      mono_internal_thread_unhandled_exception (exc.4);
      <D.21311>:
      mono_domain_set_internal (caller_domain);
    }
  finally
    {
      exc = {CLOBBER};
    }
}


object_register_finalizer (struct MonoObject * obj, void (*<Tff>) (void *, void *) callback)
{
  struct MonoException * D.21317;
  struct MonoVTable * D.21318;
  int D.21319;
  struct MonoDomain * domain;

  if (obj == 0B) goto <D.21315>; else goto <D.21316>;
  <D.21315>:
  D.21317 = mono_get_exception_argument_null ("obj");
  mono_raise_exception (D.21317);
  <D.21316>:
  D.21318 = obj->vtable;
  domain = D.21318->domain;
  D.21319 = mono_domain_is_unloading (domain);
  if (D.21319 == 0) goto <D.21320>; else goto <D.21321>;
  <D.21320>:
  mono_gc_register_for_finalization (obj, callback);
  <D.21321>:
}


add_thread_to_finalize (struct MonoInternalThread * thread)
{
  _Bool D.21324;
  long int D.21325;
  long int D.21326;
  struct MonoMList * threads_to_finalize.5;
  void * D.21334;
  struct MonoMList * threads_to_finalize.6;
  _Bool D.21338;
  long int D.21339;
  long int D.21340;

  {
    int ret;

    ret = pthread_mutex_lock (&finalizer_mutex.mutex);
    if (ret != 0) goto <D.21322>; else goto <D.21323>;
    <D.21322>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21323>:
    D.21324 = ret != 0;
    D.21325 = (long int) D.21324;
    D.21326 = __builtin_expect (D.21325, 0);
    if (D.21326 != 0) goto <D.21327>; else goto <D.21328>;
    <D.21327>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 88, "ret == 0");
    <D.21328>:
  }
  threads_to_finalize.5 = threads_to_finalize;
  if (threads_to_finalize.5 == 0B) goto <D.21330>; else goto <D.21331>;
  <D.21330>:
  if (0 != 0) goto <D.21332>; else goto <D.21333>;
  <D.21332>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 90, "sizeof (threads_to_finalize) == sizeof (MonoObject*)");
  <D.21333>:
  D.21334 = mono_gc_make_root_descr_all_refs (1);
  mono_gc_register_root (&threads_to_finalize, 4, D.21334);
  <D.21331>:
  threads_to_finalize.5 = threads_to_finalize;
  threads_to_finalize.6 = mono_mlist_append (threads_to_finalize.5, thread);
  threads_to_finalize = threads_to_finalize.6;
  {
    int ret;

    ret = pthread_mutex_unlock (&finalizer_mutex.mutex);
    if (ret != 0) goto <D.21336>; else goto <D.21337>;
    <D.21336>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21337>:
    D.21338 = ret != 0;
    D.21339 = (long int) D.21338;
    D.21340 = __builtin_expect (D.21339, 0);
    if (D.21340 != 0) goto <D.21341>; else goto <D.21342>;
    <D.21341>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 92, "ret == 0");
    <D.21342>:
  }
}


mono_gc_finalize_threadpool_threads ()
{
  struct MonoMList * threads_to_finalize.7;
  struct MonoMList * threads_to_finalize.8;

  goto <D.20876>;
  <D.20875>:
  {
    struct MonoInternalThread * thread;

    threads_to_finalize.7 = threads_to_finalize;
    thread = mono_mlist_get_data (threads_to_finalize.7);
    thread->threadpool_thread = 0;
    mono_object_register_finalizer (thread);
    mono_gc_run_finalize (thread, 0B);
    threads_to_finalize.7 = threads_to_finalize;
    threads_to_finalize.8 = mono_mlist_next (threads_to_finalize.7);
    threads_to_finalize = threads_to_finalize.8;
  }
  <D.20876>:
  threads_to_finalize.7 = threads_to_finalize;
  if (threads_to_finalize.7 != 0B) goto <D.20875>; else goto <D.20877>;
  <D.20877>:
}


mono_gc_out_of_memory (size_t size)
{
  struct MonoDomain * D.21345;
  struct MonoException * D.21346;
  void * D.21347;

  D.21345 = mono_domain_get ();
  D.21346 = D.21345->out_of_memory_ex;
  mono_raise_exception (D.21346);
  D.21347 = 0B;
  return D.21347;
}


mono_object_register_finalizer (struct MonoObject * obj)
{
  object_register_finalizer (obj, mono_gc_run_finalize);
}


mono_domain_finalize (struct MonoDomain * domain, guint32 timeout)
{
  struct MonoInternalThread * D.21349;
  struct MonoInternalThread * gc_thread.9;
  mono_bool D.21353;
  int gc_disabled.10;
  int D.21357;
  struct MonoDomain * D.21360;
  _Bool D.21365;
  long int D.21366;
  long int D.21367;
  struct GSList * domains_to_finalize.11;
  struct GSList * domains_to_finalize.12;
  _Bool D.21374;
  long int D.21375;
  long int D.21376;
  unsigned int D.21383;
  unsigned int D.21384;
  struct MonoDomain * D.21389;
  struct DomainFinalizationReq * req;
  guint32 res;
  void * done_event;
  struct MonoInternalThread * thread;

  thread = mono_thread_internal_current ();
  D.21349 = mono_thread_internal_current ();
  gc_thread.9 = gc_thread;
  if (D.21349 == gc_thread.9) goto <D.21351>; else goto <D.21352>;
  <D.21351>:
  D.21353 = 0;
  return D.21353;
  <D.21352>:
  gc_disabled.10 = gc_disabled;
  if (gc_disabled.10 != 0) goto <D.21355>; else goto <D.21356>;
  <D.21355>:
  D.21353 = 1;
  return D.21353;
  <D.21356>:
  D.21357 = mono_gc_max_generation ();
  mono_gc_collect (D.21357);
  done_event = CreateEvent (0B, 1, 0, 0B);
  if (done_event == 0B) goto <D.21358>; else goto <D.21359>;
  <D.21358>:
  D.21353 = 0;
  return D.21353;
  <D.21359>:
  req = monoeg_malloc0 (8);
  req->domain = domain;
  req->done_event = done_event;
  D.21360 = mono_get_root_domain ();
  if (D.21360 == domain) goto <D.21361>; else goto <D.21362>;
  <D.21361>:
  finalizing_root_domain = 1;
  <D.21362>:
  {
    int ret;

    ret = pthread_mutex_lock (&finalizer_mutex.mutex);
    if (ret != 0) goto <D.21363>; else goto <D.21364>;
    <D.21363>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21364>:
    D.21365 = ret != 0;
    D.21366 = (long int) D.21365;
    D.21367 = __builtin_expect (D.21366, 0);
    if (D.21367 != 0) goto <D.21368>; else goto <D.21369>;
    <D.21368>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 367, "ret == 0");
    <D.21369>:
  }
  domains_to_finalize.11 = domains_to_finalize;
  domains_to_finalize.12 = monoeg_g_slist_append (domains_to_finalize.11, req);
  domains_to_finalize = domains_to_finalize.12;
  {
    int ret;

    ret = pthread_mutex_unlock (&finalizer_mutex.mutex);
    if (ret != 0) goto <D.21372>; else goto <D.21373>;
    <D.21372>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21373>:
    D.21374 = ret != 0;
    D.21375 = (long int) D.21374;
    D.21376 = __builtin_expect (D.21375, 0);
    if (D.21376 != 0) goto <D.21377>; else goto <D.21378>;
    <D.21377>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 371, "ret == 0");
    <D.21378>:
  }
  mono_gc_finalize_notify ();
  if (timeout == 4294967295) goto <D.21379>; else goto <D.21380>;
  <D.21379>:
  timeout = 4294967295;
  <D.21380>:
  <D.20902>:
  res = WaitForSingleObjectEx (done_event, timeout, 1);
  if (res == 192) goto <D.21381>; else goto <D.21382>;
  <D.21381>:
  D.21383 = thread->state;
  D.21384 = D.21383 & 3;
  if (D.21384 != 0) goto <D.21385>; else goto <D.21386>;
  <D.21385>:
  D.21353 = 0;
  return D.21353;
  <D.21386>:
  goto <D.21387>;
  <D.21382>:
  if (res == 258) goto <D.21388>; else goto <D.20901>;
  <D.21388>:
  D.21353 = 0;
  return D.21353;
  <D.21387>:
  goto <D.20902>;
  <D.20901>:
  CloseHandle (done_event);
  D.21389 = mono_get_root_domain ();
  if (D.21389 == domain) goto <D.21390>; else goto <D.21391>;
  <D.21390>:
  mono_thread_pool_cleanup ();
  mono_gc_finalize_threadpool_threads ();
  <D.21391>:
  D.21353 = 1;
  return D.21353;
}


ves_icall_System_GC_InternalCollect (int generation)
{
  mono_gc_collect (generation);
}


ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection)
{
  int D.21395;
  gint64 D.21396;

  if (forceCollection != 0) goto <D.21393>; else goto <D.21394>;
  <D.21393>:
  D.21395 = mono_gc_max_generation ();
  mono_gc_collect (D.21395);
  <D.21394>:
  D.21396 = mono_gc_get_used_size ();
  return D.21396;
}


ves_icall_System_GC_KeepAlive (struct MonoObject * obj)
{

}


ves_icall_System_GC_ReRegisterForFinalize (struct MonoObject * obj)
{
  struct MonoException * D.21400;

  if (obj == 0B) goto <D.21398>; else goto <D.21399>;
  <D.21398>:
  D.21400 = mono_get_exception_argument_null ("obj");
  mono_raise_exception (D.21400);
  <D.21399>:
  object_register_finalizer (obj, mono_gc_run_finalize);
}


ves_icall_System_GC_SuppressFinalize (struct MonoObject * obj)
{
  struct MonoException * D.21403;
  struct MonoVTable * D.21404;
  struct MonoClass * D.21405;
  unsigned char D.21406;
  unsigned char D.21407;

  if (obj == 0B) goto <D.21401>; else goto <D.21402>;
  <D.21401>:
  D.21403 = mono_get_exception_argument_null ("obj");
  mono_raise_exception (D.21403);
  <D.21402>:
  D.21404 = obj->vtable;
  D.21405 = D.21404->klass;
  D.21406 = BIT_FIELD_REF <*D.21405, 8, 184>;
  D.21407 = D.21406 & 1;
  if (D.21407 != 0) goto <D.21408>; else goto <D.21409>;
  <D.21408>:
  return;
  <D.21409>:
  object_register_finalizer (obj, 0B);
}


ves_icall_System_GC_WaitForPendingFinalizers ()
{
  int D.21411;
  struct MonoInternalThread * D.21414;
  struct MonoInternalThread * gc_thread.13;
  void * pending_done_event.14;

  D.21411 = mono_gc_pending_finalizers ();
  if (D.21411 == 0) goto <D.21412>; else goto <D.21413>;
  <D.21412>:
  return;
  <D.21413>:
  D.21414 = mono_thread_internal_current ();
  gc_thread.13 = gc_thread;
  if (D.21414 == gc_thread.13) goto <D.21416>; else goto <D.21417>;
  <D.21416>:
  return;
  <D.21417>:
  gc_thread.13 = gc_thread;
  if (gc_thread.13 == 0B) goto <D.21418>; else goto <D.21419>;
  <D.21418>:
  return;
  <D.21419>:
  pending_done_event.14 = pending_done_event;
  ResetEvent (pending_done_event.14);
  mono_gc_finalize_notify ();
  pending_done_event.14 = pending_done_event;
  WaitForSingleObjectEx (pending_done_event.14, 4294967295, 1);
}


ves_icall_System_GC_register_ephemeron_array (struct MonoObject * array)
{
  int D.21422;
  struct MonoVTable * D.21425;
  struct MonoDomain * D.21426;
  struct MonoException * D.21427;

  D.21422 = mono_gc_ephemeron_array_add (array);
  if (D.21422 == 0) goto <D.21423>; else goto <D.21424>;
  <D.21423>:
  D.21425 = array->vtable;
  D.21426 = D.21425->domain;
  D.21427 = D.21426->out_of_memory_ex;
  mono_raise_exception (D.21427);
  <D.21424>:
}


ves_icall_System_GC_get_ephemeron_tombstone ()
{
  struct MonoObject * D.21428;
  struct MonoDomain * D.21429;

  D.21429 = mono_domain_get ();
  D.21428 = D.21429->ephemeron_tombstone;
  return D.21428;
}


ves_icall_System_GCHandle_GetTarget (guint32 handle)
{
  struct MonoObject * D.21431;

  D.21431 = mono_gchandle_get_target (handle);
  return D.21431;
}


ves_icall_System_GCHandle_GetTargetHandle (struct MonoObject * obj, guint32 handle, gint32 type)
{
  guint32 D.21435;

  if (type == -1) goto <D.21433>; else goto <D.21434>;
  <D.21433>:
  mono_gchandle_set_target (handle, obj);
  D.21435 = handle;
  return D.21435;
  <D.21434>:
  switch (type) <default: <D.20949>, case 0: <D.20945>, case 1: <D.20946>, case 2: <D.20947>, case 3: <D.20948>>
  <D.20945>:
  D.21435 = mono_gchandle_new_weakref (obj, 0);
  return D.21435;
  <D.20946>:
  D.21435 = mono_gchandle_new_weakref (obj, 1);
  return D.21435;
  <D.20947>:
  D.21435 = mono_gchandle_new (obj, 0);
  return D.21435;
  <D.20948>:
  D.21435 = mono_gchandle_new (obj, 1);
  return D.21435;
  <D.20949>:
  monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "gc.c", 545);
  D.21435 = 0;
  return D.21435;
}


mono_gchandle_set_target (guint32 gchandle, struct MonoObject * obj)
{
  unsigned int D.21437;
  _Bool D.21442;
  long int D.21443;
  long int D.21444;
  unsigned int D.21447;
  guint32 * D.21450;
  unsigned int D.21451;
  unsigned int D.21452;
  guint32 * D.21453;
  unsigned int D.21454;
  int slot.15;
  int D.21456;
  int D.21457;
  unsigned int D.21458;
  unsigned int D.21459;
  unsigned char D.21462;
  void * * D.21465;
  unsigned int D.21466;
  void * * D.21467;
  void * D.21468;
  void * * D.21471;
  _Bool D.21472;
  int D.21473;
  guint16 * D.21476;
  unsigned int D.21477;
  guint16 * D.21478;
  struct MonoDomain * iftmp.16;
  int D.21483;
  short unsigned int D.21484;
  _Bool D.21489;
  long int D.21490;
  long int D.21491;
  guint slot;
  guint type;
  struct HandleData * handles;
  struct MonoObject * old_obj;

  slot = gchandle >> 3;
  D.21437 = gchandle & 7;
  type = D.21437 + 4294967295;
  handles = &gc_handles[type];
  old_obj = 0B;
  if (type > 3) goto <D.21438>; else goto <D.21439>;
  <D.21438>:
  return;
  <D.21439>:
  {
    int ret;

    ret = pthread_mutex_lock (&handle_section.mutex);
    if (ret != 0) goto <D.21440>; else goto <D.21441>;
    <D.21440>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21441>:
    D.21442 = ret != 0;
    D.21443 = (long int) D.21442;
    D.21444 = __builtin_expect (D.21443, 0);
    if (D.21444 != 0) goto <D.21445>; else goto <D.21446>;
    <D.21445>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 834, "ret == 0");
    <D.21446>:
  }
  D.21447 = handles->size;
  if (D.21447 > slot) goto <D.21448>; else goto <D.21449>;
  <D.21448>:
  D.21450 = handles->bitmap;
  D.21451 = slot / 32;
  D.21452 = D.21451 * 4;
  D.21453 = D.21450 + D.21452;
  D.21454 = *D.21453;
  slot.15 = (int) slot;
  D.21456 = slot.15 & 31;
  D.21457 = 1 << D.21456;
  D.21458 = (unsigned int) D.21457;
  D.21459 = D.21454 & D.21458;
  if (D.21459 != 0) goto <D.21460>; else goto <D.21461>;
  <D.21460>:
  D.21462 = handles->type;
  if (D.21462 <= 1) goto <D.21463>; else goto <D.21464>;
  <D.21463>:
  D.21465 = handles->entries;
  D.21466 = slot * 4;
  D.21467 = D.21465 + D.21466;
  old_obj = *D.21467;
  D.21465 = handles->entries;
  D.21466 = slot * 4;
  D.21467 = D.21465 + D.21466;
  D.21468 = *D.21467;
  if (D.21468 != 0B) goto <D.21469>; else goto <D.21470>;
  <D.21469>:
  D.21465 = handles->entries;
  D.21466 = slot * 4;
  D.21471 = D.21465 + D.21466;
  D.21462 = handles->type;
  D.21472 = D.21462 == 1;
  D.21473 = (int) D.21472;
  mono_gc_weak_link_remove (D.21471, D.21473);
  <D.21470>:
  if (obj != 0B) goto <D.21474>; else goto <D.21475>;
  <D.21474>:
  D.21465 = handles->entries;
  D.21466 = slot * 4;
  D.21471 = D.21465 + D.21466;
  D.21462 = handles->type;
  D.21472 = D.21462 == 1;
  D.21473 = (int) D.21472;
  mono_gc_weak_link_add (D.21471, obj, D.21473);
  <D.21475>:
  D.21476 = handles->domain_ids;
  D.21477 = slot * 2;
  D.21478 = D.21476 + D.21477;
  if (obj != 0B) goto <D.21480>; else goto <D.21481>;
  <D.21480>:
  iftmp.16 = mono_object_get_domain (obj);
  goto <D.21482>;
  <D.21481>:
  iftmp.16 = mono_domain_get ();
  <D.21482>:
  D.21483 = iftmp.16->domain_id;
  D.21484 = (short unsigned int) D.21483;
  *D.21478 = D.21484;
  goto <D.21485>;
  <D.21464>:
  D.21465 = handles->entries;
  D.21466 = slot * 4;
  D.21467 = D.21465 + D.21466;
  *D.21467 = obj;
  <D.21485>:
  goto <D.21486>;
  <D.21461>:
  <D.21486>:
  <D.21449>:
  {
    int ret;

    ret = pthread_mutex_unlock (&handle_section.mutex);
    if (ret != 0) goto <D.21487>; else goto <D.21488>;
    <D.21487>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21488>:
    D.21489 = ret != 0;
    D.21490 = (long int) D.21489;
    D.21491 = __builtin_expect (D.21490, 0);
    if (D.21491 != 0) goto <D.21492>; else goto <D.21493>;
    <D.21492>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 851, "ret == 0");
    <D.21493>:
  }
}


ves_icall_System_GCHandle_FreeHandle (guint32 handle)
{
  mono_gchandle_free (handle);
}


ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle)
{
  <unnamed type> D.21495;
  void * D.21498;
  struct MonoVTable * D.21501;
  struct MonoClass * D.21502;
  unsigned char D.21505;
  unsigned int D.21508;
  unsigned int D.21509;
  struct MonoObject * obj;

  D.21495 = mono_gchandle_get_type (handle);
  if (D.21495 != 3) goto <D.21496>; else goto <D.21497>;
  <D.21496>:
  D.21498 = 4294967294B;
  return D.21498;
  <D.21497>:
  obj = mono_gchandle_get_target (handle);
  if (obj != 0B) goto <D.21499>; else goto <D.21500>;
  <D.21499>:
  {
    struct MonoClass * klass;

    D.21501 = obj->vtable;
    klass = D.21501->klass;
    D.21502 = mono_defaults.string_class;
    if (D.21502 == klass) goto <D.21503>; else goto <D.21504>;
    <D.21503>:
    D.21498 = mono_string_chars (obj);
    return D.21498;
    <D.21504>:
    D.21505 = klass->rank;
    if (D.21505 != 0) goto <D.21506>; else goto <D.21507>;
    <D.21506>:
    D.21498 = mono_array_addr_with_size (obj, 1, 0);
    return D.21498;
    <D.21507>:
    D.21508 = klass->flags;
    D.21509 = D.21508 & 24;
    if (D.21509 == 0) goto <D.21510>; else goto <D.21511>;
    <D.21510>:
    D.21498 = 4294967295B;
    return D.21498;
    <D.21511>:
    D.21498 = obj + 8;
    return D.21498;
  }
  <D.21500>:
  D.21498 = 0B;
  return D.21498;
}


mono_gchandle_get_type (guint32 gchandle)
{
  unsigned int D.21513;
  HandleType D.21514;
  guint type;

  D.21513 = gchandle & 7;
  type = D.21513 + 4294967295;
  D.21514 = type;
  return D.21514;
}


ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor (MonoBoolean flag)
{
  MonoBoolean D.21516;
  int D.21517;
  int D.21518;

  D.21517 = (int) flag;
  D.21518 = mono_gc_set_allow_synchronous_major (D.21517);
  D.21516 = (MonoBoolean) D.21518;
  return D.21516;
}


mono_gchandle_new (struct MonoObject * obj, gboolean pinned)
{
  uint32_t D.21520;
  int iftmp.17;
  struct HandleData * D.21525;

  if (pinned != 0) goto <D.21522>; else goto <D.21523>;
  <D.21522>:
  iftmp.17 = 3;
  goto <D.21524>;
  <D.21523>:
  iftmp.17 = 2;
  <D.21524>:
  D.21525 = &gc_handles[iftmp.17];
  D.21520 = alloc_handle (D.21525, obj, 0);
  return D.21520;
}


alloc_handle (struct HandleData * handles, struct MonoObject * obj, gboolean track)
{
  _Bool D.21529;
  long int D.21530;
  long int D.21531;
  unsigned int D.21534;
  unsigned char D.21537;
  unsigned int D.21540;
  int D.21541;
  _Bool D.21542;
  int D.21543;
  void * D.21544;
  void * D.21545;
  void * D.21547;
  unsigned int D.21548;
  void * D.21549;
  unsigned int D.21550;
  void * D.21551;
  <unnamed-unsigned:24> D.21552;
  guint32 * D.21553;
  unsigned int slot.18;
  unsigned int D.21555;
  guint32 * D.21556;
  unsigned int D.21557;
  <unnamed-unsigned:24> D.21560;
  unsigned int slot.19;
  unsigned int D.21562;
  unsigned int D.21565;
  unsigned int D.21566;
  int D.21571;
  unsigned int D.21574;
  unsigned int D.21577;
  int new_size.20;
  void * D.21579;
  void * * D.21580;
  unsigned int D.21582;
  guint16 * D.21583;
  unsigned int i.21;
  unsigned int D.21585;
  void * * D.21586;
  void * * D.21589;
  void * * D.21591;
  void * D.21592;
  _Bool D.21593;
  long int D.21594;
  long int D.21595;
  unsigned int i.22;
  unsigned int D.21599;
  unsigned int D.21600;
  <unnamed-unsigned:24> D.21601;
  int D.21602;
  unsigned int D.21603;
  unsigned int D.21604;
  int D.21605;
  void * * D.21606;
  unsigned int D.21609;
  guint16 * D.21610;
  struct MonoDomain * iftmp.23;
  int D.21615;
  short unsigned int D.21616;
  void * * D.21619;
  struct MonoPerfCounters * mono_perfcounters.24;
  unsigned int D.21622;
  unsigned int D.21623;
  _Bool D.21626;
  long int D.21627;
  long int D.21628;
  int D.21631;
  int D.21632;
  int D.21633;
  int D.21634;
  guint32 D.21635;
  gint slot;
  gint i;
  guint32 res;

  {
    int ret;

    ret = pthread_mutex_lock (&handle_section.mutex);
    if (ret != 0) goto <D.21527>; else goto <D.21528>;
    <D.21527>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21528>:
    D.21529 = ret != 0;
    D.21530 = (long int) D.21529;
    D.21531 = __builtin_expect (D.21530, 0);
    if (D.21531 != 0) goto <D.21532>; else goto <D.21533>;
    <D.21532>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 636, "ret == 0");
    <D.21533>:
  }
  D.21534 = handles->size;
  if (D.21534 == 0) goto <D.21535>; else goto <D.21536>;
  <D.21535>:
  handles->size = 32;
  D.21537 = handles->type;
  if (D.21537 > 1) goto <D.21538>; else goto <D.21539>;
  <D.21538>:
  D.21534 = handles->size;
  D.21540 = D.21534 * 4;
  D.21534 = handles->size;
  D.21541 = (int) D.21534;
  D.21537 = handles->type;
  D.21542 = D.21537 == 3;
  D.21543 = (int) D.21542;
  D.21544 = make_root_descr_all_refs (D.21541, D.21543);
  D.21545 = mono_gc_alloc_fixed (D.21540, D.21544);
  handles->entries = D.21545;
  goto <D.21546>;
  <D.21539>:
  D.21534 = handles->size;
  D.21540 = D.21534 * 4;
  D.21547 = monoeg_malloc0 (D.21540);
  handles->entries = D.21547;
  D.21534 = handles->size;
  D.21548 = D.21534 * 2;
  D.21549 = monoeg_malloc0 (D.21548);
  handles->domain_ids = D.21549;
  <D.21546>:
  D.21534 = handles->size;
  D.21550 = D.21534 / 8;
  D.21551 = monoeg_malloc0 (D.21550);
  handles->bitmap = D.21551;
  <D.21536>:
  i = -1;
  D.21552 = handles->slot_hint;
  slot = (gint) D.21552;
  goto <D.20993>;
  <D.20992>:
  D.21553 = handles->bitmap;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21556 = D.21553 + D.21555;
  D.21557 = *D.21556;
  if (D.21557 != 4294967295) goto <D.21558>; else goto <D.21559>;
  <D.21558>:
  D.21553 = handles->bitmap;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21556 = D.21553 + D.21555;
  D.21557 = *D.21556;
  i = find_first_unset (D.21557);
  slot.18 = (unsigned int) slot;
  D.21560 = (<unnamed-unsigned:24>) slot.18;
  handles->slot_hint = D.21560;
  goto <D.20991>;
  <D.21559>:
  slot = slot + 1;
  <D.20993>:
  slot.19 = (unsigned int) slot;
  D.21534 = handles->size;
  D.21562 = D.21534 / 32;
  if (slot.19 < D.21562) goto <D.20992>; else goto <D.20991>;
  <D.20991>:
  if (i == -1) goto <D.21563>; else goto <D.21564>;
  <D.21563>:
  D.21565 = BIT_FIELD_REF <*handles, 32, 96>;
  D.21566 = D.21565 & 4294967040;
  if (D.21566 != 0) goto <D.21567>; else goto <D.21568>;
  <D.21567>:
  slot = 0;
  goto <D.20996>;
  <D.20995>:
  D.21553 = handles->bitmap;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21556 = D.21553 + D.21555;
  D.21557 = *D.21556;
  if (D.21557 != 4294967295) goto <D.21569>; else goto <D.21570>;
  <D.21569>:
  D.21553 = handles->bitmap;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21556 = D.21553 + D.21555;
  D.21557 = *D.21556;
  i = find_first_unset (D.21557);
  slot.18 = (unsigned int) slot;
  D.21560 = (<unnamed-unsigned:24>) slot.18;
  handles->slot_hint = D.21560;
  goto <D.20994>;
  <D.21570>:
  slot = slot + 1;
  <D.20996>:
  D.21552 = handles->slot_hint;
  D.21571 = (int) D.21552;
  if (D.21571 > slot) goto <D.20995>; else goto <D.20994>;
  <D.20994>:
  <D.21568>:
  <D.21564>:
  if (i == -1) goto <D.21572>; else goto <D.21573>;
  <D.21572>:
  {
    guint32 * new_bitmap;
    guint32 new_size;

    D.21534 = handles->size;
    new_size = D.21534 * 2;
    D.21574 = new_size / 8;
    new_bitmap = monoeg_malloc0 (D.21574);
    D.21553 = handles->bitmap;
    D.21534 = handles->size;
    D.21550 = D.21534 / 8;
    memcpy (new_bitmap, D.21553, D.21550);
    D.21553 = handles->bitmap;
    monoeg_g_free (D.21553);
    handles->bitmap = new_bitmap;
    D.21537 = handles->type;
    if (D.21537 > 1) goto <D.21575>; else goto <D.21576>;
    <D.21575>:
    {
      void * * entries;

      D.21577 = new_size * 4;
      new_size.20 = (int) new_size;
      D.21537 = handles->type;
      D.21542 = D.21537 == 3;
      D.21543 = (int) D.21542;
      D.21579 = make_root_descr_all_refs (new_size.20, D.21543);
      entries = mono_gc_alloc_fixed (D.21577, D.21579);
      D.21580 = handles->entries;
      D.21534 = handles->size;
      D.21540 = D.21534 * 4;
      mono_gc_memmove_aligned (entries, D.21580, D.21540);
      D.21580 = handles->entries;
      mono_gc_free_fixed (D.21580);
      handles->entries = entries;
    }
    goto <D.21581>;
    <D.21576>:
    {
      void * * entries;
      guint16 * domain_ids;

      D.21582 = new_size * 2;
      domain_ids = monoeg_malloc0 (D.21582);
      D.21577 = new_size * 4;
      entries = monoeg_malloc0 (D.21577);
      D.21583 = handles->domain_ids;
      D.21534 = handles->size;
      D.21548 = D.21534 * 2;
      memcpy (domain_ids, D.21583, D.21548);
      i = 0;
      goto <D.21004>;
      <D.21003>:
      {
        struct MonoObject * obj;

        D.21580 = handles->entries;
        i.21 = (unsigned int) i;
        D.21585 = i.21 * 4;
        D.21586 = D.21580 + D.21585;
        obj = mono_gc_weak_link_get (D.21586);
        if (obj != 0B) goto <D.21587>; else goto <D.21588>;
        <D.21587>:
        i.21 = (unsigned int) i;
        D.21585 = i.21 * 4;
        D.21589 = entries + D.21585;
        mono_gc_weak_link_add (D.21589, obj, track);
        D.21580 = handles->entries;
        i.21 = (unsigned int) i;
        D.21585 = i.21 * 4;
        D.21586 = D.21580 + D.21585;
        mono_gc_weak_link_remove (D.21586, track);
        goto <D.21590>;
        <D.21588>:
        D.21580 = handles->entries;
        i.21 = (unsigned int) i;
        D.21585 = i.21 * 4;
        D.21591 = D.21580 + D.21585;
        D.21592 = *D.21591;
        D.21593 = D.21592 != 0B;
        D.21594 = (long int) D.21593;
        D.21595 = __builtin_expect (D.21594, 0);
        if (D.21595 != 0) goto <D.21596>; else goto <D.21597>;
        <D.21596>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 695, "!handles->entries [i]");
        <D.21597>:
        <D.21590>:
      }
      i = i + 1;
      <D.21004>:
      i.22 = (unsigned int) i;
      D.21534 = handles->size;
      if (i.22 < D.21534) goto <D.21003>; else goto <D.21005>;
      <D.21005>:
      D.21580 = handles->entries;
      monoeg_g_free (D.21580);
      D.21583 = handles->domain_ids;
      monoeg_g_free (D.21583);
      handles->entries = entries;
      handles->domain_ids = domain_ids;
    }
    <D.21581>:
    i = 0;
    D.21534 = handles->size;
    D.21599 = D.21534 + 1;
    D.21600 = D.21599 / 32;
    slot = (gint) D.21600;
    D.21534 = handles->size;
    D.21599 = D.21534 + 1;
    D.21601 = (<unnamed-unsigned:24>) D.21599;
    handles->slot_hint = D.21601;
    handles->size = new_size;
  }
  <D.21573>:
  D.21553 = handles->bitmap;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21556 = D.21553 + D.21555;
  D.21553 = handles->bitmap;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21556 = D.21553 + D.21555;
  D.21557 = *D.21556;
  D.21602 = 1 << i;
  D.21603 = (unsigned int) D.21602;
  D.21604 = D.21557 | D.21603;
  *D.21556 = D.21604;
  D.21605 = slot * 32;
  slot = D.21605 + i;
  D.21580 = handles->entries;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21606 = D.21580 + D.21555;
  *D.21606 = 0B;
  D.21537 = handles->type;
  if (D.21537 <= 1) goto <D.21607>; else goto <D.21608>;
  <D.21607>:
  D.21583 = handles->domain_ids;
  slot.18 = (unsigned int) slot;
  D.21609 = slot.18 * 2;
  D.21610 = D.21583 + D.21609;
  if (obj != 0B) goto <D.21612>; else goto <D.21613>;
  <D.21612>:
  iftmp.23 = mono_object_get_domain (obj);
  goto <D.21614>;
  <D.21613>:
  iftmp.23 = mono_domain_get ();
  <D.21614>:
  D.21615 = iftmp.23->domain_id;
  D.21616 = (short unsigned int) D.21615;
  *D.21610 = D.21616;
  if (obj != 0B) goto <D.21617>; else goto <D.21618>;
  <D.21617>:
  D.21580 = handles->entries;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21619 = D.21580 + D.21555;
  mono_gc_weak_link_add (D.21619, obj, track);
  <D.21618>:
  goto <D.21620>;
  <D.21608>:
  D.21580 = handles->entries;
  slot.18 = (unsigned int) slot;
  D.21555 = slot.18 * 4;
  D.21606 = D.21580 + D.21555;
  *D.21606 = obj;
  <D.21620>:
  mono_perfcounters.24 = mono_perfcounters;
  D.21622 = mono_perfcounters.24->gc_num_handles;
  D.21623 = D.21622 + 1;
  mono_perfcounters.24->gc_num_handles = D.21623;
  {
    int ret;

    ret = pthread_mutex_unlock (&handle_section.mutex);
    if (ret != 0) goto <D.21624>; else goto <D.21625>;
    <D.21624>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21625>:
    D.21626 = ret != 0;
    D.21627 = (long int) D.21626;
    D.21628 = __builtin_expect (D.21627, 0);
    if (D.21628 != 0) goto <D.21629>; else goto <D.21630>;
    <D.21629>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 725, "ret == 0");
    <D.21630>:
  }
  D.21631 = slot << 3;
  D.21537 = handles->type;
  D.21632 = (int) D.21537;
  D.21633 = D.21632 + 1;
  D.21634 = D.21631 | D.21633;
  res = (guint32) D.21634;
  D.21537 = handles->type;
  D.21632 = (int) D.21537;
  mono_profiler_gc_handle (0, D.21632, res, obj);
  D.21635 = res;
  return D.21635;
}


find_first_unset (guint32 bitmap)
{
  int D.21637;
  unsigned int D.21638;
  unsigned int D.21639;
  int D.21642;
  int i;

  i = 0;
  goto <D.20976>;
  <D.20975>:
  D.21637 = 1 << i;
  D.21638 = (unsigned int) D.21637;
  D.21639 = D.21638 & bitmap;
  if (D.21639 == 0) goto <D.21640>; else goto <D.21641>;
  <D.21640>:
  D.21642 = i;
  return D.21642;
  <D.21641>:
  i = i + 1;
  <D.20976>:
  if (i <= 31) goto <D.20975>; else goto <D.20977>;
  <D.20977>:
  D.21642 = -1;
  return D.21642;
}


make_root_descr_all_refs (int numbits, gboolean pinned)
{
  void * D.21646;

  if (pinned != 0) goto <D.21644>; else goto <D.21645>;
  <D.21644>:
  D.21646 = 0B;
  return D.21646;
  <D.21645>:
  D.21646 = mono_gc_make_root_descr_all_refs (numbits);
  return D.21646;
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.21648;
  unsigned int D.21649;

  D.21649 = __builtin_object_size (__dest, 0);
  D.21648 = __builtin___memcpy_chk (__dest, __src, __len, D.21649);
  return D.21648;
}


mono_gchandle_new_weakref (struct MonoObject * obj, gboolean track_resurrection)
{
  _Bool D.21651;
  int D.21652;
  struct HandleData * D.21653;
  uint32_t D.21654;
  guint32 handle;

  D.21651 = track_resurrection != 0;
  D.21652 = (int) D.21651;
  D.21653 = &gc_handles[D.21652];
  handle = alloc_handle (D.21653, obj, track_resurrection);
  D.21654 = handle;
  return D.21654;
}


mono_gchandle_get_target (guint32 gchandle)
{
  unsigned int D.21656;
  struct MonoObject * D.21659;
  _Bool D.21662;
  long int D.21663;
  long int D.21664;
  unsigned int D.21667;
  guint32 * D.21670;
  unsigned int D.21671;
  unsigned int D.21672;
  guint32 * D.21673;
  unsigned int D.21674;
  int slot.25;
  int D.21676;
  int D.21677;
  unsigned int D.21678;
  unsigned int D.21679;
  unsigned char D.21682;
  void * * D.21685;
  unsigned int D.21686;
  void * * D.21687;
  void * * D.21689;
  _Bool D.21693;
  long int D.21694;
  long int D.21695;
  guint slot;
  guint type;
  struct HandleData * handles;
  struct MonoObject * obj;

  slot = gchandle >> 3;
  D.21656 = gchandle & 7;
  type = D.21656 + 4294967295;
  handles = &gc_handles[type];
  obj = 0B;
  if (type > 3) goto <D.21657>; else goto <D.21658>;
  <D.21657>:
  D.21659 = 0B;
  return D.21659;
  <D.21658>:
  {
    int ret;

    ret = pthread_mutex_lock (&handle_section.mutex);
    if (ret != 0) goto <D.21660>; else goto <D.21661>;
    <D.21660>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21661>:
    D.21662 = ret != 0;
    D.21663 = (long int) D.21662;
    D.21664 = __builtin_expect (D.21663, 0);
    if (D.21664 != 0) goto <D.21665>; else goto <D.21666>;
    <D.21665>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 809, "ret == 0");
    <D.21666>:
  }
  D.21667 = handles->size;
  if (D.21667 > slot) goto <D.21668>; else goto <D.21669>;
  <D.21668>:
  D.21670 = handles->bitmap;
  D.21671 = slot / 32;
  D.21672 = D.21671 * 4;
  D.21673 = D.21670 + D.21672;
  D.21674 = *D.21673;
  slot.25 = (int) slot;
  D.21676 = slot.25 & 31;
  D.21677 = 1 << D.21676;
  D.21678 = (unsigned int) D.21677;
  D.21679 = D.21674 & D.21678;
  if (D.21679 != 0) goto <D.21680>; else goto <D.21681>;
  <D.21680>:
  D.21682 = handles->type;
  if (D.21682 <= 1) goto <D.21683>; else goto <D.21684>;
  <D.21683>:
  D.21685 = handles->entries;
  D.21686 = slot * 4;
  D.21687 = D.21685 + D.21686;
  obj = mono_gc_weak_link_get (D.21687);
  goto <D.21688>;
  <D.21684>:
  D.21685 = handles->entries;
  D.21686 = slot * 4;
  D.21689 = D.21685 + D.21686;
  obj = *D.21689;
  <D.21688>:
  goto <D.21690>;
  <D.21681>:
  <D.21690>:
  <D.21669>:
  {
    int ret;

    ret = pthread_mutex_unlock (&handle_section.mutex);
    if (ret != 0) goto <D.21691>; else goto <D.21692>;
    <D.21691>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21692>:
    D.21693 = ret != 0;
    D.21694 = (long int) D.21693;
    D.21695 = __builtin_expect (D.21694, 0);
    if (D.21695 != 0) goto <D.21696>; else goto <D.21697>;
    <D.21696>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 819, "ret == 0");
    <D.21697>:
  }
  D.21659 = obj;
  return D.21659;
}


mono_gchandle_is_in_domain (guint32 gchandle, struct MonoDomain * domain)
{
  unsigned int D.21699;
  gboolean D.21702;
  _Bool D.21705;
  long int D.21706;
  long int D.21707;
  unsigned int D.21710;
  guint32 * D.21713;
  unsigned int D.21714;
  unsigned int D.21715;
  guint32 * D.21716;
  unsigned int D.21717;
  int slot.26;
  int D.21719;
  int D.21720;
  unsigned int D.21721;
  unsigned int D.21722;
  unsigned char D.21725;
  int D.21728;
  guint16 * D.21729;
  unsigned int D.21730;
  guint16 * D.21731;
  short unsigned int D.21732;
  int D.21733;
  _Bool D.21734;
  void * * D.21736;
  unsigned int D.21737;
  void * * D.21738;
  struct MonoVTable * D.21742;
  struct MonoDomain * D.21743;
  _Bool D.21744;
  _Bool D.21748;
  long int D.21749;
  long int D.21750;
  guint slot;
  guint type;
  struct HandleData * handles;
  gboolean result;

  slot = gchandle >> 3;
  D.21699 = gchandle & 7;
  type = D.21699 + 4294967295;
  handles = &gc_handles[type];
  result = 0;
  if (type > 3) goto <D.21700>; else goto <D.21701>;
  <D.21700>:
  D.21702 = 0;
  return D.21702;
  <D.21701>:
  {
    int ret;

    ret = pthread_mutex_lock (&handle_section.mutex);
    if (ret != 0) goto <D.21703>; else goto <D.21704>;
    <D.21703>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21704>:
    D.21705 = ret != 0;
    D.21706 = (long int) D.21705;
    D.21707 = __builtin_expect (D.21706, 0);
    if (D.21707 != 0) goto <D.21708>; else goto <D.21709>;
    <D.21708>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 870, "ret == 0");
    <D.21709>:
  }
  D.21710 = handles->size;
  if (D.21710 > slot) goto <D.21711>; else goto <D.21712>;
  <D.21711>:
  D.21713 = handles->bitmap;
  D.21714 = slot / 32;
  D.21715 = D.21714 * 4;
  D.21716 = D.21713 + D.21715;
  D.21717 = *D.21716;
  slot.26 = (int) slot;
  D.21719 = slot.26 & 31;
  D.21720 = 1 << D.21719;
  D.21721 = (unsigned int) D.21720;
  D.21722 = D.21717 & D.21721;
  if (D.21722 != 0) goto <D.21723>; else goto <D.21724>;
  <D.21723>:
  D.21725 = handles->type;
  if (D.21725 <= 1) goto <D.21726>; else goto <D.21727>;
  <D.21726>:
  D.21728 = domain->domain_id;
  D.21729 = handles->domain_ids;
  D.21730 = slot * 2;
  D.21731 = D.21729 + D.21730;
  D.21732 = *D.21731;
  D.21733 = (int) D.21732;
  D.21734 = D.21728 == D.21733;
  result = (gboolean) D.21734;
  goto <D.21735>;
  <D.21727>:
  {
    struct MonoObject * obj;

    D.21736 = handles->entries;
    D.21737 = slot * 4;
    D.21738 = D.21736 + D.21737;
    obj = *D.21738;
    if (obj == 0B) goto <D.21739>; else goto <D.21740>;
    <D.21739>:
    result = 1;
    goto <D.21741>;
    <D.21740>:
    D.21742 = obj->vtable;
    D.21743 = D.21742->domain;
    D.21744 = D.21743 == domain;
    result = (gboolean) D.21744;
    <D.21741>:
  }
  <D.21735>:
  goto <D.21745>;
  <D.21724>:
  <D.21745>:
  <D.21712>:
  {
    int ret;

    ret = pthread_mutex_unlock (&handle_section.mutex);
    if (ret != 0) goto <D.21746>; else goto <D.21747>;
    <D.21746>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21747>:
    D.21748 = ret != 0;
    D.21749 = (long int) D.21748;
    D.21750 = __builtin_expect (D.21749, 0);
    if (D.21750 != 0) goto <D.21751>; else goto <D.21752>;
    <D.21751>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 885, "ret == 0");
    <D.21752>:
  }
  D.21702 = result;
  return D.21702;
}


mono_gchandle_free (guint32 gchandle)
{
  unsigned int D.21754;
  _Bool D.21759;
  long int D.21760;
  long int D.21761;
  unsigned int D.21764;
  guint32 * D.21767;
  unsigned int D.21768;
  unsigned int D.21769;
  guint32 * D.21770;
  unsigned int D.21771;
  int slot.27;
  int D.21773;
  int D.21774;
  unsigned int D.21775;
  unsigned int D.21776;
  unsigned char D.21779;
  void * * D.21782;
  unsigned int D.21783;
  void * * D.21784;
  void * D.21785;
  void * * D.21788;
  _Bool D.21789;
  int D.21790;
  unsigned int D.21792;
  unsigned int D.21793;
  guint32 * D.21794;
  unsigned int D.21795;
  int D.21796;
  unsigned int D.21797;
  unsigned int D.21798;
  struct MonoPerfCounters * mono_perfcounters.28;
  unsigned int D.21801;
  unsigned int D.21802;
  _Bool D.21805;
  long int D.21806;
  long int D.21807;
  int D.21810;
  guint slot;
  guint type;
  struct HandleData * handles;

  slot = gchandle >> 3;
  D.21754 = gchandle & 7;
  type = D.21754 + 4294967295;
  handles = &gc_handles[type];
  if (type > 3) goto <D.21755>; else goto <D.21756>;
  <D.21755>:
  return;
  <D.21756>:
  {
    int ret;

    ret = pthread_mutex_lock (&handle_section.mutex);
    if (ret != 0) goto <D.21757>; else goto <D.21758>;
    <D.21757>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21758>:
    D.21759 = ret != 0;
    D.21760 = (long int) D.21759;
    D.21761 = __builtin_expect (D.21760, 0);
    if (D.21761 != 0) goto <D.21762>; else goto <D.21763>;
    <D.21762>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 906, "ret == 0");
    <D.21763>:
  }
  D.21764 = handles->size;
  if (D.21764 > slot) goto <D.21765>; else goto <D.21766>;
  <D.21765>:
  D.21767 = handles->bitmap;
  D.21768 = slot / 32;
  D.21769 = D.21768 * 4;
  D.21770 = D.21767 + D.21769;
  D.21771 = *D.21770;
  slot.27 = (int) slot;
  D.21773 = slot.27 & 31;
  D.21774 = 1 << D.21773;
  D.21775 = (unsigned int) D.21774;
  D.21776 = D.21771 & D.21775;
  if (D.21776 != 0) goto <D.21777>; else goto <D.21778>;
  <D.21777>:
  D.21779 = handles->type;
  if (D.21779 <= 1) goto <D.21780>; else goto <D.21781>;
  <D.21780>:
  D.21782 = handles->entries;
  D.21783 = slot * 4;
  D.21784 = D.21782 + D.21783;
  D.21785 = *D.21784;
  if (D.21785 != 0B) goto <D.21786>; else goto <D.21787>;
  <D.21786>:
  D.21782 = handles->entries;
  D.21783 = slot * 4;
  D.21788 = D.21782 + D.21783;
  D.21779 = handles->type;
  D.21789 = D.21779 == 1;
  D.21790 = (int) D.21789;
  mono_gc_weak_link_remove (D.21788, D.21790);
  <D.21787>:
  goto <D.21791>;
  <D.21781>:
  D.21782 = handles->entries;
  D.21783 = slot * 4;
  D.21784 = D.21782 + D.21783;
  *D.21784 = 0B;
  <D.21791>:
  D.21767 = handles->bitmap;
  D.21792 = slot / 32;
  D.21793 = D.21792 * 4;
  D.21794 = D.21767 + D.21793;
  D.21767 = handles->bitmap;
  D.21793 = D.21792 * 4;
  D.21794 = D.21767 + D.21793;
  D.21795 = *D.21794;
  slot.27 = (int) slot;
  D.21773 = slot.27 & 31;
  D.21774 = 1 << D.21773;
  D.21796 = ~D.21774;
  D.21797 = (unsigned int) D.21796;
  D.21798 = D.21795 & D.21797;
  *D.21794 = D.21798;
  goto <D.21799>;
  <D.21778>:
  <D.21799>:
  <D.21766>:
  mono_perfcounters.28 = mono_perfcounters;
  D.21801 = mono_perfcounters.28->gc_num_handles;
  D.21802 = D.21801 + 4294967295;
  mono_perfcounters.28->gc_num_handles = D.21802;
  {
    int ret;

    ret = pthread_mutex_unlock (&handle_section.mutex);
    if (ret != 0) goto <D.21803>; else goto <D.21804>;
    <D.21803>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21804>:
    D.21805 = ret != 0;
    D.21806 = (long int) D.21805;
    D.21807 = __builtin_expect (D.21806, 0);
    if (D.21807 != 0) goto <D.21808>; else goto <D.21809>;
    <D.21808>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 922, "ret == 0");
    <D.21809>:
  }
  D.21779 = handles->type;
  D.21810 = (int) D.21779;
  mono_profiler_gc_handle (1, D.21810, gchandle, 0B);
}


mono_gchandle_free_domain (struct MonoDomain * domain)
{
  _Bool D.21814;
  long int D.21815;
  long int D.21816;
  guint32 * D.21819;
  unsigned int D.21820;
  unsigned int D.21821;
  guint32 * D.21822;
  unsigned int D.21823;
  int slot.29;
  int D.21825;
  int D.21826;
  unsigned int D.21827;
  unsigned int D.21828;
  int D.21833;
  guint16 * D.21834;
  unsigned int D.21835;
  guint16 * D.21836;
  short unsigned int D.21837;
  int D.21838;
  unsigned int D.21841;
  unsigned int D.21842;
  guint32 * D.21843;
  unsigned int D.21844;
  int D.21845;
  unsigned int D.21846;
  unsigned int D.21847;
  void * * D.21848;
  unsigned int D.21849;
  void * * D.21850;
  void * D.21851;
  void * * D.21854;
  unsigned char D.21855;
  _Bool D.21856;
  int D.21857;
  struct MonoVTable * D.21861;
  struct MonoDomain * D.21862;
  unsigned int D.21865;
  unsigned int D.21866;
  guint32 * D.21867;
  unsigned int D.21868;
  unsigned int D.21869;
  unsigned int D.21870;
  _Bool D.21873;
  long int D.21874;
  long int D.21875;
  guint type;

  type = 0;
  goto <D.21071>;
  <D.21070>:
  {
    guint slot;
    struct HandleData * handles;

    handles = &gc_handles[type];
    {
      int ret;

      ret = pthread_mutex_lock (&handle_section.mutex);
      if (ret != 0) goto <D.21812>; else goto <D.21813>;
      <D.21812>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
      <D.21813>:
      D.21814 = ret != 0;
      D.21815 = (long int) D.21814;
      D.21816 = __builtin_expect (D.21815, 0);
      if (D.21816 != 0) goto <D.21817>; else goto <D.21818>;
      <D.21817>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 941, "ret == 0");
      <D.21818>:
    }
    slot = 0;
    goto <D.21067>;
    <D.21066>:
    D.21819 = handles->bitmap;
    D.21820 = slot / 32;
    D.21821 = D.21820 * 4;
    D.21822 = D.21819 + D.21821;
    D.21823 = *D.21822;
    slot.29 = (int) slot;
    D.21825 = slot.29 & 31;
    D.21826 = 1 << D.21825;
    D.21827 = (unsigned int) D.21826;
    D.21828 = D.21823 & D.21827;
    if (D.21828 == 0) goto <D.21829>; else goto <D.21830>;
    <D.21829>:
    // predicted unlikely by continue predictor.
    goto <D.21065>;
    <D.21830>:
    if (type <= 1) goto <D.21831>; else goto <D.21832>;
    <D.21831>:
    D.21833 = domain->domain_id;
    D.21834 = handles->domain_ids;
    D.21835 = slot * 2;
    D.21836 = D.21834 + D.21835;
    D.21837 = *D.21836;
    D.21838 = (int) D.21837;
    if (D.21833 == D.21838) goto <D.21839>; else goto <D.21840>;
    <D.21839>:
    D.21819 = handles->bitmap;
    D.21841 = slot / 32;
    D.21842 = D.21841 * 4;
    D.21843 = D.21819 + D.21842;
    D.21819 = handles->bitmap;
    D.21842 = D.21841 * 4;
    D.21843 = D.21819 + D.21842;
    D.21844 = *D.21843;
    slot.29 = (int) slot;
    D.21825 = slot.29 & 31;
    D.21826 = 1 << D.21825;
    D.21845 = ~D.21826;
    D.21846 = (unsigned int) D.21845;
    D.21847 = D.21844 & D.21846;
    *D.21843 = D.21847;
    D.21848 = handles->entries;
    D.21849 = slot * 4;
    D.21850 = D.21848 + D.21849;
    D.21851 = *D.21850;
    if (D.21851 != 0B) goto <D.21852>; else goto <D.21853>;
    <D.21852>:
    D.21848 = handles->entries;
    D.21849 = slot * 4;
    D.21854 = D.21848 + D.21849;
    D.21855 = handles->type;
    D.21856 = D.21855 == 1;
    D.21857 = (int) D.21856;
    mono_gc_weak_link_remove (D.21854, D.21857);
    <D.21853>:
    <D.21840>:
    goto <D.21858>;
    <D.21832>:
    D.21848 = handles->entries;
    D.21849 = slot * 4;
    D.21850 = D.21848 + D.21849;
    D.21851 = *D.21850;
    if (D.21851 != 0B) goto <D.21859>; else goto <D.21860>;
    <D.21859>:
    D.21848 = handles->entries;
    D.21849 = slot * 4;
    D.21850 = D.21848 + D.21849;
    D.21851 = *D.21850;
    D.21861 = MEM[(struct MonoObject *)D.21851].vtable;
    D.21862 = D.21861->domain;
    if (D.21862 == domain) goto <D.21863>; else goto <D.21864>;
    <D.21863>:
    D.21819 = handles->bitmap;
    D.21865 = slot / 32;
    D.21866 = D.21865 * 4;
    D.21867 = D.21819 + D.21866;
    D.21819 = handles->bitmap;
    D.21866 = D.21865 * 4;
    D.21867 = D.21819 + D.21866;
    D.21868 = *D.21867;
    slot.29 = (int) slot;
    D.21825 = slot.29 & 31;
    D.21826 = 1 << D.21825;
    D.21845 = ~D.21826;
    D.21846 = (unsigned int) D.21845;
    D.21869 = D.21868 & D.21846;
    *D.21867 = D.21869;
    D.21848 = handles->entries;
    D.21849 = slot * 4;
    D.21850 = D.21848 + D.21849;
    *D.21850 = 0B;
    <D.21864>:
    <D.21860>:
    <D.21858>:
    <D.21065>:
    slot = slot + 1;
    <D.21067>:
    D.21870 = handles->size;
    if (D.21870 > slot) goto <D.21066>; else goto <D.21068>;
    <D.21068>:
    {
      int ret;

      ret = pthread_mutex_unlock (&handle_section.mutex);
      if (ret != 0) goto <D.21871>; else goto <D.21872>;
      <D.21871>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21872>:
      D.21873 = ret != 0;
      D.21874 = (long int) D.21873;
      D.21875 = __builtin_expect (D.21874, 0);
      if (D.21875 != 0) goto <D.21876>; else goto <D.21877>;
      <D.21876>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 958, "ret == 0");
      <D.21877>:
    }
  }
  type = type + 1;
  <D.21071>:
  if (type <= 2) goto <D.21070>; else goto <D.21072>;
  <D.21072>:
}


GCHandle_CheckCurrentDomain (guint32 gchandle)
{
  MonoBoolean D.21878;
  struct MonoDomain * D.21879;
  int D.21880;

  D.21879 = mono_domain_get ();
  D.21880 = mono_gchandle_is_in_domain (gchandle, D.21879);
  D.21878 = (MonoBoolean) D.21880;
  return D.21878;
}


mono_gc_finalize_notify ()
{
  mono_sem_post (&finalizer_sem);
}


mono_gc_init ()
{
  int D.21882;
  int D.21885;
  int D.21888;
  void * finalizer_event.30;
  void * pending_done_event.31;
  void * shutdown_event.32;
  void * finalizer_event.33;
  void * pending_done_event.34;
  void * shutdown_event.35;

  InitializeCriticalSection (&handle_section);
  InitializeCriticalSection (&allocator_section);
  InitializeCriticalSection (&finalizer_mutex);
  InitializeCriticalSection (&reference_queue_mutex);
  D.21882 = mono_gc_is_moving ();
  if (D.21882 == 0) goto <D.21883>; else goto <D.21884>;
  <D.21883>:
  mono_gc_register_root (&gc_handles[2].entries, 4, 0B);
  <D.21884>:
  D.21885 = mono_gc_is_moving ();
  if (D.21885 == 0) goto <D.21886>; else goto <D.21887>;
  <D.21886>:
  mono_gc_register_root (&gc_handles[3].entries, 4, 0B);
  <D.21887>:
  mono_counters_register ("Created object count", 516, &mono_stats.new_object_count);
  mono_counters_register ("Minor GC collections", 512, &gc_stats.minor_gc_count);
  mono_counters_register ("Major GC collections", 512, &gc_stats.major_gc_count);
  mono_counters_register ("Minor GC time", 519, &gc_stats.minor_gc_time_usecs);
  mono_counters_register ("Major GC time", 519, &gc_stats.major_gc_time_usecs);
  mono_gc_base_init ();
  D.21888 = mono_gc_is_disabled ();
  if (D.21888 != 0) goto <D.21889>; else goto <D.21890>;
  <D.21889>:
  gc_disabled = 1;
  return;
  <D.21890>:
  finalizer_event.30 = CreateEvent (0B, 0, 0, 0B);
  finalizer_event = finalizer_event.30;
  pending_done_event.31 = CreateEvent (0B, 1, 0, 0B);
  pending_done_event = pending_done_event.31;
  shutdown_event.32 = CreateEvent (0B, 1, 0, 0B);
  shutdown_event = shutdown_event.32;
  finalizer_event.33 = finalizer_event;
  if (finalizer_event.33 == 0B) goto <D.21894>; else goto <D.21897>;
  <D.21897>:
  pending_done_event.34 = pending_done_event;
  if (pending_done_event.34 == 0B) goto <D.21894>; else goto <D.21899>;
  <D.21899>:
  shutdown_event.35 = shutdown_event;
  if (shutdown_event.35 == 0B) goto <D.21894>; else goto <D.21895>;
  <D.21894>:
  monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "gc.c", 1152);
  <D.21895>:
  sem_init (&finalizer_sem, 0, 0);
  mono_gc_init_finalizer_thread ();
}


mono_gc_init_finalizer_thread ()
{
  struct MonoDomain * D.21902;
  struct MonoInternalThread * gc_thread.36;
  struct MonoInternalThread * gc_thread.37;
  struct MonoDomain * D.21905;
  struct MonoString * D.21906;

  D.21902 = mono_domain_get ();
  gc_thread.36 = mono_thread_create_internal (D.21902, finalizer_thread, 0B, 0, 1, 0);
  gc_thread = gc_thread.36;
  gc_thread.37 = gc_thread;
  D.21905 = mono_domain_get ();
  D.21906 = mono_string_new (D.21905, "Finalizer");
  ves_icall_System_Threading_Thread_SetName_internal (gc_thread.37, D.21906);
}


finalizer_thread (void * unused)
{
  struct MonoDomain * D.21907;
  struct MonoDomain * D.21908;
  _Bool D.21909;
  long int D.21910;
  long int D.21911;
  struct GSList * domains_to_finalize.38;
  _Bool D.21919;
  long int D.21920;
  long int D.21921;
  struct GSList * domains_to_finalize.39;
  _Bool D.21929;
  long int D.21930;
  long int D.21931;
  _Bool D.21937;
  long int D.21938;
  long int D.21939;
  void * pending_done_event.40;
  int finished.41;
  void * shutdown_event.42;
  guint32 D.21945;

  goto <D.21103>;
  <D.21102>:
  D.21907 = mono_domain_get ();
  D.21908 = mono_get_root_domain ();
  D.21909 = D.21907 != D.21908;
  D.21910 = (long int) D.21909;
  D.21911 = __builtin_expect (D.21910, 0);
  if (D.21911 != 0) goto <D.21912>; else goto <D.21913>;
  <D.21912>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1069, "mono_domain_get () == mono_get_root_domain ()");
  <D.21913>:
  mono_sem_wait (&finalizer_sem, 1);
  mono_threads_perform_thread_dump ();
  mono_console_handle_async_ops ();
  mono_attach_maybe_start ();
  domains_to_finalize.38 = domains_to_finalize;
  if (domains_to_finalize.38 != 0B) goto <D.21915>; else goto <D.21916>;
  <D.21915>:
  {
    int ret;

    ret = pthread_mutex_lock (&finalizer_mutex.mutex);
    if (ret != 0) goto <D.21917>; else goto <D.21918>;
    <D.21917>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21918>:
    D.21919 = ret != 0;
    D.21920 = (long int) D.21919;
    D.21921 = __builtin_expect (D.21920, 0);
    if (D.21921 != 0) goto <D.21922>; else goto <D.21923>;
    <D.21922>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1087, "ret == 0");
    <D.21923>:
  }
  domains_to_finalize.38 = domains_to_finalize;
  if (domains_to_finalize.38 != 0B) goto <D.21924>; else goto <D.21925>;
  <D.21924>:
  {
    struct DomainFinalizationReq * req;

    domains_to_finalize.38 = domains_to_finalize;
    req = domains_to_finalize.38->data;
    domains_to_finalize.38 = domains_to_finalize;
    domains_to_finalize.39 = monoeg_g_slist_remove (domains_to_finalize.38, req);
    domains_to_finalize = domains_to_finalize.39;
    {
      int ret;

      ret = pthread_mutex_unlock (&finalizer_mutex.mutex);
      if (ret != 0) goto <D.21927>; else goto <D.21928>;
      <D.21927>:
      monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
      <D.21928>:
      D.21929 = ret != 0;
      D.21930 = (long int) D.21929;
      D.21931 = __builtin_expect (D.21930, 0);
      if (D.21931 != 0) goto <D.21932>; else goto <D.21933>;
      <D.21932>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1091, "ret == 0");
      <D.21933>:
    }
    finalize_domain_objects (req);
  }
  goto <D.21934>;
  <D.21925>:
  {
    int ret;

    ret = pthread_mutex_unlock (&finalizer_mutex.mutex);
    if (ret != 0) goto <D.21935>; else goto <D.21936>;
    <D.21935>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21936>:
    D.21937 = ret != 0;
    D.21938 = (long int) D.21937;
    D.21939 = __builtin_expect (D.21938, 0);
    if (D.21939 != 0) goto <D.21940>; else goto <D.21941>;
    <D.21940>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1095, "ret == 0");
    <D.21941>:
  }
  <D.21934>:
  <D.21916>:
  mono_gc_invoke_finalizers ();
  reference_queue_proccess_all ();
  pending_done_event.40 = pending_done_event;
  SetEvent (pending_done_event.40);
  <D.21103>:
  finished.41 = finished;
  if (finished.41 == 0) goto <D.21102>; else goto <D.21104>;
  <D.21104>:
  shutdown_event.42 = shutdown_event;
  SetEvent (shutdown_event.42);
  D.21945 = 0;
  return D.21945;
}


finalize_domain_objects (struct DomainFinalizationReq * req)
{
  struct MonoObject * D.21947;
  void * D.21948;
  struct MonoDomain * domain;
  struct MonoObject * to_finalize[64];
  int count;

  try
    {
      domain = req->domain;
      mono_gc_invoke_finalizers ();
      goto <D.21093>;
      <D.21092>:
      {
        int i;

        i = 0;
        goto <D.21090>;
        <D.21089>:
        D.21947 = to_finalize[i];
        mono_gc_run_finalize (D.21947, 0B);
        i = i + 1;
        <D.21090>:
        if (i < count) goto <D.21089>; else goto <D.21091>;
        <D.21091>:
      }
      <D.21093>:
      count = mono_gc_finalizers_for_domain (domain, &to_finalize, 64);
      if (count != 0) goto <D.21092>; else goto <D.21094>;
      <D.21094>:
      reference_queue_clear_for_domain (domain);
      D.21948 = req->done_event;
      SetEvent (D.21948);
      monoeg_g_free (req);
    }
  finally
    {
      to_finalize = {CLOBBER};
    }
}


reference_queue_clear_for_domain (struct MonoDomain * domain)
{
  struct MonoDomain * D.21949;
  void * * D.21952;
  void (*<Tc1>) (void *) D.21953;
  void * D.21954;
  struct MonoReferenceQueue * queue;

  queue = ref_queues;
  goto <D.21198>;
  <D.21197>:
  {
    struct RefQueueEntry * * iter;
    struct RefQueueEntry * entry;

    iter = &queue->queue;
    goto <D.21195>;
    <D.21194>:
    D.21949 = entry->domain;
    if (D.21949 == domain) goto <D.21950>; else goto <D.21951>;
    <D.21950>:
    D.21952 = &entry->dis_link;
    mono_gc_weak_link_remove (D.21952, 1);
    ref_list_remove_element (iter, entry);
    D.21953 = queue->callback;
    D.21954 = entry->user_data;
    D.21953 (D.21954);
    monoeg_g_free (entry);
    goto <D.21955>;
    <D.21951>:
    iter = &entry->next;
    <D.21955>:
    <D.21195>:
    entry = *iter;
    if (entry != 0B) goto <D.21194>; else goto <D.21196>;
    <D.21196>:
  }
  queue = queue->next;
  <D.21198>:
  if (queue != 0B) goto <D.21197>; else goto <D.21199>;
  <D.21199>:
}


ref_list_remove_element (struct RefQueueEntry * * prev, struct RefQueueEntry * element)
{
  struct RefQueueEntry * D.21956;
  struct RefQueueEntry * D.21958;
  void * D.21959;

  <D.21149>:
  goto <D.21147>;
  <D.21146>:
  D.21956 = *prev;
  prev = &D.21956->next;
  <D.21147>:
  D.21956 = *prev;
  if (D.21956 != element) goto <D.21146>; else goto <D.21148>;
  <D.21148>:
  if (prev != 0B) goto <D.21957>; else goto <D.21150>;
  <D.21957>:
  D.21958 = element->next;
  D.21959 = InterlockedCompareExchangePointer (prev, D.21958, element);
  if (D.21959 != element) goto <D.21149>; else goto <D.21150>;
  <D.21150>:
}


InterlockedCompareExchangePointer (void * volatile * dest, void * exch, void * comp)
{
  void * D.21960;
  unsigned int comp.43;
  unsigned int exch.44;
  unsigned int D.21963;

  comp.43 = (unsigned int) comp;
  exch.44 = (unsigned int) exch;
  D.21963 = __sync_val_compare_and_swap_4 (dest, comp.43, exch.44);
  D.21960 = (void *) D.21963;
  return D.21960;
}


reference_queue_proccess_all ()
{
  _Bool D.21967;
  long int D.21968;
  long int D.21969;
  int D.21972;
  struct RefQueueEntry * D.21975;
  _Bool D.21980;
  long int D.21981;
  long int D.21982;
  struct MonoReferenceQueue * D.21985;
  struct MonoReferenceQueue * D.21986;
  _Bool D.21989;
  long int D.21990;
  long int D.21991;
  struct MonoReferenceQueue * * iter;
  struct MonoReferenceQueue * queue;
  void restart = <<< error >>>;

  queue = ref_queues;
  goto <D.21172>;
  <D.21171>:
  reference_queue_proccess (queue);
  queue = queue->next;
  <D.21172>:
  if (queue != 0B) goto <D.21171>; else goto <D.21173>;
  <D.21173>:
  restart:
  {
    int ret;

    ret = pthread_mutex_lock (&reference_queue_mutex.mutex);
    if (ret != 0) goto <D.21965>; else goto <D.21966>;
    <D.21965>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.21966>:
    D.21967 = ret != 0;
    D.21968 = (long int) D.21967;
    D.21969 = __builtin_expect (D.21968, 0);
    if (D.21969 != 0) goto <D.21970>; else goto <D.21971>;
    <D.21970>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1424, "ret == 0");
    <D.21971>:
  }
  iter = &ref_queues;
  goto <D.21176>;
  <D.21178>:
  queue = *iter;
  D.21972 = queue->should_be_deleted;
  if (D.21972 == 0) goto <D.21973>; else goto <D.21974>;
  <D.21973>:
  iter = &queue->next;
  // predicted unlikely by continue predictor.
  goto <D.21176>;
  <D.21974>:
  D.21975 = queue->queue;
  if (D.21975 != 0B) goto <D.21976>; else goto <D.21977>;
  <D.21976>:
  {
    int ret;

    ret = pthread_mutex_unlock (&reference_queue_mutex.mutex);
    if (ret != 0) goto <D.21978>; else goto <D.21979>;
    <D.21978>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21979>:
    D.21980 = ret != 0;
    D.21981 = (long int) D.21980;
    D.21982 = __builtin_expect (D.21981, 0);
    if (D.21982 != 0) goto <D.21983>; else goto <D.21984>;
    <D.21983>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1432, "ret == 0");
    <D.21984>:
  }
  reference_queue_proccess (queue);
  goto restart;
  <D.21977>:
  D.21985 = queue->next;
  *iter = D.21985;
  monoeg_g_free (queue);
  <D.21176>:
  D.21986 = *iter;
  if (D.21986 != 0B) goto <D.21178>; else goto <D.21179>;
  <D.21179>:
  {
    int ret;

    ret = pthread_mutex_unlock (&reference_queue_mutex.mutex);
    if (ret != 0) goto <D.21987>; else goto <D.21988>;
    <D.21987>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.21988>:
    D.21989 = ret != 0;
    D.21990 = (long int) D.21989;
    D.21991 = __builtin_expect (D.21990, 0);
    if (D.21991 != 0) goto <D.21992>; else goto <D.21993>;
    <D.21992>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1439, "ret == 0");
    <D.21993>:
  }
}


reference_queue_proccess (struct MonoReferenceQueue * queue)
{
  int D.21997;
  void * * D.21999;
  struct MonoObject * D.22000;
  void (*<Tc1>) (void *) D.22001;
  void * D.22002;
  struct RefQueueEntry * * iter;
  struct RefQueueEntry * entry;

  iter = &queue->queue;
  goto <D.21164>;
  <D.21163>:
  D.21997 = queue->should_be_deleted;
  if (D.21997 != 0) goto <D.21994>; else goto <D.21998>;
  <D.21998>:
  D.21999 = &entry->dis_link;
  D.22000 = mono_gc_weak_link_get (D.21999);
  if (D.22000 == 0B) goto <D.21994>; else goto <D.21995>;
  <D.21994>:
  D.21999 = &entry->dis_link;
  mono_gc_weak_link_remove (D.21999, 1);
  ref_list_remove_element (iter, entry);
  D.22001 = queue->callback;
  D.22002 = entry->user_data;
  D.22001 (D.22002);
  monoeg_g_free (entry);
  goto <D.21996>;
  <D.21995>:
  iter = &entry->next;
  <D.21996>:
  <D.21164>:
  entry = *iter;
  if (entry != 0B) goto <D.21163>; else goto <D.21165>;
  <D.21165>:
}


mono_gc_cleanup ()
{
  int gc_disabled.45;
  void * shutdown_event.46;
  struct MonoInternalThread * D.22007;
  struct MonoInternalThread * gc_thread.47;
  unsigned int D.22011;
  void * D.22014;
  unsigned int D.22015;
  unsigned int D.22020;
  _Bool D.22021;
  long int D.22022;
  long int D.22023;
  long long unsigned int D.22026;
  long unsigned int D.22027;

  gc_disabled.45 = gc_disabled;
  if (gc_disabled.45 == 0) goto <D.22004>; else goto <D.22005>;
  <D.22004>:
  shutdown_event.46 = shutdown_event;
  ResetEvent (shutdown_event.46);
  finished = 1;
  D.22007 = mono_thread_internal_current ();
  gc_thread.47 = gc_thread;
  if (D.22007 != gc_thread.47) goto <D.22009>; else goto <D.22010>;
  <D.22009>:
  mono_gc_finalize_notify ();
  shutdown_event.46 = shutdown_event;
  D.22011 = WaitForSingleObjectEx (shutdown_event.46, 2000, 0);
  if (D.22011 == 258) goto <D.22012>; else goto <D.22013>;
  <D.22012>:
  {
    int ret;

    suspend_finalizers = 1;
    gc_thread.47 = gc_thread;
    mono_thread_internal_stop (gc_thread.47);
    gc_thread.47 = gc_thread;
    D.22014 = gc_thread.47->handle;
    D.22015 = WaitForSingleObjectEx (D.22014, 100, 1);
    ret = (int) D.22015;
    if (ret == 258) goto <D.22016>; else goto <D.22017>;
    <D.22016>:
    monoeg_g_log (0B, 16, "Shutting down finalizer thread timed out.");
    goto <D.22018>;
    <D.22017>:
    Sleep (100);
    <D.22018>:
  }
  goto <D.22019>;
  <D.22013>:
  {
    int ret;

    gc_thread.47 = gc_thread;
    D.22014 = gc_thread.47->handle;
    D.22020 = WaitForSingleObjectEx (D.22014, 4294967295, 1);
    ret = (int) D.22020;
    D.22021 = ret != 0;
    D.22022 = (long int) D.22021;
    D.22023 = __builtin_expect (D.22022, 0);
    if (D.22023 != 0) goto <D.22024>; else goto <D.22025>;
    <D.22024>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1208, "ret == WAIT_OBJECT_0");
    <D.22025>:
    gc_thread.47 = gc_thread;
    D.22026 = gc_thread.47->tid;
    D.22027 = (long unsigned int) D.22026;
    ret = pthread_join (D.22027, 0B);
    D.22021 = ret != 0;
    D.22022 = (long int) D.22021;
    D.22023 = __builtin_expect (D.22022, 0);
    if (D.22023 != 0) goto <D.22028>; else goto <D.22029>;
    <D.22028>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1216, "ret == 0");
    <D.22029>:
  }
  <D.22019>:
  <D.22010>:
  gc_thread = 0B;
  <D.22005>:
  mono_reference_queue_cleanup ();
  DeleteCriticalSection (&handle_section);
  DeleteCriticalSection (&allocator_section);
  DeleteCriticalSection (&finalizer_mutex);
  DeleteCriticalSection (&reference_queue_mutex);
}


mono_reference_queue_cleanup ()
{
  struct MonoReferenceQueue * queue;

  queue = ref_queues;
  goto <D.21186>;
  <D.21185>:
  queue->should_be_deleted = 1;
  queue = queue->next;
  <D.21186>:
  if (queue != 0B) goto <D.21185>; else goto <D.21187>;
  <D.21187>:
  reference_queue_proccess_all ();
}


mono_gc_is_finalizer_internal_thread (struct MonoInternalThread * thread)
{
  gboolean D.22030;
  struct MonoInternalThread * gc_thread.48;
  _Bool D.22032;

  gc_thread.48 = gc_thread;
  D.22032 = thread == gc_thread.48;
  D.22030 = (gboolean) D.22032;
  return D.22030;
}


mono_gc_is_finalizer_thread (struct MonoThread * thread)
{
  gboolean D.22034;
  struct _MonoInternalThread * D.22035;

  D.22035 = thread->internal_thread;
  D.22034 = mono_gc_is_finalizer_internal_thread (D.22035);
  return D.22034;
}


mono_gc_parse_environment_string_extract_number (const char * str, glong * out)
{
  unsigned int D.22037;
  gboolean D.22040;
  sizetype len.49;
  sizetype D.22042;
  const char * D.22043;
  int D.22044;
  const short unsigned int * * D.22045;
  const short unsigned int * D.22046;
  unsigned int D.22047;
  unsigned int D.22048;
  const short unsigned int * D.22049;
  short unsigned int D.22050;
  int D.22051;
  int D.22052;
  int * D.22055;
  int D.22060;
  unsigned int val.50;
  unsigned int D.22063;
  char * endptr.51;
  char * D.22070;
  char D.22071;
  long unsigned int val.52;
  long unsigned int D.22077;
  char * endptr;
  int len;
  int shift;
  glong val;
  gboolean is_suffix;
  char suffix;

  try
    {
      D.22037 = strlen (str);
      len = (int) D.22037;
      shift = 0;
      is_suffix = 0;
      if (len == 0) goto <D.22038>; else goto <D.22039>;
      <D.22038>:
      D.22040 = 0;
      return D.22040;
      <D.22039>:
      len.49 = (sizetype) len;
      D.22042 = len.49 + 4294967295;
      D.22043 = str + D.22042;
      suffix = *D.22043;
      D.22044 = (int) suffix;
      switch (D.22044) <default: <D.21139>, case 71: <D.21133>, case 75: <D.21137>, case 77: <D.21135>, case 103: <D.21132>, case 107: <D.21136>, case 109: <D.21134>>
      <D.21132>:
      <D.21133>:
      shift = shift + 10;
      <D.21134>:
      <D.21135>:
      shift = shift + 10;
      <D.21136>:
      <D.21137>:
      shift = shift + 10;
      is_suffix = 1;
      goto <D.21138>;
      <D.21139>:
      D.22045 = __ctype_b_loc ();
      D.22046 = *D.22045;
      D.22047 = (unsigned int) suffix;
      D.22048 = D.22047 * 2;
      D.22049 = D.22046 + D.22048;
      D.22050 = *D.22049;
      D.22051 = (int) D.22050;
      D.22052 = D.22051 & 2048;
      if (D.22052 == 0) goto <D.22053>; else goto <D.22054>;
      <D.22053>:
      D.22040 = 0;
      return D.22040;
      <D.22054>:
      goto <D.21138>;
      <D.21138>:
      D.22055 = __errno_location ();
      *D.22055 = 0;
      val = strtol (str, &endptr, 10);
      D.22055 = __errno_location ();
      D.22060 = *D.22055;
      if (D.22060 == 34) goto <D.22061>; else goto <D.22056>;
      <D.22061>:
      val.50 = (unsigned int) val;
      D.22063 = val.50 + 2147483647;
      if (D.22063 > 4294967293) goto <D.22057>; else goto <D.22056>;
      <D.22056>:
      D.22055 = __errno_location ();
      D.22060 = *D.22055;
      if (D.22060 != 0) goto <D.22064>; else goto <D.22058>;
      <D.22064>:
      if (val == 0) goto <D.22057>; else goto <D.22058>;
      <D.22058>:
      endptr.51 = endptr;
      if (endptr.51 == str) goto <D.22057>; else goto <D.22059>;
      <D.22057>:
      D.22040 = 0;
      return D.22040;
      <D.22059>:
      if (is_suffix != 0) goto <D.22066>; else goto <D.22067>;
      <D.22066>:
      {
        gulong unshifted;

        if (val < 0) goto <D.22068>; else goto <D.22069>;
        <D.22068>:
        D.22040 = 0;
        return D.22040;
        <D.22069>:
        endptr.51 = endptr;
        D.22070 = endptr.51 + 1;
        D.22071 = *D.22070;
        if (D.22071 != 0) goto <D.22072>; else goto <D.22073>;
        <D.22072>:
        D.22040 = 0;
        return D.22040;
        <D.22073>:
        unshifted = (gulong) val;
        val = val << shift;
        if (val < 0) goto <D.22074>; else goto <D.22075>;
        <D.22074>:
        D.22040 = 0;
        return D.22040;
        <D.22075>:
        val.52 = (long unsigned int) val;
        D.22077 = val.52 >> shift;
        if (D.22077 != unshifted) goto <D.22078>; else goto <D.22079>;
        <D.22078>:
        D.22040 = 0;
        return D.22040;
        <D.22079>:
      }
      <D.22067>:
      *out = val;
      D.22040 = 1;
      return D.22040;
    }
  finally
    {
      endptr = {CLOBBER};
    }
}


mono_gc_reference_queue_new (void (*mono_reference_queue_callback) (void *) callback)
{
  _Bool D.22084;
  long int D.22085;
  long int D.22086;
  struct MonoReferenceQueue * ref_queues.53;
  _Bool D.22092;
  long int D.22093;
  long int D.22094;
  struct MonoReferenceQueue * D.22097;
  struct MonoReferenceQueue * res;

  res = monoeg_malloc0 (16);
  res->callback = callback;
  {
    int ret;

    ret = pthread_mutex_lock (&reference_queue_mutex.mutex);
    if (ret != 0) goto <D.22082>; else goto <D.22083>;
    <D.22082>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_lock result %d", ret);
    <D.22083>:
    D.22084 = ret != 0;
    D.22085 = (long int) D.22084;
    D.22086 = __builtin_expect (D.22085, 0);
    if (D.22086 != 0) goto <D.22087>; else goto <D.22088>;
    <D.22087>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1497, "ret == 0");
    <D.22088>:
  }
  ref_queues.53 = ref_queues;
  res->next = ref_queues.53;
  ref_queues = res;
  {
    int ret;

    ret = pthread_mutex_unlock (&reference_queue_mutex.mutex);
    if (ret != 0) goto <D.22090>; else goto <D.22091>;
    <D.22090>:
    monoeg_g_log (0B, 16, "Bad call to mono_mutex_unlock result %d", ret);
    <D.22091>:
    D.22092 = ret != 0;
    D.22093 = (long int) D.22092;
    D.22094 = __builtin_expect (D.22093, 0);
    if (D.22094 != 0) goto <D.22095>; else goto <D.22096>;
    <D.22095>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "gc.c", 1500, "ret == 0");
    <D.22096>:
  }
  D.22097 = res;
  return D.22097;
}


mono_gc_reference_queue_add (struct MonoReferenceQueue * queue, struct MonoObject * obj, void * user_data)
{
  int D.22099;
  mono_bool D.22102;
  struct MonoVTable * D.22103;
  struct MonoDomain * D.22104;
  void * * D.22105;
  struct RefQueueEntry * * D.22106;
  struct RefQueueEntry * entry;

  D.22099 = queue->should_be_deleted;
  if (D.22099 != 0) goto <D.22100>; else goto <D.22101>;
  <D.22100>:
  D.22102 = 0;
  return D.22102;
  <D.22101>:
  entry = monoeg_malloc0 (20);
  entry->user_data = user_data;
  D.22103 = obj->vtable;
  D.22104 = D.22103->domain;
  entry->domain = D.22104;
  D.22105 = &entry->dis_link;
  mono_gc_weak_link_add (D.22105, obj, 1);
  D.22106 = &queue->queue;
  ref_list_push (D.22106, entry);
  D.22102 = 1;
  return D.22102;
}


ref_list_push (struct RefQueueEntry * * head, struct RefQueueEntry * value)
{
  void * D.22108;
  struct RefQueueEntry * current;

  <D.21156>:
  current = *head;
  value->next = current;
  mono_memory_write_barrier ();
  D.22108 = InterlockedCompareExchangePointer (head, value, current);
  if (D.22108 != current) goto <D.21156>; else goto <D.21157>;
  <D.21157>:
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


mono_gc_reference_queue_free (struct MonoReferenceQueue * queue)
{
  queue->should_be_deleted = 1;
}


