sgen_workers_wake_up_all ()
{
  <unnamed-unsigned:1> D.17808;
  _Bool D.17809;
  long int D.17810;
  long int D.17811;

  D.17808 = workers_state.data.gc_in_progress;
  D.17809 = ~D.17808;
  D.17810 = (long int) D.17809;
  D.17811 = __builtin_expect (D.17810, 0);
  if (D.17811 != 0) goto <D.17812>; else goto <D.17813>;
  <D.17812>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 109, "workers_state.data.gc_in_progress");
  <D.17813>:
  workers_wake_up_all ();
}


workers_wake_up_all ()
{
  int workers_num.0;

  workers_num.0 = workers_num;
  workers_wake_up (workers_num.0);
}


workers_wake_up (int max)
{
  unsigned char D.17815;
  unsigned char D.17816;
  unsigned char D.17819;
  unsigned char D.17822;
  unsigned char D.17823;
  int D.17824;
  int i;

  i = 0;
  goto <D.17652>;
  <D.17651>:
  {
    union State old_state;
    union State new_state;

    try
      {
        <D.17649>:
        new_state = workers_state;
        old_state = new_state;
        D.17815 = BIT_FIELD_REF <old_state, 8, 8>;
        D.17816 = D.17815 & 1;
        if (D.17816 != 0) goto <D.17817>; else goto <D.17818>;
        <D.17817>:
        return;
        <D.17818>:
        D.17819 = old_state.data.num_waiting;
        if (D.17819 == 0) goto <D.17820>; else goto <D.17821>;
        <D.17820>:
        return;
        <D.17821>:
        D.17822 = new_state.data.num_waiting;
        D.17823 = D.17822 + 255;
        new_state.data.num_waiting = D.17823;
        D.17824 = set_state (old_state, new_state);
        if (D.17824 == 0) goto <D.17649>; else goto <D.17650>;
        <D.17650>:
        mono_sem_post (&workers_waiting_sem);
      }
    finally
      {
        old_state = {CLOBBER};
        new_state = {CLOBBER};
      }
  }
  i = i + 1;
  <D.17652>:
  if (i < max) goto <D.17651>; else goto <D.17653>;
  <D.17653>:
}


set_state (union State old_state, union State new_state)
{
  gboolean D.17828;
  int D.17829;
  int D.17830;
  int D.17831;
  _Bool D.17832;

  D.17829 = old_state.value;
  D.17830 = new_state.value;
  D.17831 = InterlockedCompareExchange (&workers_state.value, D.17830, D.17829);
  D.17829 = old_state.value;
  D.17832 = D.17831 == D.17829;
  D.17828 = (gboolean) D.17832;
  return D.17828;
}


InterlockedCompareExchange (volatile gint32 * dest, gint32 exch, gint32 comp)
{
  gint32 D.17834;
  unsigned int exch.1;
  unsigned int comp.2;
  unsigned int D.17837;

  exch.1 = (unsigned int) exch;
  comp.2 = (unsigned int) comp;
  D.17837 = __sync_val_compare_and_swap_4 (dest, comp.2, exch.1);
  D.17834 = (gint32) D.17837;
  return D.17834;
}


sgen_workers_enqueue_job (void (*JobFunc) (struct WorkerData *, void *) func, void * data)
{
  int D.17839;
  <unnamed-unsigned:1> D.17842;
  _Bool D.17843;
  long int D.17844;
  long int D.17845;
  volatile struct JobQueueEntry * workers_job_queue.3;
  int workers_job_queue_num_entries.4;
  int workers_job_queue_num_entries.5;
  int workers_job_queue_num_entries.6;
  int workers_num_jobs_enqueued.7;
  int workers_num_jobs_enqueued.8;
  int num_entries;
  struct JobQueueEntry * entry;

  D.17839 = collection_needs_workers ();
  if (D.17839 == 0) goto <D.17840>; else goto <D.17841>;
  <D.17840>:
  func (0B, data);
  return;
  <D.17841>:
  D.17842 = workers_state.data.gc_in_progress;
  D.17843 = ~D.17842;
  D.17844 = (long int) D.17843;
  D.17845 = __builtin_expect (D.17844, 0);
  if (D.17845 != 0) goto <D.17846>; else goto <D.17847>;
  <D.17846>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 157, "workers_state.data.gc_in_progress");
  <D.17847>:
  entry = sgen_alloc_internal (26);
  entry->func = func;
  entry->data = data;
  pthread_mutex_lock (&workers_job_queue_mutex);
  workers_job_queue.3 = workers_job_queue;
  entry->next = workers_job_queue.3;
  workers_job_queue = entry;
  workers_job_queue_num_entries.4 = workers_job_queue_num_entries;
  workers_job_queue_num_entries.5 = workers_job_queue_num_entries.4 + 1;
  workers_job_queue_num_entries.6 = workers_job_queue_num_entries.5;
  workers_job_queue_num_entries = workers_job_queue_num_entries.6;
  num_entries = workers_job_queue_num_entries.6;
  workers_num_jobs_enqueued.7 = workers_num_jobs_enqueued;
  workers_num_jobs_enqueued.8 = workers_num_jobs_enqueued.7 + 1;
  workers_num_jobs_enqueued = workers_num_jobs_enqueued.8;
  pthread_mutex_unlock (&workers_job_queue_mutex);
  workers_wake_up (num_entries);
}


collection_needs_workers ()
{
  gboolean D.17855;
  int iftmp.9;
  int D.17860;
  int D.17862;

  D.17860 = sgen_collection_is_parallel ();
  if (D.17860 != 0) goto <D.17857>; else goto <D.17861>;
  <D.17861>:
  D.17862 = sgen_collection_is_concurrent ();
  if (D.17862 != 0) goto <D.17857>; else goto <D.17858>;
  <D.17857>:
  iftmp.9 = 1;
  goto <D.17859>;
  <D.17858>:
  iftmp.9 = 0;
  <D.17859>:
  D.17855 = iftmp.9;
  return D.17855;
}


sgen_workers_wait_for_jobs ()
{
  unsigned char D.17864;
  unsigned char D.17865;
  _Bool D.17866;
  long int D.17867;
  long int D.17868;
  unsigned char D.17871;
  _Bool D.17872;
  long int D.17873;
  long int D.17874;
  unsigned char D.17877;
  int D.17878;
  int workers_num.10;
  int workers_num_jobs_finished.11;
  int workers_num_jobs_enqueued.12;

  goto <D.17681>;
  <D.17680>:
  {
    union State state;

    try
      {
        state = workers_state;
        D.17864 = BIT_FIELD_REF <state, 8, 8>;
        D.17865 = D.17864 & 2;
        D.17866 = D.17865 == 0;
        D.17867 = (long int) D.17866;
        D.17868 = __builtin_expect (D.17867, 0);
        if (D.17868 != 0) goto <D.17869>; else goto <D.17870>;
        <D.17869>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 179, "state.data.gc_in_progress");
        <D.17870>:
        D.17864 = BIT_FIELD_REF <state, 8, 8>;
        D.17871 = D.17864 & 1;
        D.17872 = D.17871 != 0;
        D.17873 = (long int) D.17872;
        D.17874 = __builtin_expect (D.17873, 0);
        if (D.17874 != 0) goto <D.17875>; else goto <D.17876>;
        <D.17875>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 180, "!state.data.done_posted");
        <D.17876>:
        D.17877 = state.data.num_waiting;
        D.17878 = (int) D.17877;
        workers_num.10 = workers_num;
        if (D.17878 == workers_num.10) goto <D.17880>; else goto <D.17881>;
        <D.17880>:
        workers_wake_up_all ();
        <D.17881>:
        monoeg_g_usleep (1000);
      }
    finally
      {
        state = {CLOBBER};
      }
  }
  <D.17681>:
  workers_num_jobs_finished.11 = workers_num_jobs_finished;
  workers_num_jobs_enqueued.12 = workers_num_jobs_enqueued;
  if (workers_num_jobs_finished.11 < workers_num_jobs_enqueued.12) goto <D.17680>; else goto <D.17682>;
  <D.17682>:
}


