__attribute__((visibility ("hidden")))
sgen_workers_wake_up_all ()
{
  <unnamed-unsigned:1> D.17952;
  _Bool D.17953;
  long int D.17954;
  long int D.17955;

  D.17952 = workers_state.data.gc_in_progress;
  D.17953 = ~D.17952;
  D.17954 = (long int) D.17953;
  D.17955 = __builtin_expect (D.17954, 0);
  if (D.17955 != 0) goto <D.17956>; else goto <D.17957>;
  <D.17956>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 109, "workers_state.data.gc_in_progress");
  <D.17957>:
  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 int D.17959;
  unsigned int D.17960;
  unsigned char D.17963;
  unsigned char D.17966;
  unsigned char D.17967;
  int D.17968;
  int i;

  i = 0;
  goto <D.17796>;
  <D.17795>:
  {
    union State old_state;
    union State new_state;

    try
      {
        <D.17793>:
        new_state = workers_state;
        old_state = new_state;
        D.17959 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
        D.17960 = D.17959 & 8388608;
        if (D.17960 != 0) goto <D.17961>; else goto <D.17962>;
        <D.17961>:
        return;
        <D.17962>:
        D.17963 = old_state.data.num_waiting;
        if (D.17963 == 0) goto <D.17964>; else goto <D.17965>;
        <D.17964>:
        return;
        <D.17965>:
        D.17966 = new_state.data.num_waiting;
        D.17967 = D.17966 + 255;
        new_state.data.num_waiting = D.17967;
        D.17968 = set_state (old_state, new_state);
        if (D.17968 == 0) goto <D.17793>; else goto <D.17794>;
        <D.17794>:
        mono_sem_post (&workers_waiting_sem);
      }
    finally
      {
        old_state = {CLOBBER};
        new_state = {CLOBBER};
      }
  }
  i = i + 1;
  <D.17796>:
  if (i < max) goto <D.17795>; else goto <D.17797>;
  <D.17797>:
}


set_state (union State old_state, union State new_state)
{
  gboolean D.17972;
  int D.17973;
  int D.17974;
  int D.17975;
  _Bool D.17976;

  D.17973 = new_state.value;
  D.17974 = old_state.value;
  D.17975 = InterlockedCompareExchange (&workers_state.value, D.17973, D.17974);
  D.17974 = old_state.value;
  D.17976 = D.17975 == D.17974;
  D.17972 = (gboolean) D.17976;
  return D.17972;
}


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

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


__attribute__((visibility ("hidden")))
sgen_workers_enqueue_job (void (*JobFunc) (struct WorkerData *, void *) func, void * data)
{
  int D.17983;
  <unnamed-unsigned:1> D.17986;
  _Bool D.17987;
  long int D.17988;
  long int D.17989;
  volatile struct JobQueueEntry * workers_job_queue.3;
  int workers_job_queue_num_entries.4;
  int D.17994;
  int num_entries.5;
  int workers_num_jobs_enqueued.6;
  int D.17997;
  int num_entries;
  struct JobQueueEntry * entry;

  D.17983 = collection_needs_workers ();
  if (D.17983 == 0) goto <D.17984>; else goto <D.17985>;
  <D.17984>:
  func (0B, data);
  return;
  <D.17985>:
  D.17986 = workers_state.data.gc_in_progress;
  D.17987 = ~D.17986;
  D.17988 = (long int) D.17987;
  D.17989 = __builtin_expect (D.17988, 0);
  if (D.17989 != 0) goto <D.17990>; else goto <D.17991>;
  <D.17990>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 157, "workers_state.data.gc_in_progress");
  <D.17991>:
  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;
  D.17994 = workers_job_queue_num_entries.4 + 1;
  num_entries.5 = D.17994;
  workers_job_queue_num_entries = num_entries.5;
  num_entries = num_entries.5;
  workers_num_jobs_enqueued.6 = workers_num_jobs_enqueued;
  D.17997 = workers_num_jobs_enqueued.6 + 1;
  workers_num_jobs_enqueued = D.17997;
  pthread_mutex_unlock (&workers_job_queue_mutex);
  workers_wake_up (num_entries);
}


collection_needs_workers ()
{
  gboolean D.17999;
  int iftmp.7;
  int D.18004;
  int D.18006;

  D.18004 = sgen_collection_is_parallel ();
  if (D.18004 != 0) goto <D.18001>; else goto <D.18005>;
  <D.18005>:
  D.18006 = sgen_collection_is_concurrent ();
  if (D.18006 != 0) goto <D.18001>; else goto <D.18002>;
  <D.18001>:
  iftmp.7 = 1;
  goto <D.18003>;
  <D.18002>:
  iftmp.7 = 0;
  <D.18003>:
  D.17999 = iftmp.7;
  return D.17999;
}


__attribute__((visibility ("hidden")))
sgen_workers_wait_for_jobs ()
{
  unsigned int D.18008;
  unsigned int D.18009;
  _Bool D.18010;
  long int D.18011;
  long int D.18012;
  unsigned int D.18015;
  _Bool D.18016;
  long int D.18017;
  long int D.18018;
  unsigned char D.18021;
  int D.18022;
  int workers_num.8;
  int workers_num_jobs_finished.9;
  int workers_num_jobs_enqueued.10;

  goto <D.17825>;
  <D.17824>:
  {
    union State state;

    try
      {
        state = workers_state;
        D.18008 = BIT_FIELD_REF <MEM[(void *)&state], 32, 0>;
        D.18009 = D.18008 & 4194304;
        D.18010 = D.18009 == 0;
        D.18011 = (long int) D.18010;
        D.18012 = __builtin_expect (D.18011, 0);
        if (D.18012 != 0) goto <D.18013>; else goto <D.18014>;
        <D.18013>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 179, "state.data.gc_in_progress");
        <D.18014>:
        D.18008 = BIT_FIELD_REF <MEM[(void *)&state], 32, 0>;
        D.18015 = D.18008 & 8388608;
        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", 180, "!state.data.done_posted");
        <D.18020>:
        D.18021 = state.data.num_waiting;
        D.18022 = (int) D.18021;
        workers_num.8 = workers_num;
        if (D.18022 == workers_num.8) goto <D.18024>; else goto <D.18025>;
        <D.18024>:
        workers_wake_up_all ();
        <D.18025>:
        monoeg_g_usleep (1000);
      }
    finally
      {
        state = {CLOBBER};
      }
  }
  <D.17825>:
  workers_num_jobs_finished.9 = workers_num_jobs_finished;
  workers_num_jobs_enqueued.10 = workers_num_jobs_enqueued;
  if (workers_num_jobs_finished.9 < workers_num_jobs_enqueued.10) goto <D.17824>; else goto <D.17826>;
  <D.17826>:
}


__attribute__((visibility ("hidden")))
sgen_workers_init_distribute_gray_queue ()
{
  int D.18028;
  int iftmp.11;
  struct SgenMajorCollector * D.18035;
  int D.18036;
  struct SgenMajorCollector * D.18038;
  int D.18039;

  D.18028 = collection_needs_workers ();
  if (D.18028 == 0) goto <D.18029>; else goto <D.18030>;
  <D.18029>:
  return;
  <D.18030>:
  D.18035 = sgen_get_major_collector ();
  D.18036 = D.18035->is_concurrent;
  if (D.18036 != 0) goto <D.18032>; else goto <D.18037>;
  <D.18037>:
  D.18038 = sgen_get_major_collector ();
  D.18039 = D.18038->is_parallel;
  if (D.18039 != 0) goto <D.18032>; else goto <D.18033>;
  <D.18032>:
  iftmp.11 = 1;
  goto <D.18034>;
  <D.18033>:
  iftmp.11 = 0;
  <D.18034>:
  init_distribute_gray_queue (iftmp.11);
}