sgen_workers_init_distribute_gray_queue ()
{
  int D.17884;
  int iftmp.13;
  struct SgenMajorCollector * D.17891;
  int D.17892;
  struct SgenMajorCollector * D.17894;
  int D.17895;

  D.17884 = collection_needs_workers ();
  if (D.17884 == 0) goto <D.17885>; else goto <D.17886>;
  <D.17885>:
  return;
  <D.17886>:
  D.17891 = sgen_get_major_collector ();
  D.17892 = D.17891->is_concurrent;
  if (D.17892 != 0) goto <D.17888>; else goto <D.17893>;
  <D.17893>:
  D.17894 = sgen_get_major_collector ();
  D.17895 = D.17894->is_parallel;
  if (D.17895 != 0) goto <D.17888>; else goto <D.17889>;
  <D.17888>:
  iftmp.13 = 1;
  goto <D.17890>;
  <D.17889>:
  iftmp.13 = 0;
  <D.17890>:
  init_distribute_gray_queue (iftmp.13);
}


init_distribute_gray_queue (gboolean locked)
{
  int workers_distribute_gray_queue_inited.14;
  int D.17900;
  _Bool D.17901;
  long int D.17902;
  long int D.17903;
  int D.17906;
  _Bool D.17907;
  _Bool D.17908;
  _Bool D.17909;
  long int D.17910;
  long int D.17911;
  void (*<T2b40>) (char *) iftmp.15;
  struct SgenMajorCollector * D.17915;
  int D.17916;

  workers_distribute_gray_queue_inited.14 = workers_distribute_gray_queue_inited;
  if (workers_distribute_gray_queue_inited.14 != 0) goto <D.17898>; else goto <D.17899>;
  <D.17898>:
  D.17900 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
  D.17901 = D.17900 == 0;
  D.17902 = (long int) D.17901;
  D.17903 = __builtin_expect (D.17902, 0);
  if (D.17903 != 0) goto <D.17904>; else goto <D.17905>;
  <D.17904>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 419, "sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue)");
  <D.17905>:
  D.17906 = workers_distribute_gray_queue.locked;
  D.17907 = D.17906 == 0;
  D.17908 = locked == 0;
  D.17909 = D.17907 ^ D.17908;
  D.17910 = (long int) D.17909;
  D.17911 = __builtin_expect (D.17910, 0);
  if (D.17911 != 0) goto <D.17912>; else goto <D.17913>;
  <D.17912>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 420, "!workers_distribute_gray_queue.locked == !locked");
  <D.17913>:
  return;
  <D.17899>:
  D.17915 = sgen_get_major_collector ();
  D.17916 = D.17915->is_concurrent;
  if (D.17916 != 0) goto <D.17917>; else goto <D.17918>;
  <D.17917>:
  iftmp.15 = concurrent_enqueue_check;
  goto <D.17919>;
  <D.17918>:
  iftmp.15 = 0B;
  <D.17919>:
  sgen_section_gray_queue_init (&workers_distribute_gray_queue, locked, iftmp.15);
  workers_distribute_gray_queue_inited = 1;
}


concurrent_enqueue_check (char * obj)
{
  int D.17921;
  _Bool D.17922;
  long int D.17923;
  long int D.17924;
  int D.17927;
  _Bool D.17928;
  long int D.17929;
  long int D.17930;
  long unsigned int D.17933;
  long unsigned int D.17934;
  _Bool D.17935;
  long int D.17936;
  long int D.17937;

  D.17921 = sgen_concurrent_collection_in_progress ();
  D.17922 = D.17921 == 0;
  D.17923 = (long int) D.17922;
  D.17924 = __builtin_expect (D.17923, 0);
  if (D.17924 != 0) goto <D.17925>; else goto <D.17926>;
  <D.17925>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 356, "sgen_concurrent_collection_in_progress ()");
  <D.17926>:
  D.17927 = sgen_ptr_in_nursery (obj);
  D.17928 = D.17927 != 0;
  D.17929 = (long int) D.17928;
  D.17930 = __builtin_expect (D.17929, 0);
  if (D.17930 != 0) goto <D.17931>; else goto <D.17932>;
  <D.17931>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 357, "!sgen_ptr_in_nursery (obj)");
  <D.17932>:
  D.17933 = MEM[(mword *)obj];
  D.17934 = D.17933 & 18446744073709551612;
  D.17935 = D.17934 == 0;
  D.17936 = (long int) D.17935;
  D.17937 = __builtin_expect (D.17936, 0);
  if (D.17937 != 0) goto <D.17938>; else goto <D.17939>;
  <D.17938>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 358, "SGEN_LOAD_VTABLE (obj)");
  <D.17939>:
}


sgen_ptr_in_nursery (void * p)
{
  gboolean D.17940;
  int sgen_nursery_bits.16;
  int D.17942;
  int D.17943;
  long unsigned int D.17944;
  long unsigned int p.17;
  long unsigned int D.17946;
  char * sgen_nursery_start.18;
  long unsigned int sgen_nursery_start.19;
  _Bool D.17949;

  sgen_nursery_bits.16 = sgen_nursery_bits;
  D.17942 = 1 << sgen_nursery_bits.16;
  D.17943 = -D.17942;
  D.17944 = (long unsigned int) D.17943;
  p.17 = (long unsigned int) p;
  D.17946 = D.17944 & p.17;
  sgen_nursery_start.18 = sgen_nursery_start;
  sgen_nursery_start.19 = (long unsigned int) sgen_nursery_start.18;
  D.17949 = D.17946 == sgen_nursery_start.19;
  D.17940 = (gboolean) D.17949;
  return D.17940;
}