init_distribute_gray_queue (gboolean locked)
{
  int workers_distribute_gray_queue_inited.12;
  int D.18044;
  _Bool D.18045;
  long int D.18046;
  long int D.18047;
  int D.18050;
  _Bool D.18051;
  _Bool D.18052;
  _Bool D.18053;
  _Bool D.18054;
  long int D.18055;
  long int D.18056;
  void (*<T2c84>) (char *) iftmp.13;
  struct SgenMajorCollector * D.18060;
  int D.18061;

  workers_distribute_gray_queue_inited.12 = workers_distribute_gray_queue_inited;
  if (workers_distribute_gray_queue_inited.12 != 0) goto <D.18042>; else goto <D.18043>;
  <D.18042>:
  D.18044 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
  D.18045 = D.18044 == 0;
  D.18046 = (long int) D.18045;
  D.18047 = __builtin_expect (D.18046, 0);
  if (D.18047 != 0) goto <D.18048>; else goto <D.18049>;
  <D.18048>:
  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.18049>:
  D.18050 = workers_distribute_gray_queue.locked;
  D.18051 = D.18050 == 0;
  D.18052 = locked == 0;
  D.18053 = D.18051 ^ D.18052;
  D.18054 = D.18053;
  D.18055 = (long int) D.18054;
  D.18056 = __builtin_expect (D.18055, 0);
  if (D.18056 != 0) goto <D.18057>; else goto <D.18058>;
  <D.18057>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 420, "!workers_distribute_gray_queue.locked == !locked");
  <D.18058>:
  return;
  <D.18043>:
  D.18060 = sgen_get_major_collector ();
  D.18061 = D.18060->is_concurrent;
  if (D.18061 != 0) goto <D.18062>; else goto <D.18063>;
  <D.18062>:
  iftmp.13 = concurrent_enqueue_check;
  goto <D.18064>;
  <D.18063>:
  iftmp.13 = 0B;
  <D.18064>:
  sgen_section_gray_queue_init (&workers_distribute_gray_queue, locked, iftmp.13);
  workers_distribute_gray_queue_inited = 1;
}


concurrent_enqueue_check (char * obj)
{
  int D.18066;
  _Bool D.18067;
  long int D.18068;
  long int D.18069;
  int D.18072;
  _Bool D.18073;
  long int D.18074;
  long int D.18075;
  long unsigned int D.18078;
  long unsigned int D.18079;
  _Bool D.18080;
  long int D.18081;
  long int D.18082;

  D.18066 = sgen_concurrent_collection_in_progress ();
  D.18067 = D.18066 == 0;
  D.18068 = (long int) D.18067;
  D.18069 = __builtin_expect (D.18068, 0);
  if (D.18069 != 0) goto <D.18070>; else goto <D.18071>;
  <D.18070>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 356, "sgen_concurrent_collection_in_progress ()");
  <D.18071>:
  D.18072 = sgen_ptr_in_nursery (obj);
  D.18073 = D.18072 != 0;
  D.18074 = (long int) D.18073;
  D.18075 = __builtin_expect (D.18074, 0);
  if (D.18075 != 0) goto <D.18076>; else goto <D.18077>;
  <D.18076>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 357, "!sgen_ptr_in_nursery (obj)");
  <D.18077>:
  D.18078 = MEM[(mword *)obj];
  D.18079 = D.18078 & 18446744073709551612;
  D.18080 = D.18079 == 0;
  D.18081 = (long int) D.18080;
  D.18082 = __builtin_expect (D.18081, 0);
  if (D.18082 != 0) goto <D.18083>; else goto <D.18084>;
  <D.18083>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 358, "SGEN_LOAD_VTABLE (obj)");
  <D.18084>:
}


__attribute__((always_inline))
sgen_ptr_in_nursery (void * p)
{
  gboolean D.18085;
  int sgen_nursery_bits.14;
  int D.18087;
  int D.18088;
  long unsigned int D.18089;
  long unsigned int p.15;
  long unsigned int D.18091;
  char * sgen_nursery_start.16;
  long unsigned int sgen_nursery_start.17;
  _Bool D.18094;

  sgen_nursery_bits.14 = sgen_nursery_bits;
  D.18087 = 1 << sgen_nursery_bits.14;
  D.18088 = -D.18087;
  D.18089 = (long unsigned int) D.18088;
  p.15 = (long unsigned int) p;
  D.18091 = D.18089 & p.15;
  sgen_nursery_start.16 = sgen_nursery_start;
  sgen_nursery_start.17 = (long unsigned int) sgen_nursery_start.16;
  D.18094 = D.18091 == sgen_nursery_start.17;
  D.18085 = (gboolean) D.18094;
  return D.18085;
}


__attribute__((visibility ("hidden")))
sgen_workers_init (int num_workers)
{
  struct SgenMajorCollector * D.18096;
  int D.18097;
  struct SgenMajorCollector * D.18100;
  int D.18101;
  long unsigned int D.18104;
  long unsigned int D.18105;
  void * D.18106;
  struct WorkerData * workers_data.18;
  int iftmp.19;
  struct SgenMajorCollector * D.18112;
  int D.18113;
  struct SgenMajorCollector * D.18115;
  int D.18116;
  struct SgenMajorCollector * D.18117;
  void * (*<T2bee>) (void) D.18118;
  struct SgenMajorCollector * D.18121;
  void * (*<T2bee>) (void) D.18122;
  void * D.18123;
  long unsigned int D.18124;
  long unsigned int D.18125;
  struct WorkerData * D.18126;
  union mono_mutex_t * D.18127;
  struct SgenMajorCollector * D.18128;
  void * (*<T2bee>) (void) D.18129;
  struct SgenMajorCollector * D.18132;
  void * (*<T2bee>) (void) D.18133;
  void * D.18134;
  int workers_num.20;
  int i;

  D.18096 = sgen_get_major_collector ();
  D.18097 = D.18096->is_parallel;
  if (D.18097 == 0) goto <D.18098>; else goto <D.18099>;
  <D.18098>:
  D.18100 = sgen_get_major_collector ();
  D.18101 = D.18100->is_concurrent;
  if (D.18101 == 0) goto <D.18102>; else goto <D.18103>;
  <D.18102>:
  return;
  <D.18103>:
  <D.18099>:
  workers_num = num_workers;
  D.18104 = (long unsigned int) num_workers;
  D.18105 = D.18104 * 4192;
  D.18106 = sgen_alloc_internal_dynamic (D.18105, 19, 1);
  workers_data = D.18106;
  workers_data.18 = workers_data;
  D.18104 = (long unsigned int) num_workers;
  D.18105 = D.18104 * 4192;
  memset (workers_data.18, 0, D.18105);
  sem_init (&workers_waiting_sem, 0, 0);
  sem_init (&workers_done_sem, 0, 0);
  D.18112 = sgen_get_major_collector ();
  D.18113 = D.18112->is_concurrent;
  if (D.18113 != 0) goto <D.18109>; else goto <D.18114>;
  <D.18114>:
  D.18115 = sgen_get_major_collector ();
  D.18116 = D.18115->is_parallel;
  if (D.18116 != 0) goto <D.18109>; else goto <D.18110>;
  <D.18109>:
  iftmp.19 = 1;
  goto <D.18111>;
  <D.18110>:
  iftmp.19 = 0;
  <D.18111>:
  init_distribute_gray_queue (iftmp.19);
  D.18117 = sgen_get_major_collector ();
  D.18118 = D.18117->alloc_worker_data;
  if (D.18118 != 0B) goto <D.18119>; else goto <D.18120>;
  <D.18119>:
  D.18121 = sgen_get_major_collector ();
  D.18122 = D.18121->alloc_worker_data;
  D.18123 = D.18122 ();
  workers_gc_thread_major_collector_data = D.18123;
  <D.18120>:
  i = 0;
  goto <D.17898>;
  <D.17897>:
  workers_data.18 = workers_data;
  D.18124 = (long unsigned int) i;
  D.18125 = D.18124 * 4192;
  D.18126 = workers_data.18 + D.18125;
  D.18127 = &D.18126->stealable_stack_mutex;
  pthread_mutex_init (D.18127, 0B);
  workers_data.18 = workers_data;
  D.18124 = (long unsigned int) i;
  D.18125 = D.18124 * 4192;
  D.18126 = workers_data.18 + D.18125;
  D.18126->stealable_stack_fill = 0;
  D.18128 = sgen_get_major_collector ();
  D.18129 = D.18128->alloc_worker_data;
  if (D.18129 != 0B) goto <D.18130>; else goto <D.18131>;
  <D.18130>:
  workers_data.18 = workers_data;
  D.18124 = (long unsigned int) i;
  D.18125 = D.18124 * 4192;
  D.18126 = workers_data.18 + D.18125;
  D.18132 = sgen_get_major_collector ();
  D.18133 = D.18132->alloc_worker_data;
  D.18134 = D.18133 ();
  D.18126->major_collector_data = D.18134;
  <D.18131>:
  i = i + 1;
  <D.17898>:
  workers_num.20 = workers_num;
  if (i < workers_num.20) goto <D.17897>; else goto <D.17899>;
  <D.17899>:
  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);
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__, __nothrow__, __leaf__))
memset (void * __dest, int __ch, size_t __len)
{
  void * D.18137;
  long unsigned int D.18138;

  D.18138 = __builtin_object_size (__dest, 0);
  D.18137 = __builtin___memset_chk (__dest, __ch, __len, D.18138);
  return D.18137;
}


__attribute__((visibility ("hidden")))
sgen_workers_start_all_workers ()
{
  int D.18140;
  struct SgenMajorCollector * D.18143;
  void (*<Tc6>) (void *) D.18144;
  struct SgenMajorCollector * D.18147;
  void (*<Tc6>) (void *) D.18148;
  void * workers_gc_thread_major_collector_data.21;
  unsigned int D.18150;
  unsigned int D.18151;
  _Bool D.18152;
  long int D.18153;
  long int D.18154;
  int workers_job_queue_num_entries.22;
  _Bool D.18158;
  long int D.18159;
  long int D.18160;
  int workers_started.23;
  unsigned int D.18166;
  _Bool D.18167;
  long int D.18168;
  long int D.18169;
  unsigned char D.18172;
  int D.18173;
  int workers_num.24;
  int D.18177;
  _Bool D.18180;
  long int D.18181;
  long int D.18182;
  int D.18185;
  union State old_state;
  union State new_state;
  int i;

  try
    {
      D.18140 = collection_needs_workers ();
      if (D.18140 == 0) goto <D.18141>; else goto <D.18142>;
      <D.18141>:
      return;
      <D.18142>:
      D.18143 = sgen_get_major_collector ();
      D.18144 = D.18143->init_worker_thread;
      if (D.18144 != 0B) goto <D.18145>; else goto <D.18146>;
      <D.18145>:
      D.18147 = sgen_get_major_collector ();
      D.18148 = D.18147->init_worker_thread;
      workers_gc_thread_major_collector_data.21 = workers_gc_thread_major_collector_data;
      D.18148 (workers_gc_thread_major_collector_data.21);
      <D.18146>:
      new_state = workers_state;
      old_state = new_state;
      D.18150 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18151 = D.18150 & 4194304;
      D.18152 = D.18151 != 0;
      D.18153 = (long int) D.18152;
      D.18154 = __builtin_expect (D.18153, 0);
      if (D.18154 != 0) goto <D.18155>; else goto <D.18156>;
      <D.18155>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 504, "!old_state.data.gc_in_progress");
      <D.18156>:
      new_state.data.gc_in_progress = 1;
      workers_marking = 0;
      workers_job_queue_num_entries.22 = workers_job_queue_num_entries;
      D.18158 = workers_job_queue_num_entries.22 != 0;
      D.18159 = (long int) D.18158;
      D.18160 = __builtin_expect (D.18159, 0);
      if (D.18160 != 0) goto <D.18161>; else goto <D.18162>;
      <D.18161>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 509, "workers_job_queue_num_entries == 0");
      <D.18162>:
      workers_num_jobs_enqueued = 0;
      workers_num_jobs_finished = 0;
      workers_started.23 = workers_started;
      if (workers_started.23 != 0) goto <D.18164>; else goto <D.18165>;
      <D.18164>:
      D.18150 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18166 = D.18150 & 8388608;
      D.18167 = D.18166 == 0;
      D.18168 = (long int) D.18167;
      D.18169 = __builtin_expect (D.18168, 0);
      if (D.18169 != 0) goto <D.18170>; else goto <D.18171>;
      <D.18170>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 514, "old_state.data.done_posted");
      <D.18171>:
      D.18172 = old_state.data.num_waiting;
      D.18173 = (int) D.18172;
      workers_num.24 = workers_num;
      if (D.18173 != workers_num.24) goto <D.18175>; else goto <D.18176>;
      <D.18175>:
      workers_num.24 = workers_num;
      D.18172 = old_state.data.num_waiting;
      D.18173 = (int) D.18172;
      monoeg_g_log (0B, 4, "Expecting all %d sgen workers to be parked, but only %d are", workers_num.24, D.18173);
      <D.17909>:
      goto <D.17909>;
      <D.18176>:
      new_state.data.done_posted = 0;
      D.18177 = set_state (old_state, new_state);
      if (D.18177 == 0) goto <D.18178>; else goto <D.18179>;
      <D.18178>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 523);
      <D.18179>:
      workers_wake_up_all ();
      return;
      <D.18165>:
      D.18150 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18166 = D.18150 & 8388608;
      D.18180 = D.18166 != 0;
      D.18181 = (long int) D.18180;
      D.18182 = __builtin_expect (D.18181, 0);
      if (D.18182 != 0) goto <D.18183>; else goto <D.18184>;
      <D.18183>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 529, "!old_state.data.done_posted");
      <D.18184>:
      D.18185 = set_state (old_state, new_state);
      if (D.18185 == 0) goto <D.18186>; else goto <D.18187>;
      <D.18186>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 532);
      <D.18187>:
      i = 0;
      goto <D.17911>;
      <D.17910>:
      workers_start_worker (i);
      i = i + 1;
      <D.17911>:
      workers_num.24 = workers_num;
      if (i < workers_num.24) goto <D.17910>; else goto <D.17912>;
      <D.17912>:
      workers_started = 1;
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