sgen_workers_init (int num_workers)
{
  struct SgenMajorCollector * D.17951;
  int D.17952;
  struct SgenMajorCollector * D.17955;
  int D.17956;
  long unsigned int D.17959;
  long unsigned int D.17960;
  void * workers_data.20;
  struct WorkerData * workers_data.21;
  int iftmp.22;
  struct SgenMajorCollector * D.17967;
  int D.17968;
  struct SgenMajorCollector * D.17970;
  int D.17971;
  struct SgenMajorCollector * D.17972;
  void * (*<T2aaa>) (void) D.17973;
  struct SgenMajorCollector * D.17976;
  void * (*<T2aaa>) (void) D.17977;
  void * workers_gc_thread_major_collector_data.23;
  long unsigned int D.17979;
  long unsigned int D.17980;
  struct WorkerData * D.17981;
  union mono_mutex_t * D.17982;
  struct SgenMajorCollector * D.17983;
  void * (*<T2aaa>) (void) D.17984;
  struct SgenMajorCollector * D.17987;
  void * (*<T2aaa>) (void) D.17988;
  void * D.17989;
  int workers_num.24;
  int i;

  D.17951 = sgen_get_major_collector ();
  D.17952 = D.17951->is_parallel;
  if (D.17952 == 0) goto <D.17953>; else goto <D.17954>;
  <D.17953>:
  D.17955 = sgen_get_major_collector ();
  D.17956 = D.17955->is_concurrent;
  if (D.17956 == 0) goto <D.17957>; else goto <D.17958>;
  <D.17957>:
  return;
  <D.17958>:
  <D.17954>:
  workers_num = num_workers;
  D.17959 = (long unsigned int) num_workers;
  D.17960 = D.17959 * 4192;
  workers_data.20 = sgen_alloc_internal_dynamic (D.17960, 19, 1);
  workers_data = workers_data.20;
  D.17959 = (long unsigned int) num_workers;
  D.17960 = D.17959 * 4192;
  workers_data.21 = workers_data;
  memset (workers_data.21, 0, D.17960);
  sem_init (&workers_waiting_sem, 0, 0);
  sem_init (&workers_done_sem, 0, 0);
  D.17967 = sgen_get_major_collector ();
  D.17968 = D.17967->is_concurrent;
  if (D.17968 != 0) goto <D.17964>; else goto <D.17969>;
  <D.17969>:
  D.17970 = sgen_get_major_collector ();
  D.17971 = D.17970->is_parallel;
  if (D.17971 != 0) goto <D.17964>; else goto <D.17965>;
  <D.17964>:
  iftmp.22 = 1;
  goto <D.17966>;
  <D.17965>:
  iftmp.22 = 0;
  <D.17966>:
  init_distribute_gray_queue (iftmp.22);
  D.17972 = sgen_get_major_collector ();
  D.17973 = D.17972->alloc_worker_data;
  if (D.17973 != 0B) goto <D.17974>; else goto <D.17975>;
  <D.17974>:
  D.17976 = sgen_get_major_collector ();
  D.17977 = D.17976->alloc_worker_data;
  workers_gc_thread_major_collector_data.23 = D.17977 ();
  workers_gc_thread_major_collector_data = workers_gc_thread_major_collector_data.23;
  <D.17975>:
  i = 0;
  goto <D.17754>;
  <D.17753>:
  workers_data.21 = workers_data;
  D.17979 = (long unsigned int) i;
  D.17980 = D.17979 * 4192;
  D.17981 = workers_data.21 + D.17980;
  D.17982 = &D.17981->stealable_stack_mutex;
  pthread_mutex_init (D.17982, 0B);
  workers_data.21 = workers_data;
  D.17979 = (long unsigned int) i;
  D.17980 = D.17979 * 4192;
  D.17981 = workers_data.21 + D.17980;
  D.17981->stealable_stack_fill = 0;
  D.17983 = sgen_get_major_collector ();
  D.17984 = D.17983->alloc_worker_data;
  if (D.17984 != 0B) goto <D.17985>; else goto <D.17986>;
  <D.17985>:
  workers_data.21 = workers_data;
  D.17979 = (long unsigned int) i;
  D.17980 = D.17979 * 4192;
  D.17981 = workers_data.21 + D.17980;
  D.17987 = sgen_get_major_collector ();
  D.17988 = D.17987->alloc_worker_data;
  D.17989 = D.17988 ();
  D.17981->major_collector_data = D.17989;
  <D.17986>:
  i = i + 1;
  <D.17754>:
  workers_num.24 = workers_num;
  if (i < workers_num.24) goto <D.17753>; else goto <D.17755>;
  <D.17755>:
  pthread_mutex_init (&workers_job_queue_mutex, 0B);
  sgen_register_fixed_internal_mem_type (26, 24);
  mono_counters_register ("Stolen from self lock", 515, &stat_workers_stolen_from_self_lock);
  mono_counters_register ("Stolen from self no lock", 515, &stat_workers_stolen_from_self_no_lock);
  mono_counters_register ("Stolen from others", 515, &stat_workers_stolen_from_others);
  mono_counters_register ("# workers waited", 515, &stat_workers_num_waited);
}


memset (void * __dest, int __ch, size_t __len)
{
  int D.17994;
  int D.17999;
  void * D.18001;
  long unsigned int D.18002;

  D.17994 = __builtin_constant_p (__len);
  if (D.17994 != 0) goto <D.17995>; else goto <D.17996>;
  <D.17995>:
  if (__len == 0) goto <D.17997>; else goto <D.17998>;
  <D.17997>:
  D.17999 = __builtin_constant_p (__ch);
  if (D.17999 == 0) goto <D.17992>; else goto <D.18000>;
  <D.18000>:
  if (__ch != 0) goto <D.17992>; else goto <D.17993>;
  <D.17992>:
  __warn_memset_zero_len ();
  D.18001 = __dest;
  return D.18001;
  <D.17993>:
  <D.17998>:
  <D.17996>:
  D.18002 = __builtin_object_size (__dest, 0);
  D.18001 = __builtin___memset_chk (__dest, __ch, __len, D.18002);
  return D.18001;
}


sgen_workers_start_all_workers ()
{
  int D.18004;
  struct SgenMajorCollector * D.18007;
  void (*<Tc2>) (void *) D.18008;
  struct SgenMajorCollector * D.18011;
  void (*<Tc2>) (void *) D.18012;
  void * workers_gc_thread_major_collector_data.25;
  unsigned char D.18014;
  unsigned char D.18015;
  _Bool D.18016;
  long int D.18017;
  long int D.18018;
  int workers_job_queue_num_entries.26;
  _Bool D.18022;
  long int D.18023;
  long int D.18024;
  int workers_started.27;
  unsigned char D.18030;
  _Bool D.18031;
  long int D.18032;
  long int D.18033;
  unsigned char D.18036;
  int D.18037;
  int workers_num.28;
  int D.18041;
  _Bool D.18044;
  long int D.18045;
  long int D.18046;
  int D.18049;
  union State old_state;
  union State new_state;
  int i;

  try
    {
      D.18004 = collection_needs_workers ();
      if (D.18004 == 0) goto <D.18005>; else goto <D.18006>;
      <D.18005>:
      return;
      <D.18006>:
      D.18007 = sgen_get_major_collector ();
      D.18008 = D.18007->init_worker_thread;
      if (D.18008 != 0B) goto <D.18009>; else goto <D.18010>;
      <D.18009>:
      D.18011 = sgen_get_major_collector ();
      D.18012 = D.18011->init_worker_thread;
      workers_gc_thread_major_collector_data.25 = workers_gc_thread_major_collector_data;
      D.18012 (workers_gc_thread_major_collector_data.25);
      <D.18010>:
      new_state = workers_state;
      old_state = new_state;
      D.18014 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18015 = D.18014 & 2;
      D.18016 = D.18015 != 0;
      D.18017 = (long int) D.18016;
      D.18018 = __builtin_expect (D.18017, 0);
      if (D.18018 != 0) goto <D.18019>; else goto <D.18020>;
      <D.18019>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 504, "!old_state.data.gc_in_progress");
      <D.18020>:
      new_state.data.gc_in_progress = 1;
      workers_marking = 0;
      workers_job_queue_num_entries.26 = workers_job_queue_num_entries;
      D.18022 = workers_job_queue_num_entries.26 != 0;
      D.18023 = (long int) D.18022;
      D.18024 = __builtin_expect (D.18023, 0);
      if (D.18024 != 0) goto <D.18025>; else goto <D.18026>;
      <D.18025>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 509, "workers_job_queue_num_entries == 0");
      <D.18026>:
      workers_num_jobs_enqueued = 0;
      workers_num_jobs_finished = 0;
      workers_started.27 = workers_started;
      if (workers_started.27 != 0) goto <D.18028>; else goto <D.18029>;
      <D.18028>:
      D.18014 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18030 = D.18014 & 1;
      D.18031 = D.18030 == 0;
      D.18032 = (long int) D.18031;
      D.18033 = __builtin_expect (D.18032, 0);
      if (D.18033 != 0) goto <D.18034>; else goto <D.18035>;
      <D.18034>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 514, "old_state.data.done_posted");
      <D.18035>:
      D.18036 = old_state.data.num_waiting;
      D.18037 = (int) D.18036;
      workers_num.28 = workers_num;
      if (D.18037 != workers_num.28) goto <D.18039>; else goto <D.18040>;
      <D.18039>:
      D.18036 = old_state.data.num_waiting;
      D.18037 = (int) D.18036;
      workers_num.28 = workers_num;
      monoeg_g_log (0B, 4, "Expecting all %d sgen workers to be parked, but only %d are", workers_num.28, D.18037);
      <D.17765>:
      goto <D.17765>;
      <D.18040>:
      new_state.data.done_posted = 0;
      D.18041 = set_state (old_state, new_state);
      if (D.18041 == 0) goto <D.18042>; else goto <D.18043>;
      <D.18042>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 523);
      <D.18043>:
      workers_wake_up_all ();
      return;
      <D.18029>:
      D.18014 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18030 = D.18014 & 1;
      D.18044 = D.18030 != 0;
      D.18045 = (long int) D.18044;
      D.18046 = __builtin_expect (D.18045, 0);
      if (D.18046 != 0) goto <D.18047>; else goto <D.18048>;
      <D.18047>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 529, "!old_state.data.done_posted");
      <D.18048>:
      D.18049 = set_state (old_state, new_state);
      if (D.18049 == 0) goto <D.18050>; else goto <D.18051>;
      <D.18050>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 532);
      <D.18051>:
      i = 0;
      goto <D.17767>;
      <D.17766>:
      workers_start_worker (i);
      i = i + 1;
      <D.17767>:
      workers_num.28 = workers_num;
      if (i < workers_num.28) goto <D.17766>; else goto <D.17768>;
      <D.17768>:
      workers_started = 1;
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