workers_start_worker (int index)
{
  int iftmp.25;
  int workers_num.26;
  _Bool D.18197;
  long int D.18198;
  long int D.18199;
  struct WorkerData * workers_data.27;
  long unsigned int D.18203;
  long unsigned int D.18204;
  struct WorkerData * D.18205;
  long unsigned int D.18206;
  _Bool D.18207;
  long int D.18208;
  long int D.18209;
  MonoNativeThreadId * D.18212;

  if (index < 0) goto <D.18192>; else goto <D.18195>;
  <D.18195>:
  workers_num.26 = workers_num;
  if (index >= workers_num.26) goto <D.18192>; else goto <D.18193>;
  <D.18192>:
  iftmp.25 = 1;
  goto <D.18194>;
  <D.18193>:
  iftmp.25 = 0;
  <D.18194>:
  D.18197 = iftmp.25 != 0;
  D.18198 = (long int) D.18197;
  D.18199 = __builtin_expect (D.18198, 0);
  if (D.18199 != 0) goto <D.18200>; else goto <D.18201>;
  <D.18200>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 485, "index >= 0 && index < workers_num");
  <D.18201>:
  workers_data.27 = workers_data;
  D.18203 = (long unsigned int) index;
  D.18204 = D.18203 * 4192;
  D.18205 = workers_data.27 + D.18204;
  D.18206 = D.18205->thread;
  D.18207 = D.18206 != 0;
  D.18208 = (long int) D.18207;
  D.18209 = __builtin_expect (D.18208, 0);
  if (D.18209 != 0) goto <D.18210>; else goto <D.18211>;
  <D.18210>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 487, "!workers_data [index].thread");
  <D.18211>:
  workers_data.27 = workers_data;
  D.18203 = (long unsigned int) index;
  D.18204 = D.18203 * 4192;
  D.18205 = workers_data.27 + D.18204;
  D.18212 = &D.18205->thread;
  workers_data.27 = workers_data;
  D.18203 = (long unsigned int) index;
  D.18204 = D.18203 * 4192;
  D.18205 = workers_data.27 + D.18204;
  mono_native_thread_create (D.18212, workers_thread_func, D.18205);
}


workers_thread_func (void * data_untyped)
{
  void (*<Tc6>) (void *) D.18213;
  void * D.18216;
  int D.18217;
  int workers_marking.28;
  struct SgenGrayQueue * D.18223;
  int D.18224;
  int D.18226;
  struct SgenObjectOperations * iftmp.29;
  int D.18228;
  void (*<T2d43>) (char *, struct SgenGrayQueue *) D.18232;
  int D.18233;
  _Bool D.18234;
  long int D.18235;
  long int D.18236;
  int D.18239;
  int D.18240;
  _Bool D.18241;
  long int D.18242;
  long int D.18243;
  void * D.18248;
  struct WorkerData * data;
  struct SgenMajorCollector * major;

  data = data_untyped;
  major = sgen_get_major_collector ();
  mono_thread_info_register_small_id ();
  D.18213 = major->init_worker_thread;
  if (D.18213 != 0B) goto <D.18214>; else goto <D.18215>;
  <D.18214>:
  D.18213 = major->init_worker_thread;
  D.18216 = data->major_collector_data;
  D.18213 (D.18216);
  <D.18215>:
  init_private_gray_queue (data);
  <D.17886>:
  {
    gboolean did_work;

    did_work = 0;
    goto <D.17879>;
    <D.17878>:
    did_work = 1;
    <D.17879>:
    D.18217 = workers_dequeue_and_do_job (data);
    if (D.18217 != 0) goto <D.17878>; else goto <D.17880>;
    <D.17880>:
    workers_marking.28 = workers_marking;
    if (workers_marking.28 != 0) goto <D.18221>; else goto <D.18222>;
    <D.18221>:
    D.18223 = &data->private_gray_queue;
    D.18224 = sgen_gray_object_queue_is_empty (D.18223);
    if (D.18224 == 0) goto <D.18218>; else goto <D.18225>;
    <D.18225>:
    D.18226 = workers_get_work (data);
    if (D.18226 != 0) goto <D.18218>; else goto <D.18219>;
    <D.18218>:
    {
      struct SgenObjectOperations * ops;
      struct ScanCopyContext ctx;

      try
        {
          D.18228 = sgen_concurrent_collection_in_progress ();
          if (D.18228 != 0) goto <D.18229>; else goto <D.18230>;
          <D.18229>:
          iftmp.29 = &major->major_concurrent_ops;
          goto <D.18231>;
          <D.18230>:
          iftmp.29 = &major->major_ops;
          <D.18231>:
          ops = iftmp.29;
          D.18232 = ops->scan_object;
          ctx.scan_func = D.18232;
          ctx.copy_func = 0B;
          D.18223 = &data->private_gray_queue;
          ctx.queue = D.18223;
          D.18223 = &data->private_gray_queue;
          D.18233 = sgen_gray_object_queue_is_empty (D.18223);
          D.18234 = D.18233 != 0;
          D.18235 = (long int) D.18234;
          D.18236 = __builtin_expect (D.18235, 0);
          if (D.18236 != 0) goto <D.18237>; else goto <D.18238>;
          <D.18237>:
          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.18238>:
          goto <D.17884>;
          <D.17883>:
          D.18223 = &data->private_gray_queue;
          workers_gray_queue_share_redirect (D.18223);
          <D.17884>:
          D.18239 = sgen_drain_gray_stack (32, ctx);
          if (D.18239 == 0) goto <D.17883>; else goto <D.17885>;
          <D.17885>:
          D.18223 = &data->private_gray_queue;
          D.18240 = sgen_gray_object_queue_is_empty (D.18223);
          D.18241 = D.18240 == 0;
          D.18242 = (long int) D.18241;
          D.18243 = __builtin_expect (D.18242, 0);
          if (D.18243 != 0) goto <D.18244>; else goto <D.18245>;
          <D.18244>:
          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.18245>:
          init_private_gray_queue (data);
          did_work = 1;
        }
      finally
        {
          ctx = {CLOBBER};
        }
    }
    <D.18219>:
    <D.18222>:
    if (did_work == 0) goto <D.18246>; else goto <D.18247>;
    <D.18246>:
    workers_wait ();
    <D.18247>:
  }
  goto <D.17886>;
  D.18248 = 0B;
  return D.18248;
}


workers_dequeue_and_do_job (struct WorkerData * data)
{
  int workers_job_queue_num_entries.30;
  gboolean D.18253;
  volatile struct JobQueueEntry * D.18256;
  int workers_job_queue_num_entries.31;
  int D.18258;
  int D.18261;
  _Bool D.18262;
  long int D.18263;
  long int D.18264;
  void (*<T301a>) (struct WorkerData *, void *) D.18267;
  void * D.18268;
  int D.18269;
  int D.18270;
  struct JobQueueEntry * entry;

  workers_job_queue_num_entries.30 = workers_job_queue_num_entries;
  if (workers_job_queue_num_entries.30 == 0) goto <D.18251>; else goto <D.18252>;
  <D.18251>:
  D.18253 = 0;
  return D.18253;
  <D.18252>:
  pthread_mutex_lock (&workers_job_queue_mutex);
  entry = workers_job_queue;
  if (entry != 0B) goto <D.18254>; else goto <D.18255>;
  <D.18254>:
  D.18256 = entry->next;
  workers_job_queue = D.18256;
  workers_job_queue_num_entries.31 = workers_job_queue_num_entries;
  D.18258 = workers_job_queue_num_entries.31 + -1;
  workers_job_queue_num_entries = D.18258;
  <D.18255>:
  pthread_mutex_unlock (&workers_job_queue_mutex);
  if (entry == 0B) goto <D.18259>; else goto <D.18260>;
  <D.18259>:
  D.18253 = 0;
  return D.18253;
  <D.18260>:
  D.18261 = collection_needs_workers ();
  D.18262 = D.18261 == 0;
  D.18263 = (long int) D.18262;
  D.18264 = __builtin_expect (D.18263, 0);
  if (D.18264 != 0) goto <D.18265>; else goto <D.18266>;
  <D.18265>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 214, "collection_needs_workers ()");
  <D.18266>:
  D.18267 = entry->func;
  D.18268 = entry->data;
  D.18267 (data, D.18268);
  sgen_free_internal (entry, 26);
  {
    int __old_x;

    <D.17832>:
    __old_x = workers_num_jobs_finished;
    D.18269 = __old_x + 1;
    D.18270 = InterlockedCompareExchange (&workers_num_jobs_finished, D.18269, __old_x);
    if (D.18270 != __old_x) goto <D.17832>; else goto <D.17833>;
    <D.17833>:
  }
  D.18253 = 1;
  return D.18253;
}