workers_start_worker (int index)
{
  int iftmp.29;
  int workers_num.30;
  _Bool D.18061;
  long int D.18062;
  long int D.18063;
  struct WorkerData * workers_data.31;
  long unsigned int D.18067;
  long unsigned int D.18068;
  struct WorkerData * D.18069;
  long unsigned int D.18070;
  _Bool D.18071;
  long int D.18072;
  long int D.18073;
  void * D.18076;
  MonoNativeThreadId * D.18077;

  if (index < 0) goto <D.18056>; else goto <D.18059>;
  <D.18059>:
  workers_num.30 = workers_num;
  if (index >= workers_num.30) goto <D.18056>; else goto <D.18057>;
  <D.18056>:
  iftmp.29 = 1;
  goto <D.18058>;
  <D.18057>:
  iftmp.29 = 0;
  <D.18058>:
  D.18061 = iftmp.29 != 0;
  D.18062 = (long int) D.18061;
  D.18063 = __builtin_expect (D.18062, 0);
  if (D.18063 != 0) goto <D.18064>; else goto <D.18065>;
  <D.18064>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 485, "index >= 0 && index < workers_num");
  <D.18065>:
  workers_data.31 = workers_data;
  D.18067 = (long unsigned int) index;
  D.18068 = D.18067 * 4192;
  D.18069 = workers_data.31 + D.18068;
  D.18070 = D.18069->thread;
  D.18071 = D.18070 != 0;
  D.18072 = (long int) D.18071;
  D.18073 = __builtin_expect (D.18072, 0);
  if (D.18073 != 0) goto <D.18074>; else goto <D.18075>;
  <D.18074>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 487, "!workers_data [index].thread");
  <D.18075>:
  workers_data.31 = workers_data;
  D.18067 = (long unsigned int) index;
  D.18068 = D.18067 * 4192;
  D.18076 = workers_data.31 + D.18068;
  workers_data.31 = workers_data;
  D.18067 = (long unsigned int) index;
  D.18068 = D.18067 * 4192;
  D.18069 = workers_data.31 + D.18068;
  D.18077 = &D.18069->thread;
  mono_native_thread_create (D.18077, workers_thread_func, D.18076);
}


workers_thread_func (void * data_untyped)
{
  void (*<Tc2>) (void *) D.18078;
  void * D.18081;
  int D.18082;
  int workers_marking.32;
  struct SgenGrayQueue * D.18088;
  int D.18089;
  int D.18091;
  struct SgenObjectOperations * iftmp.33;
  int D.18093;
  void (*<T2bff>) (char *, struct SgenGrayQueue *) D.18097;
  int D.18098;
  _Bool D.18099;
  long int D.18100;
  long int D.18101;
  int D.18104;
  int D.18105;
  _Bool D.18106;
  long int D.18107;
  long int D.18108;
  void * D.18113;
  struct WorkerData * data;
  struct SgenMajorCollector * major;

  data = data_untyped;
  major = sgen_get_major_collector ();
  mono_thread_info_register_small_id ();
  D.18078 = major->init_worker_thread;
  if (D.18078 != 0B) goto <D.18079>; else goto <D.18080>;
  <D.18079>:
  D.18078 = major->init_worker_thread;
  D.18081 = data->major_collector_data;
  D.18078 (D.18081);
  <D.18080>:
  init_private_gray_queue (data);
  <D.17742>:
  {
    gboolean did_work;

    did_work = 0;
    goto <D.17735>;
    <D.17734>:
    did_work = 1;
    <D.17735>:
    D.18082 = workers_dequeue_and_do_job (data);
    if (D.18082 != 0) goto <D.17734>; else goto <D.17736>;
    <D.17736>:
    workers_marking.32 = workers_marking;
    if (workers_marking.32 != 0) goto <D.18086>; else goto <D.18087>;
    <D.18086>:
    D.18088 = &data->private_gray_queue;
    D.18089 = sgen_gray_object_queue_is_empty (D.18088);
    if (D.18089 == 0) goto <D.18083>; else goto <D.18090>;
    <D.18090>:
    D.18091 = workers_get_work (data);
    if (D.18091 != 0) goto <D.18083>; else goto <D.18084>;
    <D.18083>:
    {
      struct SgenObjectOperations * ops;
      struct ScanCopyContext ctx;

      try
        {
          D.18093 = sgen_concurrent_collection_in_progress ();
          if (D.18093 != 0) goto <D.18094>; else goto <D.18095>;
          <D.18094>:
          iftmp.33 = &major->major_concurrent_ops;
          goto <D.18096>;
          <D.18095>:
          iftmp.33 = &major->major_ops;
          <D.18096>:
          ops = iftmp.33;
          D.18097 = ops->scan_object;
          ctx.scan_func = D.18097;
          ctx.copy_func = 0B;
          D.18088 = &data->private_gray_queue;
          ctx.queue = D.18088;
          D.18088 = &data->private_gray_queue;
          D.18098 = sgen_gray_object_queue_is_empty (D.18088);
          D.18099 = D.18098 != 0;
          D.18100 = (long int) D.18099;
          D.18101 = __builtin_expect (D.18100, 0);
          if (D.18101 != 0) goto <D.18102>; else goto <D.18103>;
          <D.18102>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 396, "!sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
          <D.18103>:
          goto <D.17740>;
          <D.17739>:
          D.18088 = &data->private_gray_queue;
          workers_gray_queue_share_redirect (D.18088);
          <D.17740>:
          D.18104 = sgen_drain_gray_stack (32, ctx);
          if (D.18104 == 0) goto <D.17739>; else goto <D.17741>;
          <D.17741>:
          D.18088 = &data->private_gray_queue;
          D.18105 = sgen_gray_object_queue_is_empty (D.18088);
          D.18106 = D.18105 == 0;
          D.18107 = (long int) D.18106;
          D.18108 = __builtin_expect (D.18107, 0);
          if (D.18108 != 0) goto <D.18109>; else goto <D.18110>;
          <D.18109>:
          monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 400, "sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
          <D.18110>:
          init_private_gray_queue (data);
          did_work = 1;
        }
      finally
        {
          ctx = {CLOBBER};
        }
    }
    <D.18084>:
    <D.18087>:
    if (did_work == 0) goto <D.18111>; else goto <D.18112>;
    <D.18111>:
    workers_wait ();
    <D.18112>:
  }
  goto <D.17742>;
  D.18113 = 0B;
  return D.18113;
}