workers_get_work (struct WorkerData * data)
{
  struct SgenGrayQueue * D.18272;
  int D.18273;
  _Bool D.18274;
  long int D.18275;
  long int D.18276;
  int D.18279;
  gboolean D.18282;
  struct WorkerData * workers_data.32;
  long unsigned int D.18284;
  long unsigned int D.18285;
  int D.18288;
  int workers_num.33;
  signed long D.18292;
  long unsigned int D.18293;
  long unsigned int D.18294;
  int D.18299;
  _Bool D.18300;
  long int D.18301;
  long int D.18302;
  struct SgenMajorCollector * major;
  int i;

  D.18272 = &data->private_gray_queue;
  D.18273 = sgen_gray_object_queue_is_empty (D.18272);
  D.18274 = D.18273 == 0;
  D.18275 = (long int) D.18274;
  D.18276 = __builtin_expect (D.18275, 0);
  if (D.18276 != 0) goto <D.18277>; else goto <D.18278>;
  <D.18277>:
  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.18278>:
  D.18279 = workers_steal (data, data, 1);
  if (D.18279 != 0) goto <D.18280>; else goto <D.18281>;
  <D.18280>:
  D.18282 = 1;
  return D.18282;
  <D.18281>:
  i = 0;
  goto <D.17854>;
  <D.17853>:
  {
    struct WorkerData * victim_data;

    workers_data.32 = workers_data;
    D.18284 = (long unsigned int) i;
    D.18285 = D.18284 * 4192;
    victim_data = workers_data.32 + D.18285;
    if (data == victim_data) goto <D.18286>; else goto <D.18287>;
    <D.18286>:
    // predicted unlikely by continue predictor.
    goto <D.17852>;
    <D.18287>:
    D.18288 = workers_steal (data, victim_data, 1);
    if (D.18288 != 0) goto <D.18289>; else goto <D.18290>;
    <D.18289>:
    D.18282 = 1;
    return D.18282;
    <D.18290>:
  }
  <D.17852>:
  i = i + 1;
  <D.17854>:
  workers_num.33 = workers_num;
  if (i < workers_num.33) goto <D.17853>; else goto <D.17855>;
  <D.17855>:
  major = sgen_get_major_collector ();
  D.18292 = BIT_FIELD_REF <*major, 64, 64>;
  D.18293 = (long unsigned int) D.18292;
  D.18294 = D.18293;
  if (D.18294 != 0) goto <D.18295>; else goto <D.18296>;
  <D.18295>:
  {
    struct GrayQueueSection * section;

    section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
    if (section != 0B) goto <D.18297>; else goto <D.18298>;
    <D.18297>:
    D.18272 = &data->private_gray_queue;
    sgen_gray_object_enqueue_section (D.18272, section);
    D.18282 = 1;
    return D.18282;
    <D.18298>:
  }
  <D.18296>:
  D.18272 = &data->private_gray_queue;
  D.18299 = sgen_gray_object_queue_is_empty (D.18272);
  D.18300 = D.18299 == 0;
  D.18301 = (long int) D.18300;
  D.18302 = __builtin_expect (D.18301, 0);
  if (D.18302 != 0) goto <D.18303>; else goto <D.18304>;
  <D.18303>:
  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.18304>:
  D.18282 = 0;
  return D.18282;
}


workers_steal (struct WorkerData * data, struct WorkerData * victim_data, gboolean lock)
{
  struct GrayQueueSection * D.18306;
  _Bool D.18307;
  long int D.18308;
  long int D.18309;
  int D.18312;
  gboolean D.18315;
  union mono_mutex_t * D.18318;
  int D.18319;
  int D.18322;
  int D.18323;
  char *[125] * D.18324;
  char *[512] * D.18325;
  int D.18326;
  sizetype D.18327;
  sizetype D.18328;
  sizetype D.18329;
  sizetype D.18330;
  sizetype D.18331;
  sizetype D.18332;
  const void * D.18333;
  long unsigned int D.18334;
  long unsigned int D.18335;
  int D.18336;
  int D.18337;
  long long int D.18344;
  long long int stat_workers_stolen_from_self_lock.34;
  long long int D.18346;
  long long int stat_workers_stolen_from_self_no_lock.35;
  long long int D.18349;
  long long int stat_workers_stolen_from_others.36;
  long long int D.18352;
  _Bool D.18353;
  struct SgenGrayQueue * queue;
  int num;
  int n;

  queue = &data->private_gray_queue;
  D.18306 = queue->first;
  D.18307 = D.18306 != 0B;
  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", 230, "!queue->first");
  <D.18311>:
  D.18312 = victim_data->stealable_stack_fill;
  if (D.18312 == 0) goto <D.18313>; else goto <D.18314>;
  <D.18313>:
  D.18315 = 0;
  return D.18315;
  <D.18314>:
  if (lock != 0) goto <D.18316>; else goto <D.18317>;
  <D.18316>:
  D.18318 = &victim_data->stealable_stack_mutex;
  D.18319 = pthread_mutex_trylock (D.18318);
  if (D.18319 != 0) goto <D.18320>; else goto <D.18321>;
  <D.18320>:
  D.18315 = 0;
  return D.18315;
  <D.18321>:
  <D.18317>:
  D.18322 = victim_data->stealable_stack_fill;
  D.18323 = D.18322 + 1;
  num = D.18323 / 2;
  n = num;
  goto <D.17844>;
  <D.17843>:
  {
    int m;

    m = MIN_EXPR <n, 125>;
    n = n - m;
    sgen_gray_object_alloc_queue_section (queue);
    D.18306 = queue->first;
    D.18324 = &D.18306->objects;
    D.18325 = &victim_data->stealable_stack;
    D.18326 = victim_data->stealable_stack_fill;
    D.18327 = (sizetype) D.18326;
    D.18328 = (sizetype) num;
    D.18329 = D.18327 - D.18328;
    D.18330 = (sizetype) n;
    D.18331 = D.18329 + D.18330;
    D.18332 = D.18331 * 8;
    D.18333 = D.18325 + D.18332;
    D.18334 = (long unsigned int) m;
    D.18335 = D.18334 * 8;
    memcpy (D.18324, D.18333, D.18335);
    D.18306 = queue->first;
    D.18306->end = m;
  }
  <D.17844>:
  if (n > 0) goto <D.17843>; else goto <D.17845>;
  <D.17845>:
  D.18336 = victim_data->stealable_stack_fill;
  D.18337 = D.18336 - num;
  victim_data->stealable_stack_fill = D.18337;
  if (lock != 0) goto <D.18338>; else goto <D.18339>;
  <D.18338>:
  D.18318 = &victim_data->stealable_stack_mutex;
  pthread_mutex_unlock (D.18318);
  <D.18339>:
  if (data == victim_data) goto <D.18340>; else goto <D.18341>;
  <D.18340>:
  if (lock != 0) goto <D.18342>; else goto <D.18343>;
  <D.18342>:
  D.18344 = (long long int) num;
  stat_workers_stolen_from_self_lock.34 = stat_workers_stolen_from_self_lock;
  D.18346 = D.18344 + stat_workers_stolen_from_self_lock.34;
  stat_workers_stolen_from_self_lock = D.18346;
  goto <D.18347>;
  <D.18343>:
  D.18344 = (long long int) num;
  stat_workers_stolen_from_self_no_lock.35 = stat_workers_stolen_from_self_no_lock;
  D.18349 = D.18344 + stat_workers_stolen_from_self_no_lock.35;
  stat_workers_stolen_from_self_no_lock = D.18349;
  <D.18347>:
  goto <D.18350>;
  <D.18341>:
  D.18344 = (long long int) num;
  stat_workers_stolen_from_others.36 = stat_workers_stolen_from_others;
  D.18352 = D.18344 + stat_workers_stolen_from_others.36;
  stat_workers_stolen_from_others = D.18352;
  <D.18350>:
  D.18353 = num != 0;
  D.18315 = (gboolean) D.18353;
  return D.18315;
}


__attribute__((__artificial__, __gnu_inline__, __always_inline__, __nothrow__, __leaf__))
memcpy (void * restrict __dest, const void * restrict __src, size_t __len)
{
  void * D.18355;
  long unsigned int D.18356;

  D.18356 = __builtin_object_size (__dest, 0);
  D.18355 = __builtin___memcpy_chk (__dest, __src, __len, D.18356);
  return D.18355;
}


workers_gray_queue_share_redirect (struct SgenGrayQueue * queue)
{
  int D.18358;
  <unnamed-unsigned:1> D.18361;
  union mono_mutex_t * D.18364;
  int iftmp.37;
  int D.18366;
  int D.18367;
  int D.18368;
  int D.18372;
  char *[512] * D.18373;
  int D.18374;
  long unsigned int D.18375;
  long unsigned int D.18376;
  void * D.18377;
  char *[125] * D.18378;
  sizetype D.18379;
  sizetype D.18380;
  sizetype D.18381;
  sizetype D.18382;
  const void * D.18383;
  long unsigned int D.18384;
  long unsigned int D.18385;
  int D.18386;
  int D.18387;
  int D.18388;
  int D.18392;
  int D.18394;
  <unnamed-unsigned:1> D.18397;
  struct GrayQueueSection * section;
  struct WorkerData * data;

  data = queue->alloc_prepare_data;
  D.18358 = data->stealable_stack_fill;
  if (D.18358 != 0) goto <D.18359>; else goto <D.18360>;
  <D.18359>:
  D.18361 = workers_state.data.gc_in_progress;
  if (D.18361 != 0) goto <D.18362>; else goto <D.18363>;
  <D.18362>:
  workers_wake_up_all ();
  <D.18363>:
  return;
  <D.18360>:
  D.18364 = &data->stealable_stack_mutex;
  pthread_mutex_lock (D.18364);
  goto <D.17864>;
  <D.17863>:
  {
    int num;

    D.18366 = section->end;
    D.18367 = data->stealable_stack_fill;
    D.18368 = 512 - D.18367;
    if (D.18366 < D.18368) goto <D.18369>; else goto <D.18370>;
    <D.18369>:
    iftmp.37 = section->end;
    goto <D.18371>;
    <D.18370>:
    D.18372 = data->stealable_stack_fill;
    iftmp.37 = 512 - D.18372;
    <D.18371>:
    num = iftmp.37;
    D.18373 = &data->stealable_stack;
    D.18374 = data->stealable_stack_fill;
    D.18375 = (long unsigned int) D.18374;
    D.18376 = D.18375 * 8;
    D.18377 = D.18373 + D.18376;
    D.18378 = &section->objects;
    D.18366 = section->end;
    D.18379 = (sizetype) D.18366;
    D.18380 = (sizetype) num;
    D.18381 = D.18379 - D.18380;
    D.18382 = D.18381 * 8;
    D.18383 = D.18378 + D.18382;
    D.18384 = (long unsigned int) num;
    D.18385 = D.18384 * 8;
    memcpy (D.18377, D.18383, D.18385);
    D.18366 = section->end;
    D.18386 = D.18366 - num;
    section->end = D.18386;
    D.18387 = data->stealable_stack_fill;
    D.18388 = D.18387 + num;
    data->stealable_stack_fill = D.18388;
    D.18366 = section->end;
    if (D.18366 != 0) goto <D.18389>; else goto <D.18390>;
    <D.18389>:
    sgen_gray_object_enqueue_section (queue, section);
    goto <D.18391>;
    <D.18390>:
    sgen_gray_object_free_queue_section (section);
    <D.18391>:
  }
  <D.17864>:
  D.18392 = data->stealable_stack_fill;
  if (D.18392 <= 511) goto <D.18393>; else goto <D.17865>;
  <D.18393>:
  section = sgen_gray_object_dequeue_section (queue);
  if (section != 0B) goto <D.17863>; else goto <D.17865>;
  <D.17865>:
  D.18394 = sgen_gray_object_queue_is_empty (queue);
  if (D.18394 != 0) goto <D.18395>; else goto <D.18396>;
  <D.18395>:
  workers_steal (data, data, 0);
  <D.18396>:
  D.18364 = &data->stealable_stack_mutex;
  pthread_mutex_unlock (D.18364);
  D.18397 = workers_state.data.gc_in_progress;
  if (D.18397 != 0) goto <D.18398>; else goto <D.18399>;
  <D.18398>:
  workers_wake_up_all ();
  <D.18399>:
}


sgen_gray_object_queue_is_empty (struct SgenGrayQueue * queue)
{
  gboolean D.18401;
  struct GrayQueueSection * D.18402;
  _Bool D.18403;

  D.18402 = queue->first;
  D.18403 = D.18402 == 0B;
  D.18401 = (gboolean) D.18403;
  return D.18401;
}


init_private_gray_queue (struct WorkerData * data)
{
  struct SgenGrayQueue * D.18405;
  void (*<T2c84>) (char *) iftmp.38;
  struct SgenMajorCollector * D.18407;
  int D.18408;

  D.18405 = &data->private_gray_queue;
  D.18407 = sgen_get_major_collector ();
  D.18408 = D.18407->is_concurrent;
  if (D.18408 != 0) goto <D.18409>; else goto <D.18410>;
  <D.18409>:
  iftmp.38 = concurrent_enqueue_check;
  goto <D.18411>;
  <D.18410>:
  iftmp.38 = 0B;
  <D.18411>:
  sgen_gray_object_queue_init_with_alloc_prepare (D.18405, iftmp.38, workers_gray_queue_share_redirect, data);
}