workers_dequeue_and_do_job (struct WorkerData * data)
{
  int workers_job_queue_num_entries.34;
  gboolean D.18118;
  volatile struct JobQueueEntry * workers_job_queue.35;
  int workers_job_queue_num_entries.36;
  int workers_job_queue_num_entries.37;
  int D.18126;
  _Bool D.18127;
  long int D.18128;
  long int D.18129;
  void (*<T2ed8>) (struct WorkerData *, void *) D.18132;
  void * D.18133;
  int D.18134;
  int D.18135;
  struct JobQueueEntry * entry;

  workers_job_queue_num_entries.34 = workers_job_queue_num_entries;
  if (workers_job_queue_num_entries.34 == 0) goto <D.18116>; else goto <D.18117>;
  <D.18116>:
  D.18118 = 0;
  return D.18118;
  <D.18117>:
  pthread_mutex_lock (&workers_job_queue_mutex);
  entry = workers_job_queue;
  if (entry != 0B) goto <D.18119>; else goto <D.18120>;
  <D.18119>:
  workers_job_queue.35 = entry->next;
  workers_job_queue = workers_job_queue.35;
  workers_job_queue_num_entries.36 = workers_job_queue_num_entries;
  workers_job_queue_num_entries.37 = workers_job_queue_num_entries.36 + -1;
  workers_job_queue_num_entries = workers_job_queue_num_entries.37;
  <D.18120>:
  pthread_mutex_unlock (&workers_job_queue_mutex);
  if (entry == 0B) goto <D.18124>; else goto <D.18125>;
  <D.18124>:
  D.18118 = 0;
  return D.18118;
  <D.18125>:
  D.18126 = collection_needs_workers ();
  D.18127 = D.18126 == 0;
  D.18128 = (long int) D.18127;
  D.18129 = __builtin_expect (D.18128, 0);
  if (D.18129 != 0) goto <D.18130>; else goto <D.18131>;
  <D.18130>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 214, "collection_needs_workers ()");
  <D.18131>:
  D.18132 = entry->func;
  D.18133 = entry->data;
  D.18132 (data, D.18133);
  sgen_free_internal (entry, 26);
  {
    int __old_x;

    <D.17688>:
    __old_x = workers_num_jobs_finished;
    D.18134 = __old_x + 1;
    D.18135 = InterlockedCompareExchange (&workers_num_jobs_finished, D.18134, __old_x);
    if (D.18135 != __old_x) goto <D.17688>; else goto <D.17689>;
    <D.17689>:
  }
  D.18118 = 1;
  return D.18118;
}


workers_get_work (struct WorkerData * data)
{
  struct SgenGrayQueue * D.18137;
  int D.18138;
  _Bool D.18139;
  long int D.18140;
  long int D.18141;
  int D.18144;
  gboolean D.18147;
  struct WorkerData * workers_data.38;
  long unsigned int D.18149;
  long unsigned int D.18150;
  int D.18153;
  int workers_num.39;
  signed long D.18157;
  long unsigned int D.18158;
  long unsigned int D.18159;
  int D.18164;
  _Bool D.18165;
  long int D.18166;
  long int D.18167;
  struct SgenMajorCollector * major;
  int i;

  D.18137 = &data->private_gray_queue;
  D.18138 = sgen_gray_object_queue_is_empty (D.18137);
  D.18139 = D.18138 == 0;
  D.18140 = (long int) D.18139;
  D.18141 = __builtin_expect (D.18140, 0);
  if (D.18141 != 0) goto <D.18142>; else goto <D.18143>;
  <D.18142>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 275, "sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
  <D.18143>:
  D.18144 = workers_steal (data, data, 1);
  if (D.18144 != 0) goto <D.18145>; else goto <D.18146>;
  <D.18145>:
  D.18147 = 1;
  return D.18147;
  <D.18146>:
  i = 0;
  goto <D.17710>;
  <D.17709>:
  {
    struct WorkerData * victim_data;

    workers_data.38 = workers_data;
    D.18149 = (long unsigned int) i;
    D.18150 = D.18149 * 4192;
    victim_data = workers_data.38 + D.18150;
    if (data == victim_data) goto <D.18151>; else goto <D.18152>;
    <D.18151>:
    // predicted unlikely by continue predictor.
    goto <D.17708>;
    <D.18152>:
    D.18153 = workers_steal (data, victim_data, 1);
    if (D.18153 != 0) goto <D.18154>; else goto <D.18155>;
    <D.18154>:
    D.18147 = 1;
    return D.18147;
    <D.18155>:
  }
  <D.17708>:
  i = i + 1;
  <D.17710>:
  workers_num.39 = workers_num;
  if (i < workers_num.39) goto <D.17709>; else goto <D.17711>;
  <D.17711>:
  major = sgen_get_major_collector ();
  D.18157 = BIT_FIELD_REF <*major, 64, 64>;
  D.18158 = (long unsigned int) D.18157;
  D.18159 = D.18158;
  if (D.18159 != 0) goto <D.18160>; else goto <D.18161>;
  <D.18160>:
  {
    struct GrayQueueSection * section;

    section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
    if (section != 0B) goto <D.18162>; else goto <D.18163>;
    <D.18162>:
    D.18137 = &data->private_gray_queue;
    sgen_gray_object_enqueue_section (D.18137, section);
    D.18147 = 1;
    return D.18147;
    <D.18163>:
  }
  <D.18161>:
  D.18137 = &data->private_gray_queue;
  D.18164 = sgen_gray_object_queue_is_empty (D.18137);
  D.18165 = D.18164 == 0;
  D.18166 = (long int) D.18165;
  D.18167 = __builtin_expect (D.18166, 0);
  if (D.18167 != 0) goto <D.18168>; else goto <D.18169>;
  <D.18168>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 304, "sgen_gray_object_queue_is_empty (&data->private_gray_queue)");
  <D.18169>:
  D.18147 = 0;
  return D.18147;
}


workers_steal (struct WorkerData * data, struct WorkerData * victim_data, gboolean lock)
{
  struct GrayQueueSection * D.18171;
  _Bool D.18172;
  long int D.18173;
  long int D.18174;
  int D.18177;
  gboolean D.18180;
  union mono_mutex_t * D.18183;
  int D.18184;
  int D.18187;
  int D.18188;
  long unsigned int D.18189;
  long unsigned int D.18190;
  int D.18191;
  sizetype D.18192;
  sizetype D.18193;
  sizetype D.18194;
  sizetype D.18195;
  sizetype D.18196;
  char * * D.18197;
  char *[125] * D.18198;
  int D.18199;
  int D.18200;
  long long int D.18207;
  long long int stat_workers_stolen_from_self_lock.40;
  long long int stat_workers_stolen_from_self_lock.41;
  long long int stat_workers_stolen_from_self_no_lock.42;
  long long int stat_workers_stolen_from_self_no_lock.43;
  long long int stat_workers_stolen_from_others.44;
  long long int stat_workers_stolen_from_others.45;
  _Bool D.18216;
  struct SgenGrayQueue * queue;
  int num;
  int n;

  queue = &data->private_gray_queue;
  D.18171 = queue->first;
  D.18172 = D.18171 != 0B;
  D.18173 = (long int) D.18172;
  D.18174 = __builtin_expect (D.18173, 0);
  if (D.18174 != 0) goto <D.18175>; else goto <D.18176>;
  <D.18175>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 230, "!queue->first");
  <D.18176>:
  D.18177 = victim_data->stealable_stack_fill;
  if (D.18177 == 0) goto <D.18178>; else goto <D.18179>;
  <D.18178>:
  D.18180 = 0;
  return D.18180;
  <D.18179>:
  if (lock != 0) goto <D.18181>; else goto <D.18182>;
  <D.18181>:
  D.18183 = &victim_data->stealable_stack_mutex;
  D.18184 = pthread_mutex_trylock (D.18183);
  if (D.18184 != 0) goto <D.18185>; else goto <D.18186>;
  <D.18185>:
  D.18180 = 0;
  return D.18180;
  <D.18186>:
  <D.18182>:
  D.18187 = victim_data->stealable_stack_fill;
  D.18188 = D.18187 + 1;
  num = D.18188 / 2;
  n = num;
  goto <D.17700>;
  <D.17699>:
  {
    int m;

    m = MIN_EXPR <n, 125>;
    n = n - m;
    sgen_gray_object_alloc_queue_section (queue);
    D.18189 = (long unsigned int) m;
    D.18190 = D.18189 * 8;
    D.18191 = victim_data->stealable_stack_fill;
    D.18192 = (sizetype) D.18191;
    D.18193 = (sizetype) n;
    D.18194 = (sizetype) num;
    D.18195 = D.18193 - D.18194;
    D.18196 = D.18192 + D.18195;
    D.18197 = &victim_data->stealable_stack[D.18196];
    D.18171 = queue->first;
    D.18198 = &D.18171->objects;
    memcpy (D.18198, D.18197, D.18190);
    D.18171 = queue->first;
    D.18171->end = m;
  }
  <D.17700>:
  if (n > 0) goto <D.17699>; else goto <D.17701>;
  <D.17701>:
  D.18199 = victim_data->stealable_stack_fill;
  D.18200 = D.18199 - num;
  victim_data->stealable_stack_fill = D.18200;
  if (lock != 0) goto <D.18201>; else goto <D.18202>;
  <D.18201>:
  D.18183 = &victim_data->stealable_stack_mutex;
  pthread_mutex_unlock (D.18183);
  <D.18202>:
  if (data == victim_data) goto <D.18203>; else goto <D.18204>;
  <D.18203>:
  if (lock != 0) goto <D.18205>; else goto <D.18206>;
  <D.18205>:
  D.18207 = (long long int) num;
  stat_workers_stolen_from_self_lock.40 = stat_workers_stolen_from_self_lock;
  stat_workers_stolen_from_self_lock.41 = D.18207 + stat_workers_stolen_from_self_lock.40;
  stat_workers_stolen_from_self_lock = stat_workers_stolen_from_self_lock.41;
  goto <D.18210>;
  <D.18206>:
  D.18207 = (long long int) num;
  stat_workers_stolen_from_self_no_lock.42 = stat_workers_stolen_from_self_no_lock;
  stat_workers_stolen_from_self_no_lock.43 = D.18207 + stat_workers_stolen_from_self_no_lock.42;
  stat_workers_stolen_from_self_no_lock = stat_workers_stolen_from_self_no_lock.43;
  <D.18210>:
  goto <D.18213>;
  <D.18204>:
  D.18207 = (long long int) num;
  stat_workers_stolen_from_others.44 = stat_workers_stolen_from_others;
  stat_workers_stolen_from_others.45 = D.18207 + stat_workers_stolen_from_others.44;
  stat_workers_stolen_from_others = stat_workers_stolen_from_others.45;
  <D.18213>:
  D.18216 = num != 0;
  D.18180 = (gboolean) D.18216;
  return D.18180;
}


memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.18218;
  long unsigned int D.18219;

  D.18219 = __builtin_object_size (__dest, 0);
  D.18218 = __builtin___memcpy_chk (__dest, __src, __len, D.18219);
  return D.18218;
}


workers_gray_queue_share_redirect (struct SgenGrayQueue * queue)
{
  int D.18221;
  <unnamed-unsigned:1> D.18224;
  union mono_mutex_t * D.18227;
  int iftmp.46;
  int D.18229;
  int D.18230;
  int D.18231;
  int D.18235;
  long unsigned int D.18236;
  long unsigned int D.18237;
  sizetype D.18238;
  char * * D.18239;
  sizetype D.18240;
  char * * D.18241;
  int D.18242;
  sizetype D.18243;
  char * * D.18244;
  int D.18245;
  int D.18246;
  int D.18247;
  int D.18251;
  int D.18253;
  <unnamed-unsigned:1> D.18256;
  struct GrayQueueSection * section;
  struct WorkerData * data;

  data = queue->alloc_prepare_data;
  D.18221 = data->stealable_stack_fill;
  if (D.18221 != 0) goto <D.18222>; else goto <D.18223>;
  <D.18222>:
  D.18224 = workers_state.data.gc_in_progress;
  if (D.18224 != 0) goto <D.18225>; else goto <D.18226>;
  <D.18225>:
  workers_wake_up_all ();
  <D.18226>:
  return;
  <D.18223>:
  D.18227 = &data->stealable_stack_mutex;
  pthread_mutex_lock (D.18227);
  goto <D.17720>;
  <D.17719>:
  {
    int num;

    D.18229 = section->end;
    D.18230 = data->stealable_stack_fill;
    D.18231 = 512 - D.18230;
    if (D.18229 < D.18231) goto <D.18232>; else goto <D.18233>;
    <D.18232>:
    iftmp.46 = section->end;
    goto <D.18234>;
    <D.18233>:
    D.18235 = data->stealable_stack_fill;
    iftmp.46 = 512 - D.18235;
    <D.18234>:
    num = iftmp.46;
    D.18236 = (long unsigned int) num;
    D.18237 = D.18236 * 8;
    D.18229 = section->end;
    D.18238 = (sizetype) D.18229;
    D.18239 = &section->objects[D.18238];
    D.18236 = (long unsigned int) num;
    D.18237 = D.18236 * 8;
    D.18240 = -D.18237;
    D.18241 = D.18239 + D.18240;
    D.18242 = data->stealable_stack_fill;
    D.18243 = (sizetype) D.18242;
    D.18244 = &data->stealable_stack[D.18243];
    memcpy (D.18244, D.18241, D.18237);
    D.18229 = section->end;
    D.18245 = D.18229 - num;
    section->end = D.18245;
    D.18246 = data->stealable_stack_fill;
    D.18247 = D.18246 + num;
    data->stealable_stack_fill = D.18247;
    D.18229 = section->end;
    if (D.18229 != 0) goto <D.18248>; else goto <D.18249>;
    <D.18248>:
    sgen_gray_object_enqueue_section (queue, section);
    goto <D.18250>;
    <D.18249>:
    sgen_gray_object_free_queue_section (section);
    <D.18250>:
  }
  <D.17720>:
  D.18251 = data->stealable_stack_fill;
  if (D.18251 <= 511) goto <D.18252>; else goto <D.17721>;
  <D.18252>:
  section = sgen_gray_object_dequeue_section (queue);
  if (section != 0B) goto <D.17719>; else goto <D.17721>;
  <D.17721>:
  D.18253 = sgen_gray_object_queue_is_empty (queue);
  if (D.18253 != 0) goto <D.18254>; else goto <D.18255>;
  <D.18254>:
  workers_steal (data, data, 0);
  <D.18255>:
  D.18227 = &data->stealable_stack_mutex;
  pthread_mutex_unlock (D.18227);
  D.18256 = workers_state.data.gc_in_progress;
  if (D.18256 != 0) goto <D.18257>; else goto <D.18258>;
  <D.18257>:
  workers_wake_up_all ();
  <D.18258>:
}


sgen_gray_object_queue_is_empty (struct SgenGrayQueue * queue)
{
  gboolean D.18260;
  struct GrayQueueSection * D.18261;
  _Bool D.18262;

  D.18261 = queue->first;
  D.18262 = D.18261 == 0B;
  D.18260 = (gboolean) D.18262;
  return D.18260;
}


init_private_gray_queue (struct WorkerData * data)
{
  void (*<T2b40>) (char *) iftmp.47;
  struct SgenMajorCollector * D.18265;
  int D.18266;
  struct SgenGrayQueue * D.18270;

  D.18265 = sgen_get_major_collector ();
  D.18266 = D.18265->is_concurrent;
  if (D.18266 != 0) goto <D.18267>; else goto <D.18268>;
  <D.18267>:
  iftmp.47 = concurrent_enqueue_check;
  goto <D.18269>;
  <D.18268>:
  iftmp.47 = 0B;
  <D.18269>:
  D.18270 = &data->private_gray_queue;
  sgen_gray_object_queue_init_with_alloc_prepare (D.18270, iftmp.47, workers_gray_queue_share_redirect, data);
}


workers_wait ()
{
  long long int stat_workers_num_waited.48;
  long long int stat_workers_num_waited.49;
  unsigned char D.18273;
  unsigned char D.18274;
  _Bool D.18275;
  long int D.18276;
  long int D.18277;
  unsigned char D.18280;
  unsigned char D.18281;
  int D.18282;
  int workers_num.50;
  unsigned char D.18286;
  int D.18289;
  unsigned char D.18290;
  unsigned char D.18291;
  union State old_state;
  union State new_state;

  try
    {
      stat_workers_num_waited.48 = stat_workers_num_waited;
      stat_workers_num_waited.49 = stat_workers_num_waited.48 + 1;
      stat_workers_num_waited = stat_workers_num_waited.49;
      <D.17665>:
      new_state = workers_state;
      old_state = new_state;
      D.18273 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18274 = D.18273 & 1;
      D.18275 = D.18274 != 0;
      D.18276 = (long int) D.18275;
      D.18277 = __builtin_expect (D.18276, 0);
      if (D.18277 != 0) goto <D.18278>; else goto <D.18279>;
      <D.18278>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 125, "!old_state.data.done_posted");
      <D.18279>:
      D.18280 = new_state.data.num_waiting;
      D.18281 = D.18280 + 1;
      new_state.data.num_waiting = D.18281;
      D.18280 = new_state.data.num_waiting;
      D.18282 = (int) D.18280;
      workers_num.50 = workers_num;
      if (D.18282 == workers_num.50) goto <D.18284>; else goto <D.18285>;
      <D.18284>:
      D.18273 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18286 = D.18273 & 2;
      if (D.18286 == 0) goto <D.18287>; else goto <D.18288>;
      <D.18287>:
      new_state.data.done_posted = 1;
      <D.18288>:
      <D.18285>:
      D.18289 = set_state (old_state, new_state);
      if (D.18289 == 0) goto <D.17665>; else goto <D.17666>;
      <D.17666>:
      mono_memory_barrier ();
      D.18290 = BIT_FIELD_REF <new_state, 8, 8>;
      D.18291 = D.18290 & 1;
      if (D.18291 != 0) goto <D.18292>; else goto <D.18293>;
      <D.18292>:
      mono_sem_post (&workers_done_sem);
      <D.18293>:
      mono_sem_wait (&workers_waiting_sem, 0);
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


sgen_workers_have_started ()
{
  gboolean D.18294;
  <unnamed-unsigned:1> D.18295;

  D.18295 = workers_state.data.gc_in_progress;
  D.18294 = (gboolean) D.18295;
  return D.18294;
}


sgen_workers_start_marking ()
{
  int D.18297;
  int iftmp.51;
  int workers_started.52;
  <unnamed-unsigned:1> D.18306;
  _Bool D.18307;
  long int D.18308;
  long int D.18309;
  int workers_marking.53;
  _Bool D.18313;
  long int D.18314;
  long int D.18315;

  D.18297 = collection_needs_workers ();
  if (D.18297 == 0) goto <D.18298>; else goto <D.18299>;
  <D.18298>:
  return;
  <D.18299>:
  workers_started.52 = workers_started;
  if (workers_started.52 == 0) goto <D.18301>; else goto <D.18305>;
  <D.18305>:
  D.18306 = workers_state.data.gc_in_progress;
  if (D.18306 == 0) goto <D.18301>; else goto <D.18302>;
  <D.18301>:
  iftmp.51 = 1;
  goto <D.18303>;
  <D.18302>:
  iftmp.51 = 0;
  <D.18303>:
  D.18307 = iftmp.51 != 0;
  D.18308 = (long int) D.18307;
  D.18309 = __builtin_expect (D.18308, 0);
  if (D.18309 != 0) goto <D.18310>; else goto <D.18311>;
  <D.18310>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 552, "workers_started && workers_state.data.gc_in_progress");
  <D.18311>:
  workers_marking.53 = workers_marking;
  D.18313 = workers_marking.53 != 0;
  D.18314 = (long int) D.18313;
  D.18315 = __builtin_expect (D.18314, 0);
  if (D.18315 != 0) goto <D.18316>; else goto <D.18317>;
  <D.18316>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 553, "!workers_marking");
  <D.18317>:
  workers_marking = 1;
  workers_wake_up_all ();
}


sgen_workers_join ()
{
  int D.18319;
  unsigned char D.18322;
  unsigned char D.18323;
  _Bool D.18324;
  long int D.18325;
  long int D.18326;
  unsigned char D.18329;
  _Bool D.18330;
  long int D.18331;
  long int D.18332;
  int D.18335;
  unsigned char D.18336;
  int D.18337;
  int workers_num.54;
  unsigned char D.18341;
  int D.18342;
  _Bool D.18343;
  long int D.18344;
  long int D.18345;
  _Bool D.18348;
  long int D.18349;
  long int D.18350;
  int workers_job_queue_num_entries.55;
  int D.18357;
  int D.18358;
  struct SgenMajorCollector * D.18361;
  void (*<Tc2>) (void *) D.18362;
  struct SgenMajorCollector * D.18365;
  void (*<Tc2>) (void *) D.18366;
  struct WorkerData * workers_data.56;
  long unsigned int D.18368;
  long unsigned int D.18369;
  struct WorkerData * D.18370;
  void * D.18371;
  int workers_job_queue_num_entries.57;
  _Bool D.18373;
  long int D.18374;
  long int D.18375;
  int D.18378;
  _Bool D.18379;
  long int D.18380;
  long int D.18381;
  int D.18384;
  _Bool D.18385;
  long int D.18386;
  long int D.18387;
  struct SgenGrayQueue * D.18390;
  int D.18391;
  _Bool D.18392;
  long int D.18393;
  long int D.18394;
  union State old_state;
  union State new_state;
  int i;
  void reawaken = <<< error >>>;

  try
    {
      D.18319 = collection_needs_workers ();
      if (D.18319 == 0) goto <D.18320>; else goto <D.18321>;
      <D.18320>:
      return;
      <D.18321>:
      <D.17781>:
      new_state = workers_state;
      old_state = new_state;
      D.18322 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18323 = D.18322 & 2;
      D.18324 = D.18323 == 0;
      D.18325 = (long int) D.18324;
      D.18326 = __builtin_expect (D.18325, 0);
      if (D.18326 != 0) goto <D.18327>; else goto <D.18328>;
      <D.18327>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 571, "old_state.data.gc_in_progress");
      <D.18328>:
      D.18322 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18329 = D.18322 & 1;
      D.18330 = D.18329 != 0;
      D.18331 = (long int) D.18330;
      D.18332 = __builtin_expect (D.18331, 0);
      if (D.18332 != 0) goto <D.18333>; else goto <D.18334>;
      <D.18333>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 572, "!old_state.data.done_posted");
      <D.18334>:
      new_state.data.gc_in_progress = 0;
      D.18335 = set_state (old_state, new_state);
      if (D.18335 == 0) goto <D.17781>; else goto <D.17782>;
      <D.17782>:
      D.18336 = new_state.data.num_waiting;
      D.18337 = (int) D.18336;
      workers_num.54 = workers_num;
      if (D.18337 == workers_num.54) goto <D.18339>; else goto <D.18340>;
      <D.18339>:
      reawaken:
      workers_wake_up_all ();
      <D.18340>:
      mono_sem_wait (&workers_done_sem, 0);
      new_state = workers_state;
      old_state = new_state;
      D.18341 = old_state.data.num_waiting;
      D.18342 = (int) D.18341;
      workers_num.54 = workers_num;
      D.18343 = D.18342 != workers_num.54;
      D.18344 = (long int) D.18343;
      D.18345 = __builtin_expect (D.18344, 0);
      if (D.18345 != 0) goto <D.18346>; else goto <D.18347>;
      <D.18346>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 593, "old_state.data.num_waiting == workers_num");
      <D.18347>:
      D.18322 = BIT_FIELD_REF <old_state, 8, 8>;
      D.18329 = D.18322 & 1;
      D.18348 = D.18329 == 0;
      D.18349 = (long int) D.18348;
      D.18350 = __builtin_expect (D.18349, 0);
      if (D.18350 != 0) goto <D.18351>; else goto <D.18352>;
      <D.18351>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 594, "old_state.data.done_posted");
      <D.18352>:
      workers_job_queue_num_entries.55 = workers_job_queue_num_entries;
      if (workers_job_queue_num_entries.55 != 0) goto <D.18353>; else goto <D.18356>;
      <D.18356>:
      D.18357 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      if (D.18357 == 0) goto <D.18353>; else goto <D.18354>;
      <D.18353>:
      new_state.data.done_posted = 0;
      D.18358 = set_state (old_state, new_state);
      if (D.18358 == 0) goto <D.18359>; else goto <D.18360>;
      <D.18359>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 613);
      <D.18360>:
      goto reawaken;
      <D.18354>:
      workers_marking = 0;
      D.18361 = sgen_get_major_collector ();
      D.18362 = D.18361->reset_worker_data;
      if (D.18362 != 0B) goto <D.18363>; else goto <D.18364>;
      <D.18363>:
      i = 0;
      goto <D.17785>;
      <D.17784>:
      D.18365 = sgen_get_major_collector ();
      D.18366 = D.18365->reset_worker_data;
      workers_data.56 = workers_data;
      D.18368 = (long unsigned int) i;
      D.18369 = D.18368 * 4192;
      D.18370 = workers_data.56 + D.18369;
      D.18371 = D.18370->major_collector_data;
      D.18366 (D.18371);
      i = i + 1;
      <D.17785>:
      workers_num.54 = workers_num;
      if (i < workers_num.54) goto <D.17784>; else goto <D.17786>;
      <D.17786>:
      <D.18364>:
      workers_job_queue_num_entries.57 = workers_job_queue_num_entries;
      D.18373 = workers_job_queue_num_entries.57 != 0;
      D.18374 = (long int) D.18373;
      D.18375 = __builtin_expect (D.18374, 0);
      if (D.18375 != 0) goto <D.18376>; else goto <D.18377>;
      <D.18376>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 626, "workers_job_queue_num_entries == 0");
      <D.18377>:
      D.18378 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      D.18379 = D.18378 == 0;
      D.18380 = (long int) D.18379;
      D.18381 = __builtin_expect (D.18380, 0);
      if (D.18381 != 0) goto <D.18382>; else goto <D.18383>;
      <D.18382>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 627, "sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue)");
      <D.18383>:
      i = 0;
      goto <D.17788>;
      <D.17787>:
      workers_data.56 = workers_data;
      D.18368 = (long unsigned int) i;
      D.18369 = D.18368 * 4192;
      D.18370 = workers_data.56 + D.18369;
      D.18384 = D.18370->stealable_stack_fill;
      D.18385 = D.18384 != 0;
      D.18386 = (long int) D.18385;
      D.18387 = __builtin_expect (D.18386, 0);
      if (D.18387 != 0) goto <D.18388>; else goto <D.18389>;
      <D.18388>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 629, "!workers_data [i].stealable_stack_fill");
      <D.18389>:
      workers_data.56 = workers_data;
      D.18368 = (long unsigned int) i;
      D.18369 = D.18368 * 4192;
      D.18370 = workers_data.56 + D.18369;
      D.18390 = &D.18370->private_gray_queue;
      D.18391 = sgen_gray_object_queue_is_empty (D.18390);
      D.18392 = D.18391 == 0;
      D.18393 = (long int) D.18392;
      D.18394 = __builtin_expect (D.18393, 0);
      if (D.18394 != 0) goto <D.18395>; else goto <D.18396>;
      <D.18395>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 630, "sgen_gray_object_queue_is_empty (&workers_data [i].private_gray_queue)");
      <D.18396>:
      i = i + 1;
      <D.17788>:
      workers_num.54 = workers_num;
      if (i < workers_num.54) goto <D.17787>; else goto <D.17789>;
      <D.17789>:
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