workers_wait ()
{
  long long int stat_workers_num_waited.39;
  long long int D.18413;
  unsigned int D.18414;
  unsigned int D.18415;
  _Bool D.18416;
  long int D.18417;
  long int D.18418;
  unsigned char D.18421;
  unsigned char D.18422;
  int D.18423;
  int workers_num.40;
  unsigned int D.18427;
  int D.18430;
  unsigned int D.18431;
  unsigned int D.18432;
  union State old_state;
  union State new_state;

  try
    {
      stat_workers_num_waited.39 = stat_workers_num_waited;
      D.18413 = stat_workers_num_waited.39 + 1;
      stat_workers_num_waited = D.18413;
      <D.17809>:
      new_state = workers_state;
      old_state = new_state;
      D.18414 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18415 = D.18414 & 8388608;
      D.18416 = D.18415 != 0;
      D.18417 = (long int) D.18416;
      D.18418 = __builtin_expect (D.18417, 0);
      if (D.18418 != 0) goto <D.18419>; else goto <D.18420>;
      <D.18419>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 125, "!old_state.data.done_posted");
      <D.18420>:
      D.18421 = new_state.data.num_waiting;
      D.18422 = D.18421 + 1;
      new_state.data.num_waiting = D.18422;
      D.18421 = new_state.data.num_waiting;
      D.18423 = (int) D.18421;
      workers_num.40 = workers_num;
      if (D.18423 == workers_num.40) goto <D.18425>; else goto <D.18426>;
      <D.18425>:
      D.18414 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18427 = D.18414 & 4194304;
      if (D.18427 == 0) goto <D.18428>; else goto <D.18429>;
      <D.18428>:
      new_state.data.done_posted = 1;
      <D.18429>:
      <D.18426>:
      D.18430 = set_state (old_state, new_state);
      if (D.18430 == 0) goto <D.17809>; else goto <D.17810>;
      <D.17810>:
      mono_memory_barrier ();
      D.18431 = BIT_FIELD_REF <MEM[(void *)&new_state], 32, 0>;
      D.18432 = D.18431 & 8388608;
      if (D.18432 != 0) goto <D.18433>; else goto <D.18434>;
      <D.18433>:
      mono_sem_post (&workers_done_sem);
      <D.18434>:
      mono_sem_wait (&workers_waiting_sem, 0);
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


__attribute__((visibility ("hidden")))
sgen_workers_have_started ()
{
  gboolean D.18435;
  <unnamed-unsigned:1> D.18436;

  D.18436 = workers_state.data.gc_in_progress;
  D.18435 = (gboolean) D.18436;
  return D.18435;
}


__attribute__((visibility ("hidden")))
sgen_workers_start_marking ()
{
  int D.18438;
  int iftmp.41;
  int workers_started.42;
  <unnamed-unsigned:1> D.18447;
  _Bool D.18448;
  long int D.18449;
  long int D.18450;
  int workers_marking.43;
  _Bool D.18454;
  long int D.18455;
  long int D.18456;

  D.18438 = collection_needs_workers ();
  if (D.18438 == 0) goto <D.18439>; else goto <D.18440>;
  <D.18439>:
  return;
  <D.18440>:
  workers_started.42 = workers_started;
  if (workers_started.42 == 0) goto <D.18442>; else goto <D.18446>;
  <D.18446>:
  D.18447 = workers_state.data.gc_in_progress;
  if (D.18447 == 0) goto <D.18442>; else goto <D.18443>;
  <D.18442>:
  iftmp.41 = 1;
  goto <D.18444>;
  <D.18443>:
  iftmp.41 = 0;
  <D.18444>:
  D.18448 = iftmp.41 != 0;
  D.18449 = (long int) D.18448;
  D.18450 = __builtin_expect (D.18449, 0);
  if (D.18450 != 0) goto <D.18451>; else goto <D.18452>;
  <D.18451>:
  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.18452>:
  workers_marking.43 = workers_marking;
  D.18454 = workers_marking.43 != 0;
  D.18455 = (long int) D.18454;
  D.18456 = __builtin_expect (D.18455, 0);
  if (D.18456 != 0) goto <D.18457>; else goto <D.18458>;
  <D.18457>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 553, "!workers_marking");
  <D.18458>:
  workers_marking = 1;
  workers_wake_up_all ();
}


__attribute__((visibility ("hidden")))
sgen_workers_join ()
{
  int D.18460;
  unsigned int D.18463;
  unsigned int D.18464;
  _Bool D.18465;
  long int D.18466;
  long int D.18467;
  unsigned int D.18470;
  _Bool D.18471;
  long int D.18472;
  long int D.18473;
  int D.18476;
  unsigned char D.18477;
  int D.18478;
  int workers_num.44;
  unsigned char D.18482;
  int D.18483;
  _Bool D.18484;
  long int D.18485;
  long int D.18486;
  _Bool D.18489;
  long int D.18490;
  long int D.18491;
  int workers_job_queue_num_entries.45;
  int D.18498;
  int D.18499;
  struct SgenMajorCollector * D.18502;
  void (*<Tc6>) (void *) D.18503;
  struct SgenMajorCollector * D.18506;
  void (*<Tc6>) (void *) D.18507;
  struct WorkerData * workers_data.46;
  long unsigned int D.18509;
  long unsigned int D.18510;
  struct WorkerData * D.18511;
  void * D.18512;
  int workers_job_queue_num_entries.47;
  _Bool D.18514;
  long int D.18515;
  long int D.18516;
  int D.18519;
  _Bool D.18520;
  long int D.18521;
  long int D.18522;
  int D.18525;
  _Bool D.18526;
  long int D.18527;
  long int D.18528;
  struct SgenGrayQueue * D.18531;
  int D.18532;
  _Bool D.18533;
  long int D.18534;
  long int D.18535;
  union State old_state;
  union State new_state;
  int i;
  void reawaken = <<< error >>>;

  try
    {
      D.18460 = collection_needs_workers ();
      if (D.18460 == 0) goto <D.18461>; else goto <D.18462>;
      <D.18461>:
      return;
      <D.18462>:
      <D.17925>:
      new_state = workers_state;
      old_state = new_state;
      D.18463 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18464 = D.18463 & 4194304;
      D.18465 = D.18464 == 0;
      D.18466 = (long int) D.18465;
      D.18467 = __builtin_expect (D.18466, 0);
      if (D.18467 != 0) goto <D.18468>; else goto <D.18469>;
      <D.18468>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 571, "old_state.data.gc_in_progress");
      <D.18469>:
      D.18463 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18470 = D.18463 & 8388608;
      D.18471 = D.18470 != 0;
      D.18472 = (long int) D.18471;
      D.18473 = __builtin_expect (D.18472, 0);
      if (D.18473 != 0) goto <D.18474>; else goto <D.18475>;
      <D.18474>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 572, "!old_state.data.done_posted");
      <D.18475>:
      new_state.data.gc_in_progress = 0;
      D.18476 = set_state (old_state, new_state);
      if (D.18476 == 0) goto <D.17925>; else goto <D.17926>;
      <D.17926>:
      D.18477 = new_state.data.num_waiting;
      D.18478 = (int) D.18477;
      workers_num.44 = workers_num;
      if (D.18478 == workers_num.44) goto <D.18480>; else goto <D.18481>;
      <D.18480>:
      reawaken:
      workers_wake_up_all ();
      <D.18481>:
      mono_sem_wait (&workers_done_sem, 0);
      new_state = workers_state;
      old_state = new_state;
      D.18482 = old_state.data.num_waiting;
      D.18483 = (int) D.18482;
      workers_num.44 = workers_num;
      D.18484 = D.18483 != workers_num.44;
      D.18485 = (long int) D.18484;
      D.18486 = __builtin_expect (D.18485, 0);
      if (D.18486 != 0) goto <D.18487>; else goto <D.18488>;
      <D.18487>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 593, "old_state.data.num_waiting == workers_num");
      <D.18488>:
      D.18463 = BIT_FIELD_REF <MEM[(void *)&old_state], 32, 0>;
      D.18470 = D.18463 & 8388608;
      D.18489 = D.18470 == 0;
      D.18490 = (long int) D.18489;
      D.18491 = __builtin_expect (D.18490, 0);
      if (D.18491 != 0) goto <D.18492>; else goto <D.18493>;
      <D.18492>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 594, "old_state.data.done_posted");
      <D.18493>:
      workers_job_queue_num_entries.45 = workers_job_queue_num_entries;
      if (workers_job_queue_num_entries.45 != 0) goto <D.18494>; else goto <D.18497>;
      <D.18497>:
      D.18498 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      if (D.18498 == 0) goto <D.18494>; else goto <D.18495>;
      <D.18494>:
      new_state.data.done_posted = 0;
      D.18499 = set_state (old_state, new_state);
      if (D.18499 == 0) goto <D.18500>; else goto <D.18501>;
      <D.18500>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 613);
      <D.18501>:
      goto reawaken;
      <D.18495>:
      workers_marking = 0;
      D.18502 = sgen_get_major_collector ();
      D.18503 = D.18502->reset_worker_data;
      if (D.18503 != 0B) goto <D.18504>; else goto <D.18505>;
      <D.18504>:
      i = 0;
      goto <D.17929>;
      <D.17928>:
      D.18506 = sgen_get_major_collector ();
      D.18507 = D.18506->reset_worker_data;
      workers_data.46 = workers_data;
      D.18509 = (long unsigned int) i;
      D.18510 = D.18509 * 4192;
      D.18511 = workers_data.46 + D.18510;
      D.18512 = D.18511->major_collector_data;
      D.18507 (D.18512);
      i = i + 1;
      <D.17929>:
      workers_num.44 = workers_num;
      if (i < workers_num.44) goto <D.17928>; else goto <D.17930>;
      <D.17930>:
      <D.18505>:
      workers_job_queue_num_entries.47 = workers_job_queue_num_entries;
      D.18514 = workers_job_queue_num_entries.47 != 0;
      D.18515 = (long int) D.18514;
      D.18516 = __builtin_expect (D.18515, 0);
      if (D.18516 != 0) goto <D.18517>; else goto <D.18518>;
      <D.18517>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 626, "workers_job_queue_num_entries == 0");
      <D.18518>:
      D.18519 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      D.18520 = D.18519 == 0;
      D.18521 = (long int) D.18520;
      D.18522 = __builtin_expect (D.18521, 0);
      if (D.18522 != 0) goto <D.18523>; else goto <D.18524>;
      <D.18523>:
      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.18524>:
      i = 0;
      goto <D.17932>;
      <D.17931>:
      workers_data.46 = workers_data;
      D.18509 = (long unsigned int) i;
      D.18510 = D.18509 * 4192;
      D.18511 = workers_data.46 + D.18510;
      D.18525 = D.18511->stealable_stack_fill;
      D.18526 = D.18525 != 0;
      D.18527 = (long int) D.18526;
      D.18528 = __builtin_expect (D.18527, 0);
      if (D.18528 != 0) goto <D.18529>; else goto <D.18530>;
      <D.18529>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 629, "!workers_data [i].stealable_stack_fill");
      <D.18530>:
      workers_data.46 = workers_data;
      D.18509 = (long unsigned int) i;
      D.18510 = D.18509 * 4192;
      D.18511 = workers_data.46 + D.18510;
      D.18531 = &D.18511->private_gray_queue;
      D.18532 = sgen_gray_object_queue_is_empty (D.18531);
      D.18533 = D.18532 == 0;
      D.18534 = (long int) D.18533;
      D.18535 = __builtin_expect (D.18534, 0);
      if (D.18535 != 0) goto <D.18536>; else goto <D.18537>;
      <D.18536>:
      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.18537>:
      i = i + 1;
      <D.17932>:
      workers_num.44 = workers_num;
      if (i < workers_num.44) goto <D.17931>; else goto <D.17933>;
      <D.17933>:
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