sgen_workers_all_done ()
{
  unsigned char D.18400;
  unsigned char D.18401;
  _Bool D.18402;
  long int D.18403;
  long int D.18404;
  unsigned char D.18407;
  _Bool D.18408;
  long int D.18409;
  long int D.18410;
  gboolean D.18413;
  unsigned char D.18414;
  int D.18415;
  int workers_num.58;
  _Bool D.18417;
  union State state;

  try
    {
      state = workers_state;
      D.18400 = BIT_FIELD_REF <state, 8, 8>;
      D.18401 = D.18400 & 2;
      D.18402 = D.18401 == 0;
      D.18403 = (long int) D.18402;
      D.18404 = __builtin_expect (D.18403, 0);
      if (D.18404 != 0) goto <D.18405>; else goto <D.18406>;
      <D.18405>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 642, "state.data.gc_in_progress");
      <D.18406>:
      D.18400 = BIT_FIELD_REF <state, 8, 8>;
      D.18407 = D.18400 & 1;
      D.18408 = D.18407 != 0;
      D.18409 = (long int) D.18408;
      D.18410 = __builtin_expect (D.18409, 0);
      if (D.18410 != 0) goto <D.18411>; else goto <D.18412>;
      <D.18411>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 643, "!state.data.done_posted");
      <D.18412>:
      D.18414 = state.data.num_waiting;
      D.18415 = (int) D.18414;
      workers_num.58 = workers_num;
      D.18417 = D.18415 == workers_num.58;
      D.18413 = (gboolean) D.18417;
      return D.18413;
    }
  finally
    {
      state = {CLOBBER};
    }
}


sgen_is_worker_thread (MonoNativeThreadId thread)
{
  struct SgenMajorCollector * D.18420;
  gboolean (*<T2d20>) (MonoNativeThreadId) D.18421;
  struct SgenMajorCollector * D.18424;
  gboolean (*<T2d20>) (MonoNativeThreadId) D.18425;
  int D.18426;
  gboolean D.18429;
  struct WorkerData * workers_data.59;
  long unsigned int D.18431;
  long unsigned int D.18432;
  struct WorkerData * D.18433;
  long unsigned int D.18434;
  int workers_num.60;
  int i;

  D.18420 = sgen_get_major_collector ();
  D.18421 = D.18420->is_worker_thread;
  if (D.18421 != 0B) goto <D.18422>; else goto <D.18423>;
  <D.18422>:
  D.18424 = sgen_get_major_collector ();
  D.18425 = D.18424->is_worker_thread;
  D.18426 = D.18425 (thread);
  if (D.18426 != 0) goto <D.18427>; else goto <D.18428>;
  <D.18427>:
  D.18429 = 1;
  return D.18429;
  <D.18428>:
  <D.18423>:
  i = 0;
  goto <D.17799>;
  <D.17798>:
  workers_data.59 = workers_data;
  D.18431 = (long unsigned int) i;
  D.18432 = D.18431 * 4192;
  D.18433 = workers_data.59 + D.18432;
  D.18434 = D.18433->thread;
  if (D.18434 == thread) goto <D.18435>; else goto <D.18436>;
  <D.18435>:
  D.18429 = 1;
  return D.18429;
  <D.18436>:
  i = i + 1;
  <D.17799>:
  workers_num.60 = workers_num;
  if (i < workers_num.60) goto <D.17798>; else goto <D.17800>;
  <D.17800>:
  D.18429 = 0;
  return D.18429;
}


sgen_workers_get_distribute_section_gray_queue ()
{
  struct SgenSectionGrayQueue * D.18439;

  D.18439 = &workers_distribute_gray_queue;
  return D.18439;
}


sgen_workers_reset_data ()
{
  struct SgenMajorCollector * D.18441;
  void (*<Tc2>) (void *) D.18442;
  struct SgenMajorCollector * D.18445;
  void (*<Tc2>) (void *) D.18446;
  void * workers_gc_thread_major_collector_data.61;

  D.18441 = sgen_get_major_collector ();
  D.18442 = D.18441->reset_worker_data;
  if (D.18442 != 0B) goto <D.18443>; else goto <D.18444>;
  <D.18443>:
  D.18445 = sgen_get_major_collector ();
  D.18446 = D.18445->reset_worker_data;
  workers_gc_thread_major_collector_data.61 = workers_gc_thread_major_collector_data;
  D.18446 (workers_gc_thread_major_collector_data.61);
  <D.18444>:
}