__attribute__((visibility ("hidden")))
sgen_workers_all_done ()
{
  unsigned int D.18541;
  unsigned int D.18542;
  _Bool D.18543;
  long int D.18544;
  long int D.18545;
  unsigned int D.18548;
  _Bool D.18549;
  long int D.18550;
  long int D.18551;
  gboolean D.18554;
  unsigned char D.18555;
  int D.18556;
  int workers_num.48;
  _Bool D.18558;
  union State state;

  try
    {
      state = workers_state;
      D.18541 = BIT_FIELD_REF <MEM[(void *)&state], 32, 0>;
      D.18542 = D.18541 & 4194304;
      D.18543 = D.18542 == 0;
      D.18544 = (long int) D.18543;
      D.18545 = __builtin_expect (D.18544, 0);
      if (D.18545 != 0) goto <D.18546>; else goto <D.18547>;
      <D.18546>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 642, "state.data.gc_in_progress");
      <D.18547>:
      D.18541 = BIT_FIELD_REF <MEM[(void *)&state], 32, 0>;
      D.18548 = D.18541 & 8388608;
      D.18549 = D.18548 != 0;
      D.18550 = (long int) D.18549;
      D.18551 = __builtin_expect (D.18550, 0);
      if (D.18551 != 0) goto <D.18552>; else goto <D.18553>;
      <D.18552>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 643, "!state.data.done_posted");
      <D.18553>:
      D.18555 = state.data.num_waiting;
      D.18556 = (int) D.18555;
      workers_num.48 = workers_num;
      D.18558 = D.18556 == workers_num.48;
      D.18554 = (gboolean) D.18558;
      return D.18554;
    }
  finally
    {
      state = {CLOBBER};
    }
}


__attribute__((visibility ("hidden")))
sgen_is_worker_thread (MonoNativeThreadId thread)
{
  struct SgenMajorCollector * D.18561;
  gboolean (*<T2e64>) (MonoNativeThreadId) D.18562;
  struct SgenMajorCollector * D.18565;
  gboolean (*<T2e64>) (MonoNativeThreadId) D.18566;
  int D.18567;
  gboolean D.18570;
  struct WorkerData * workers_data.49;
  long unsigned int D.18572;
  long unsigned int D.18573;
  struct WorkerData * D.18574;
  long unsigned int D.18575;
  int workers_num.50;
  int i;

  D.18561 = sgen_get_major_collector ();
  D.18562 = D.18561->is_worker_thread;
  if (D.18562 != 0B) goto <D.18563>; else goto <D.18564>;
  <D.18563>:
  D.18565 = sgen_get_major_collector ();
  D.18566 = D.18565->is_worker_thread;
  D.18567 = D.18566 (thread);
  if (D.18567 != 0) goto <D.18568>; else goto <D.18569>;
  <D.18568>:
  D.18570 = 1;
  return D.18570;
  <D.18569>:
  <D.18564>:
  i = 0;
  goto <D.17943>;
  <D.17942>:
  workers_data.49 = workers_data;
  D.18572 = (long unsigned int) i;
  D.18573 = D.18572 * 4192;
  D.18574 = workers_data.49 + D.18573;
  D.18575 = D.18574->thread;
  if (D.18575 == thread) goto <D.18576>; else goto <D.18577>;
  <D.18576>:
  D.18570 = 1;
  return D.18570;
  <D.18577>:
  i = i + 1;
  <D.17943>:
  workers_num.50 = workers_num;
  if (i < workers_num.50) goto <D.17942>; else goto <D.17944>;
  <D.17944>:
  D.18570 = 0;
  return D.18570;
}


__attribute__((visibility ("hidden")))
sgen_workers_get_distribute_section_gray_queue ()
{
  struct SgenSectionGrayQueue * D.18580;

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


__attribute__((visibility ("hidden")))
sgen_workers_reset_data ()
{
  struct SgenMajorCollector * D.18582;
  void (*<Tc6>) (void *) D.18583;
  struct SgenMajorCollector * D.18586;
  void (*<Tc6>) (void *) D.18587;
  void * workers_gc_thread_major_collector_data.51;

  D.18582 = sgen_get_major_collector ();
  D.18583 = D.18582->reset_worker_data;
  if (D.18583 != 0B) goto <D.18584>; else goto <D.18585>;
  <D.18584>:
  D.18586 = sgen_get_major_collector ();
  D.18587 = D.18586->reset_worker_data;
  workers_gc_thread_major_collector_data.51 = workers_gc_thread_major_collector_data;
  D.18587 (workers_gc_thread_major_collector_data.51);
  <D.18585>:
}


