sgen_workers_wake_up_all ()
{
  <unnamed-unsigned:1> D.18338;
  _Bool D.18339;
  long int D.18340;
  long int D.18341;

  D.18338 = workers_state.data.gc_in_progress;
  D.18339 = ~D.18338;
  D.18340 = (long int) D.18339;
  D.18341 = __builtin_expect (D.18340, 0);
  if (D.18341 != 0) goto <D.18342>; else goto <D.18343>;
  <D.18342>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 109, "workers_state.data.gc_in_progress");
  <D.18343>:
  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.18345;
  unsigned int D.18346;
  unsigned char D.18349;
  unsigned char D.18352;
  unsigned char D.18353;
  int D.18354;
  int i;

  i = 0;
  goto <D.18182>;
  <D.18181>:
  {
    union State old_state;
    union State new_state;

    try
      {
        <D.18179>:
        new_state = workers_state;
        old_state = new_state;
        D.18345 = BIT_FIELD_REF <old_state, 32, 0>;
        D.18346 = D.18345 & 256;
        if (D.18346 != 0) goto <D.18347>; else goto <D.18348>;
        <D.18347>:
        return;
        <D.18348>:
        D.18349 = old_state.data.num_waiting;
        if (D.18349 == 0) goto <D.18350>; else goto <D.18351>;
        <D.18350>:
        return;
        <D.18351>:
        D.18352 = new_state.data.num_waiting;
        D.18353 = D.18352 + 255;
        new_state.data.num_waiting = D.18353;
        D.18354 = set_state (old_state, new_state);
        if (D.18354 == 0) goto <D.18179>; else goto <D.18180>;
        <D.18180>:
        mono_sem_post (&workers_waiting_sem);
      }
    finally
      {
        old_state = {CLOBBER};
        new_state = {CLOBBER};
      }
  }
  i = i + 1;
  <D.18182>:
  if (i < max) goto <D.18181>; else goto <D.18183>;
  <D.18183>:
}


set_state (union State old_state, union State new_state)
{
  gboolean D.18358;
  int D.18359;
  int D.18360;
  int D.18361;
  _Bool D.18362;

  D.18359 = new_state.value;
  D.18360 = old_state.value;
  D.18361 = InterlockedCompareExchange (&workers_state.value, D.18359, D.18360);
  D.18360 = old_state.value;
  D.18362 = D.18361 == D.18360;
  D.18358 = (gboolean) D.18362;
  return D.18358;
}


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

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


sgen_workers_enqueue_job (void (*JobFunc) (struct WorkerData *, void *) func, void * data)
{
  int D.18369;
  <unnamed-unsigned:1> D.18372;
  _Bool D.18373;
  long int D.18374;
  long int D.18375;
  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.18369 = collection_needs_workers ();
  if (D.18369 == 0) goto <D.18370>; else goto <D.18371>;
  <D.18370>:
  func (0B, data);
  return;
  <D.18371>:
  D.18372 = workers_state.data.gc_in_progress;
  D.18373 = ~D.18372;
  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", 157, "workers_state.data.gc_in_progress");
  <D.18377>:
  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.18385;
  int iftmp.9;
  int D.18390;
  int D.18392;

  D.18390 = sgen_collection_is_parallel ();
  if (D.18390 != 0) goto <D.18387>; else goto <D.18391>;
  <D.18391>:
  D.18392 = sgen_collection_is_concurrent ();
  if (D.18392 != 0) goto <D.18387>; else goto <D.18388>;
  <D.18387>:
  iftmp.9 = 1;
  goto <D.18389>;
  <D.18388>:
  iftmp.9 = 0;
  <D.18389>:
  D.18385 = iftmp.9;
  return D.18385;
}


sgen_workers_wait_for_jobs ()
{
  unsigned int D.18394;
  unsigned int D.18395;
  _Bool D.18396;
  long int D.18397;
  long int D.18398;
  unsigned int D.18401;
  _Bool D.18402;
  long int D.18403;
  long int D.18404;
  unsigned char D.18407;
  int D.18408;
  int workers_num.10;
  int workers_num_jobs_finished.11;
  int workers_num_jobs_enqueued.12;

  goto <D.18211>;
  <D.18210>:
  {
    union State state;

    try
      {
        state = workers_state;
        D.18394 = BIT_FIELD_REF <state, 32, 0>;
        D.18395 = D.18394 & 512;
        D.18396 = D.18395 == 0;
        D.18397 = (long int) D.18396;
        D.18398 = __builtin_expect (D.18397, 0);
        if (D.18398 != 0) goto <D.18399>; else goto <D.18400>;
        <D.18399>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 179, "state.data.gc_in_progress");
        <D.18400>:
        D.18394 = BIT_FIELD_REF <state, 32, 0>;
        D.18401 = D.18394 & 256;
        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", 180, "!state.data.done_posted");
        <D.18406>:
        D.18407 = state.data.num_waiting;
        D.18408 = (int) D.18407;
        workers_num.10 = workers_num;
        if (D.18408 == workers_num.10) goto <D.18410>; else goto <D.18411>;
        <D.18410>:
        workers_wake_up_all ();
        <D.18411>:
        monoeg_g_usleep (1000);
      }
    finally
      {
        state = {CLOBBER};
      }
  }
  <D.18211>:
  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.18210>; else goto <D.18212>;
  <D.18212>:
}


sgen_workers_init_distribute_gray_queue ()
{
  int D.18414;
  int iftmp.13;
  struct SgenMajorCollector * D.18421;
  int D.18422;
  struct SgenMajorCollector * D.18424;
  int D.18425;

  D.18414 = collection_needs_workers ();
  if (D.18414 == 0) goto <D.18415>; else goto <D.18416>;
  <D.18415>:
  return;
  <D.18416>:
  D.18421 = sgen_get_major_collector ();
  D.18422 = D.18421->is_concurrent;
  if (D.18422 != 0) goto <D.18418>; else goto <D.18423>;
  <D.18423>:
  D.18424 = sgen_get_major_collector ();
  D.18425 = D.18424->is_parallel;
  if (D.18425 != 0) goto <D.18418>; else goto <D.18419>;
  <D.18418>:
  iftmp.13 = 1;
  goto <D.18420>;
  <D.18419>:
  iftmp.13 = 0;
  <D.18420>:
  init_distribute_gray_queue (iftmp.13);
}


init_distribute_gray_queue (gboolean locked)
{
  int workers_distribute_gray_queue_inited.14;
  int D.18430;
  _Bool D.18431;
  long int D.18432;
  long int D.18433;
  int D.18436;
  _Bool D.18437;
  _Bool D.18438;
  _Bool D.18439;
  long int D.18440;
  long int D.18441;
  void (*<T2bc8>) (char *) iftmp.15;
  struct SgenMajorCollector * D.18445;
  int D.18446;

  workers_distribute_gray_queue_inited.14 = workers_distribute_gray_queue_inited;
  if (workers_distribute_gray_queue_inited.14 != 0) goto <D.18428>; else goto <D.18429>;
  <D.18428>:
  D.18430 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
  D.18431 = D.18430 == 0;
  D.18432 = (long int) D.18431;
  D.18433 = __builtin_expect (D.18432, 0);
  if (D.18433 != 0) goto <D.18434>; else goto <D.18435>;
  <D.18434>:
  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.18435>:
  D.18436 = workers_distribute_gray_queue.locked;
  D.18437 = D.18436 == 0;
  D.18438 = locked == 0;
  D.18439 = D.18437 ^ D.18438;
  D.18440 = (long int) D.18439;
  D.18441 = __builtin_expect (D.18440, 0);
  if (D.18441 != 0) goto <D.18442>; else goto <D.18443>;
  <D.18442>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 420, "!workers_distribute_gray_queue.locked == !locked");
  <D.18443>:
  return;
  <D.18429>:
  D.18445 = sgen_get_major_collector ();
  D.18446 = D.18445->is_concurrent;
  if (D.18446 != 0) goto <D.18447>; else goto <D.18448>;
  <D.18447>:
  iftmp.15 = concurrent_enqueue_check;
  goto <D.18449>;
  <D.18448>:
  iftmp.15 = 0B;
  <D.18449>:
  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.18451;
  _Bool D.18452;
  long int D.18453;
  long int D.18454;
  int D.18457;
  _Bool D.18458;
  long int D.18459;
  long int D.18460;
  long unsigned int D.18463;
  long unsigned int D.18464;
  _Bool D.18465;
  long int D.18466;
  long int D.18467;

  D.18451 = sgen_concurrent_collection_in_progress ();
  D.18452 = D.18451 == 0;
  D.18453 = (long int) D.18452;
  D.18454 = __builtin_expect (D.18453, 0);
  if (D.18454 != 0) goto <D.18455>; else goto <D.18456>;
  <D.18455>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 356, "sgen_concurrent_collection_in_progress ()");
  <D.18456>:
  D.18457 = sgen_ptr_in_nursery (obj);
  D.18458 = D.18457 != 0;
  D.18459 = (long int) D.18458;
  D.18460 = __builtin_expect (D.18459, 0);
  if (D.18460 != 0) goto <D.18461>; else goto <D.18462>;
  <D.18461>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 357, "!sgen_ptr_in_nursery (obj)");
  <D.18462>:
  D.18463 = MEM[(mword *)obj];
  D.18464 = D.18463 & 18446744073709551612;
  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", 358, "SGEN_LOAD_VTABLE (obj)");
  <D.18469>:
}


sgen_ptr_in_nursery (void * p)
{
  gboolean D.18470;
  int sgen_nursery_bits.16;
  int D.18472;
  int D.18473;
  long unsigned int D.18474;
  long unsigned int p.17;
  long unsigned int D.18476;
  char * sgen_nursery_start.18;
  long unsigned int sgen_nursery_start.19;
  _Bool D.18479;

  sgen_nursery_bits.16 = sgen_nursery_bits;
  D.18472 = 1 << sgen_nursery_bits.16;
  D.18473 = -D.18472;
  D.18474 = (long unsigned int) D.18473;
  p.17 = (long unsigned int) p;
  D.18476 = D.18474 & p.17;
  sgen_nursery_start.18 = sgen_nursery_start;
  sgen_nursery_start.19 = (long unsigned int) sgen_nursery_start.18;
  D.18479 = D.18476 == sgen_nursery_start.19;
  D.18470 = (gboolean) D.18479;
  return D.18470;
}


sgen_workers_init (int num_workers)
{
  struct SgenMajorCollector * D.18481;
  int D.18482;
  struct SgenMajorCollector * D.18485;
  int D.18486;
  long unsigned int D.18489;
  long unsigned int D.18490;
  void * workers_data.20;
  struct WorkerData * workers_data.21;
  int iftmp.22;
  struct SgenMajorCollector * D.18497;
  int D.18498;
  struct SgenMajorCollector * D.18500;
  int D.18501;
  struct SgenMajorCollector * D.18502;
  void * (*<T2b32>) (void) D.18503;
  struct SgenMajorCollector * D.18506;
  void * (*<T2b32>) (void) D.18507;
  void * workers_gc_thread_major_collector_data.23;
  long unsigned int D.18509;
  long unsigned int D.18510;
  struct WorkerData * D.18511;
  union mono_mutex_t * D.18512;
  struct SgenMajorCollector * D.18513;
  void * (*<T2b32>) (void) D.18514;
  struct SgenMajorCollector * D.18517;
  void * (*<T2b32>) (void) D.18518;
  void * D.18519;
  int workers_num.24;
  int i;

  D.18481 = sgen_get_major_collector ();
  D.18482 = D.18481->is_parallel;
  if (D.18482 == 0) goto <D.18483>; else goto <D.18484>;
  <D.18483>:
  D.18485 = sgen_get_major_collector ();
  D.18486 = D.18485->is_concurrent;
  if (D.18486 == 0) goto <D.18487>; else goto <D.18488>;
  <D.18487>:
  return;
  <D.18488>:
  <D.18484>:
  workers_num = num_workers;
  D.18489 = (long unsigned int) num_workers;
  D.18490 = D.18489 * 4192;
  workers_data.20 = sgen_alloc_internal_dynamic (D.18490, 19, 1);
  workers_data = workers_data.20;
  workers_data.21 = workers_data;
  D.18489 = (long unsigned int) num_workers;
  D.18490 = D.18489 * 4192;
  memset (workers_data.21, 0, D.18490);
  sem_init (&workers_waiting_sem, 0, 0);
  sem_init (&workers_done_sem, 0, 0);
  D.18497 = sgen_get_major_collector ();
  D.18498 = D.18497->is_concurrent;
  if (D.18498 != 0) goto <D.18494>; else goto <D.18499>;
  <D.18499>:
  D.18500 = sgen_get_major_collector ();
  D.18501 = D.18500->is_parallel;
  if (D.18501 != 0) goto <D.18494>; else goto <D.18495>;
  <D.18494>:
  iftmp.22 = 1;
  goto <D.18496>;
  <D.18495>:
  iftmp.22 = 0;
  <D.18496>:
  init_distribute_gray_queue (iftmp.22);
  D.18502 = sgen_get_major_collector ();
  D.18503 = D.18502->alloc_worker_data;
  if (D.18503 != 0B) goto <D.18504>; else goto <D.18505>;
  <D.18504>:
  D.18506 = sgen_get_major_collector ();
  D.18507 = D.18506->alloc_worker_data;
  workers_gc_thread_major_collector_data.23 = D.18507 ();
  workers_gc_thread_major_collector_data = workers_gc_thread_major_collector_data.23;
  <D.18505>:
  i = 0;
  goto <D.18284>;
  <D.18283>:
  workers_data.21 = workers_data;
  D.18509 = (long unsigned int) i;
  D.18510 = D.18509 * 4192;
  D.18511 = workers_data.21 + D.18510;
  D.18512 = &D.18511->stealable_stack_mutex;
  pthread_mutex_init (D.18512, 0B);
  workers_data.21 = workers_data;
  D.18509 = (long unsigned int) i;
  D.18510 = D.18509 * 4192;
  D.18511 = workers_data.21 + D.18510;
  D.18511->stealable_stack_fill = 0;
  D.18513 = sgen_get_major_collector ();
  D.18514 = D.18513->alloc_worker_data;
  if (D.18514 != 0B) goto <D.18515>; else goto <D.18516>;
  <D.18515>:
  workers_data.21 = workers_data;
  D.18509 = (long unsigned int) i;
  D.18510 = D.18509 * 4192;
  D.18511 = workers_data.21 + D.18510;
  D.18517 = sgen_get_major_collector ();
  D.18518 = D.18517->alloc_worker_data;
  D.18519 = D.18518 ();
  D.18511->major_collector_data = D.18519;
  <D.18516>:
  i = i + 1;
  <D.18284>:
  workers_num.24 = workers_num;
  if (i < workers_num.24) goto <D.18283>; else goto <D.18285>;
  <D.18285>:
  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.18524;
  int D.18529;
  void * D.18531;
  long unsigned int D.18532;

  D.18524 = __builtin_constant_p (__len);
  if (D.18524 != 0) goto <D.18525>; else goto <D.18526>;
  <D.18525>:
  if (__len == 0) goto <D.18527>; else goto <D.18528>;
  <D.18527>:
  D.18529 = __builtin_constant_p (__ch);
  if (D.18529 == 0) goto <D.18522>; else goto <D.18530>;
  <D.18530>:
  if (__ch != 0) goto <D.18522>; else goto <D.18523>;
  <D.18522>:
  __warn_memset_zero_len ();
  D.18531 = __dest;
  return D.18531;
  <D.18523>:
  <D.18528>:
  <D.18526>:
  D.18532 = __builtin_object_size (__dest, 0);
  D.18531 = __builtin___memset_chk (__dest, __ch, __len, D.18532);
  return D.18531;
}


sgen_workers_start_all_workers ()
{
  int D.18534;
  struct SgenMajorCollector * D.18537;
  void (*<Tbf>) (void *) D.18538;
  struct SgenMajorCollector * D.18541;
  void (*<Tbf>) (void *) D.18542;
  void * workers_gc_thread_major_collector_data.25;
  unsigned int D.18544;
  unsigned int D.18545;
  _Bool D.18546;
  long int D.18547;
  long int D.18548;
  int workers_job_queue_num_entries.26;
  _Bool D.18552;
  long int D.18553;
  long int D.18554;
  int workers_started.27;
  unsigned int D.18560;
  _Bool D.18561;
  long int D.18562;
  long int D.18563;
  unsigned char D.18566;
  int D.18567;
  int workers_num.28;
  int D.18571;
  _Bool D.18574;
  long int D.18575;
  long int D.18576;
  int D.18579;
  union State old_state;
  union State new_state;
  int i;

  try
    {
      D.18534 = collection_needs_workers ();
      if (D.18534 == 0) goto <D.18535>; else goto <D.18536>;
      <D.18535>:
      return;
      <D.18536>:
      D.18537 = sgen_get_major_collector ();
      D.18538 = D.18537->init_worker_thread;
      if (D.18538 != 0B) goto <D.18539>; else goto <D.18540>;
      <D.18539>:
      D.18541 = sgen_get_major_collector ();
      D.18542 = D.18541->init_worker_thread;
      workers_gc_thread_major_collector_data.25 = workers_gc_thread_major_collector_data;
      D.18542 (workers_gc_thread_major_collector_data.25);
      <D.18540>:
      new_state = workers_state;
      old_state = new_state;
      D.18544 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18545 = D.18544 & 512;
      D.18546 = D.18545 != 0;
      D.18547 = (long int) D.18546;
      D.18548 = __builtin_expect (D.18547, 0);
      if (D.18548 != 0) goto <D.18549>; else goto <D.18550>;
      <D.18549>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 504, "!old_state.data.gc_in_progress");
      <D.18550>:
      new_state.data.gc_in_progress = 1;
      workers_marking = 0;
      workers_job_queue_num_entries.26 = workers_job_queue_num_entries;
      D.18552 = workers_job_queue_num_entries.26 != 0;
      D.18553 = (long int) D.18552;
      D.18554 = __builtin_expect (D.18553, 0);
      if (D.18554 != 0) goto <D.18555>; else goto <D.18556>;
      <D.18555>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 509, "workers_job_queue_num_entries == 0");
      <D.18556>:
      workers_num_jobs_enqueued = 0;
      workers_num_jobs_finished = 0;
      workers_started.27 = workers_started;
      if (workers_started.27 != 0) goto <D.18558>; else goto <D.18559>;
      <D.18558>:
      D.18544 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18560 = D.18544 & 256;
      D.18561 = D.18560 == 0;
      D.18562 = (long int) D.18561;
      D.18563 = __builtin_expect (D.18562, 0);
      if (D.18563 != 0) goto <D.18564>; else goto <D.18565>;
      <D.18564>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 514, "old_state.data.done_posted");
      <D.18565>:
      D.18566 = old_state.data.num_waiting;
      D.18567 = (int) D.18566;
      workers_num.28 = workers_num;
      if (D.18567 != workers_num.28) goto <D.18569>; else goto <D.18570>;
      <D.18569>:
      workers_num.28 = workers_num;
      D.18566 = old_state.data.num_waiting;
      D.18567 = (int) D.18566;
      monoeg_g_log (0B, 4, "Expecting all %d sgen workers to be parked, but only %d are", workers_num.28, D.18567);
      <D.18295>:
      goto <D.18295>;
      <D.18570>:
      new_state.data.done_posted = 0;
      D.18571 = set_state (old_state, new_state);
      if (D.18571 == 0) goto <D.18572>; else goto <D.18573>;
      <D.18572>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 523);
      <D.18573>:
      workers_wake_up_all ();
      return;
      <D.18559>:
      D.18544 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18560 = D.18544 & 256;
      D.18574 = D.18560 != 0;
      D.18575 = (long int) D.18574;
      D.18576 = __builtin_expect (D.18575, 0);
      if (D.18576 != 0) goto <D.18577>; else goto <D.18578>;
      <D.18577>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 529, "!old_state.data.done_posted");
      <D.18578>:
      D.18579 = set_state (old_state, new_state);
      if (D.18579 == 0) goto <D.18580>; else goto <D.18581>;
      <D.18580>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 532);
      <D.18581>:
      i = 0;
      goto <D.18297>;
      <D.18296>:
      workers_start_worker (i);
      i = i + 1;
      <D.18297>:
      workers_num.28 = workers_num;
      if (i < workers_num.28) goto <D.18296>; else goto <D.18298>;
      <D.18298>:
      workers_started = 1;
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


workers_start_worker (int index)
{
  int iftmp.29;
  int workers_num.30;
  _Bool D.18591;
  long int D.18592;
  long int D.18593;
  struct WorkerData * workers_data.31;
  long unsigned int D.18597;
  long unsigned int D.18598;
  struct WorkerData * D.18599;
  long unsigned int D.18600;
  _Bool D.18601;
  long int D.18602;
  long int D.18603;
  MonoNativeThreadId * D.18606;
  void * D.18607;

  if (index < 0) goto <D.18586>; else goto <D.18589>;
  <D.18589>:
  workers_num.30 = workers_num;
  if (index >= workers_num.30) goto <D.18586>; else goto <D.18587>;
  <D.18586>:
  iftmp.29 = 1;
  goto <D.18588>;
  <D.18587>:
  iftmp.29 = 0;
  <D.18588>:
  D.18591 = iftmp.29 != 0;
  D.18592 = (long int) D.18591;
  D.18593 = __builtin_expect (D.18592, 0);
  if (D.18593 != 0) goto <D.18594>; else goto <D.18595>;
  <D.18594>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 485, "index >= 0 && index < workers_num");
  <D.18595>:
  workers_data.31 = workers_data;
  D.18597 = (long unsigned int) index;
  D.18598 = D.18597 * 4192;
  D.18599 = workers_data.31 + D.18598;
  D.18600 = D.18599->thread;
  D.18601 = D.18600 != 0;
  D.18602 = (long int) D.18601;
  D.18603 = __builtin_expect (D.18602, 0);
  if (D.18603 != 0) goto <D.18604>; else goto <D.18605>;
  <D.18604>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 487, "!workers_data [index].thread");
  <D.18605>:
  workers_data.31 = workers_data;
  D.18597 = (long unsigned int) index;
  D.18598 = D.18597 * 4192;
  D.18599 = workers_data.31 + D.18598;
  D.18606 = &D.18599->thread;
  workers_data.31 = workers_data;
  D.18597 = (long unsigned int) index;
  D.18598 = D.18597 * 4192;
  D.18607 = workers_data.31 + D.18598;
  mono_native_thread_create (D.18606, workers_thread_func, D.18607);
}


workers_thread_func (void * data_untyped)
{
  void (*<Tbf>) (void *) D.18608;
  void * D.18611;
  int D.18612;
  int workers_marking.32;
  struct SgenGrayQueue * D.18618;
  int D.18619;
  int D.18621;
  struct SgenObjectOperations * iftmp.33;
  int D.18623;
  void (*<T2c8a>) (char *, struct SgenGrayQueue *) D.18627;
  int D.18628;
  _Bool D.18629;
  long int D.18630;
  long int D.18631;
  int D.18634;
  int D.18635;
  _Bool D.18636;
  long int D.18637;
  long int D.18638;
  void * D.18643;
  struct WorkerData * data;
  struct SgenMajorCollector * major;

  data = data_untyped;
  major = sgen_get_major_collector ();
  mono_thread_info_register_small_id ();
  D.18608 = major->init_worker_thread;
  if (D.18608 != 0B) goto <D.18609>; else goto <D.18610>;
  <D.18609>:
  D.18608 = major->init_worker_thread;
  D.18611 = data->major_collector_data;
  D.18608 (D.18611);
  <D.18610>:
  init_private_gray_queue (data);
  <D.18272>:
  {
    gboolean did_work;

    did_work = 0;
    goto <D.18265>;
    <D.18264>:
    did_work = 1;
    <D.18265>:
    D.18612 = workers_dequeue_and_do_job (data);
    if (D.18612 != 0) goto <D.18264>; else goto <D.18266>;
    <D.18266>:
    workers_marking.32 = workers_marking;
    if (workers_marking.32 != 0) goto <D.18616>; else goto <D.18617>;
    <D.18616>:
    D.18618 = &data->private_gray_queue;
    D.18619 = sgen_gray_object_queue_is_empty (D.18618);
    if (D.18619 == 0) goto <D.18613>; else goto <D.18620>;
    <D.18620>:
    D.18621 = workers_get_work (data);
    if (D.18621 != 0) goto <D.18613>; else goto <D.18614>;
    <D.18613>:
    {
      struct SgenObjectOperations * ops;
      struct ScanCopyContext ctx;

      try
        {
          D.18623 = sgen_concurrent_collection_in_progress ();
          if (D.18623 != 0) goto <D.18624>; else goto <D.18625>;
          <D.18624>:
          iftmp.33 = &major->major_concurrent_ops;
          goto <D.18626>;
          <D.18625>:
          iftmp.33 = &major->major_ops;
          <D.18626>:
          ops = iftmp.33;
          D.18627 = ops->scan_object;
          ctx.scan_func = D.18627;
          ctx.copy_func = 0B;
          D.18618 = &data->private_gray_queue;
          ctx.queue = D.18618;
          D.18618 = &data->private_gray_queue;
          D.18628 = sgen_gray_object_queue_is_empty (D.18618);
          D.18629 = D.18628 != 0;
          D.18630 = (long int) D.18629;
          D.18631 = __builtin_expect (D.18630, 0);
          if (D.18631 != 0) goto <D.18632>; else goto <D.18633>;
          <D.18632>:
          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.18633>:
          goto <D.18270>;
          <D.18269>:
          D.18618 = &data->private_gray_queue;
          workers_gray_queue_share_redirect (D.18618);
          <D.18270>:
          D.18634 = sgen_drain_gray_stack (32, ctx);
          if (D.18634 == 0) goto <D.18269>; else goto <D.18271>;
          <D.18271>:
          D.18618 = &data->private_gray_queue;
          D.18635 = sgen_gray_object_queue_is_empty (D.18618);
          D.18636 = D.18635 == 0;
          D.18637 = (long int) D.18636;
          D.18638 = __builtin_expect (D.18637, 0);
          if (D.18638 != 0) goto <D.18639>; else goto <D.18640>;
          <D.18639>:
          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.18640>:
          init_private_gray_queue (data);
          did_work = 1;
        }
      finally
        {
          ctx = {CLOBBER};
        }
    }
    <D.18614>:
    <D.18617>:
    if (did_work == 0) goto <D.18641>; else goto <D.18642>;
    <D.18641>:
    workers_wait ();
    <D.18642>:
  }
  goto <D.18272>;
  D.18643 = 0B;
  return D.18643;
}


workers_dequeue_and_do_job (struct WorkerData * data)
{
  int workers_job_queue_num_entries.34;
  gboolean D.18648;
  volatile struct JobQueueEntry * workers_job_queue.35;
  int workers_job_queue_num_entries.36;
  int workers_job_queue_num_entries.37;
  int D.18656;
  _Bool D.18657;
  long int D.18658;
  long int D.18659;
  void (*<T2f63>) (struct WorkerData *, void *) D.18662;
  void * D.18663;
  int D.18664;
  int D.18665;
  struct JobQueueEntry * entry;

  workers_job_queue_num_entries.34 = workers_job_queue_num_entries;
  if (workers_job_queue_num_entries.34 == 0) goto <D.18646>; else goto <D.18647>;
  <D.18646>:
  D.18648 = 0;
  return D.18648;
  <D.18647>:
  pthread_mutex_lock (&workers_job_queue_mutex);
  entry = workers_job_queue;
  if (entry != 0B) goto <D.18649>; else goto <D.18650>;
  <D.18649>:
  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.18650>:
  pthread_mutex_unlock (&workers_job_queue_mutex);
  if (entry == 0B) goto <D.18654>; else goto <D.18655>;
  <D.18654>:
  D.18648 = 0;
  return D.18648;
  <D.18655>:
  D.18656 = collection_needs_workers ();
  D.18657 = D.18656 == 0;
  D.18658 = (long int) D.18657;
  D.18659 = __builtin_expect (D.18658, 0);
  if (D.18659 != 0) goto <D.18660>; else goto <D.18661>;
  <D.18660>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 214, "collection_needs_workers ()");
  <D.18661>:
  D.18662 = entry->func;
  D.18663 = entry->data;
  D.18662 (data, D.18663);
  sgen_free_internal (entry, 26);
  {
    int __old_x;

    <D.18218>:
    __old_x = workers_num_jobs_finished;
    D.18664 = __old_x + 1;
    D.18665 = InterlockedCompareExchange (&workers_num_jobs_finished, D.18664, __old_x);
    if (D.18665 != __old_x) goto <D.18218>; else goto <D.18219>;
    <D.18219>:
  }
  D.18648 = 1;
  return D.18648;
}


workers_get_work (struct WorkerData * data)
{
  struct SgenGrayQueue * D.18667;
  int D.18668;
  _Bool D.18669;
  long int D.18670;
  long int D.18671;
  int D.18674;
  gboolean D.18677;
  struct WorkerData * workers_data.38;
  long unsigned int D.18679;
  long unsigned int D.18680;
  int D.18683;
  int workers_num.39;
  signed long D.18687;
  long unsigned int D.18688;
  long unsigned int D.18689;
  int D.18694;
  _Bool D.18695;
  long int D.18696;
  long int D.18697;
  struct SgenMajorCollector * major;
  int i;

  D.18667 = &data->private_gray_queue;
  D.18668 = sgen_gray_object_queue_is_empty (D.18667);
  D.18669 = D.18668 == 0;
  D.18670 = (long int) D.18669;
  D.18671 = __builtin_expect (D.18670, 0);
  if (D.18671 != 0) goto <D.18672>; else goto <D.18673>;
  <D.18672>:
  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.18673>:
  D.18674 = workers_steal (data, data, 1);
  if (D.18674 != 0) goto <D.18675>; else goto <D.18676>;
  <D.18675>:
  D.18677 = 1;
  return D.18677;
  <D.18676>:
  i = 0;
  goto <D.18240>;
  <D.18239>:
  {
    struct WorkerData * victim_data;

    workers_data.38 = workers_data;
    D.18679 = (long unsigned int) i;
    D.18680 = D.18679 * 4192;
    victim_data = workers_data.38 + D.18680;
    if (data == victim_data) goto <D.18681>; else goto <D.18682>;
    <D.18681>:
    // predicted unlikely by continue predictor.
    goto <D.18238>;
    <D.18682>:
    D.18683 = workers_steal (data, victim_data, 1);
    if (D.18683 != 0) goto <D.18684>; else goto <D.18685>;
    <D.18684>:
    D.18677 = 1;
    return D.18677;
    <D.18685>:
  }
  <D.18238>:
  i = i + 1;
  <D.18240>:
  workers_num.39 = workers_num;
  if (i < workers_num.39) goto <D.18239>; else goto <D.18241>;
  <D.18241>:
  major = sgen_get_major_collector ();
  D.18687 = BIT_FIELD_REF <*major, 64, 64>;
  D.18688 = (long unsigned int) D.18687;
  D.18689 = D.18688;
  if (D.18689 != 0) goto <D.18690>; else goto <D.18691>;
  <D.18690>:
  {
    struct GrayQueueSection * section;

    section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue);
    if (section != 0B) goto <D.18692>; else goto <D.18693>;
    <D.18692>:
    D.18667 = &data->private_gray_queue;
    sgen_gray_object_enqueue_section (D.18667, section);
    D.18677 = 1;
    return D.18677;
    <D.18693>:
  }
  <D.18691>:
  D.18667 = &data->private_gray_queue;
  D.18694 = sgen_gray_object_queue_is_empty (D.18667);
  D.18695 = D.18694 == 0;
  D.18696 = (long int) D.18695;
  D.18697 = __builtin_expect (D.18696, 0);
  if (D.18697 != 0) goto <D.18698>; else goto <D.18699>;
  <D.18698>:
  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.18699>:
  D.18677 = 0;
  return D.18677;
}


workers_steal (struct WorkerData * data, struct WorkerData * victim_data, gboolean lock)
{
  struct GrayQueueSection * D.18701;
  _Bool D.18702;
  long int D.18703;
  long int D.18704;
  int D.18707;
  gboolean D.18710;
  union mono_mutex_t * D.18713;
  int D.18714;
  int D.18717;
  int D.18718;
  char *[125] * D.18719;
  int D.18720;
  sizetype D.18721;
  sizetype D.18722;
  sizetype D.18723;
  sizetype D.18724;
  sizetype D.18725;
  char * * D.18726;
  long unsigned int D.18727;
  long unsigned int D.18728;
  int D.18729;
  int D.18730;
  long long int D.18737;
  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.18746;
  struct SgenGrayQueue * queue;
  int num;
  int n;

  queue = &data->private_gray_queue;
  D.18701 = queue->first;
  D.18702 = D.18701 != 0B;
  D.18703 = (long int) D.18702;
  D.18704 = __builtin_expect (D.18703, 0);
  if (D.18704 != 0) goto <D.18705>; else goto <D.18706>;
  <D.18705>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 230, "!queue->first");
  <D.18706>:
  D.18707 = victim_data->stealable_stack_fill;
  if (D.18707 == 0) goto <D.18708>; else goto <D.18709>;
  <D.18708>:
  D.18710 = 0;
  return D.18710;
  <D.18709>:
  if (lock != 0) goto <D.18711>; else goto <D.18712>;
  <D.18711>:
  D.18713 = &victim_data->stealable_stack_mutex;
  D.18714 = pthread_mutex_trylock (D.18713);
  if (D.18714 != 0) goto <D.18715>; else goto <D.18716>;
  <D.18715>:
  D.18710 = 0;
  return D.18710;
  <D.18716>:
  <D.18712>:
  D.18717 = victim_data->stealable_stack_fill;
  D.18718 = D.18717 + 1;
  num = D.18718 / 2;
  n = num;
  goto <D.18230>;
  <D.18229>:
  {
    int m;

    m = MIN_EXPR <n, 125>;
    n = n - m;
    sgen_gray_object_alloc_queue_section (queue);
    D.18701 = queue->first;
    D.18719 = &D.18701->objects;
    D.18720 = victim_data->stealable_stack_fill;
    D.18721 = (sizetype) D.18720;
    D.18722 = (sizetype) n;
    D.18723 = (sizetype) num;
    D.18724 = D.18722 - D.18723;
    D.18725 = D.18721 + D.18724;
    D.18726 = &victim_data->stealable_stack[D.18725];
    D.18727 = (long unsigned int) m;
    D.18728 = D.18727 * 8;
    memcpy (D.18719, D.18726, D.18728);
    D.18701 = queue->first;
    D.18701->end = m;
  }
  <D.18230>:
  if (n > 0) goto <D.18229>; else goto <D.18231>;
  <D.18231>:
  D.18729 = victim_data->stealable_stack_fill;
  D.18730 = D.18729 - num;
  victim_data->stealable_stack_fill = D.18730;
  if (lock != 0) goto <D.18731>; else goto <D.18732>;
  <D.18731>:
  D.18713 = &victim_data->stealable_stack_mutex;
  pthread_mutex_unlock (D.18713);
  <D.18732>:
  if (data == victim_data) goto <D.18733>; else goto <D.18734>;
  <D.18733>:
  if (lock != 0) goto <D.18735>; else goto <D.18736>;
  <D.18735>:
  D.18737 = (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.18737 + stat_workers_stolen_from_self_lock.40;
  stat_workers_stolen_from_self_lock = stat_workers_stolen_from_self_lock.41;
  goto <D.18740>;
  <D.18736>:
  D.18737 = (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.18737 + stat_workers_stolen_from_self_no_lock.42;
  stat_workers_stolen_from_self_no_lock = stat_workers_stolen_from_self_no_lock.43;
  <D.18740>:
  goto <D.18743>;
  <D.18734>:
  D.18737 = (long long int) num;
  stat_workers_stolen_from_others.44 = stat_workers_stolen_from_others;
  stat_workers_stolen_from_others.45 = D.18737 + stat_workers_stolen_from_others.44;
  stat_workers_stolen_from_others = stat_workers_stolen_from_others.45;
  <D.18743>:
  D.18746 = num != 0;
  D.18710 = (gboolean) D.18746;
  return D.18710;
}


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

  D.18749 = __builtin_object_size (__dest, 0);
  D.18748 = __builtin___memcpy_chk (__dest, __src, __len, D.18749);
  return D.18748;
}


workers_gray_queue_share_redirect (struct SgenGrayQueue * queue)
{
  int D.18751;
  <unnamed-unsigned:1> D.18754;
  union mono_mutex_t * D.18757;
  int iftmp.46;
  int D.18759;
  int D.18760;
  int D.18761;
  int D.18765;
  int D.18766;
  sizetype D.18767;
  char * * D.18768;
  sizetype D.18769;
  char * * D.18770;
  long unsigned int D.18771;
  long unsigned int D.18772;
  sizetype D.18773;
  char * * D.18774;
  int D.18775;
  int D.18776;
  int D.18777;
  int D.18781;
  int D.18783;
  <unnamed-unsigned:1> D.18786;
  struct GrayQueueSection * section;
  struct WorkerData * data;

  data = queue->alloc_prepare_data;
  D.18751 = data->stealable_stack_fill;
  if (D.18751 != 0) goto <D.18752>; else goto <D.18753>;
  <D.18752>:
  D.18754 = workers_state.data.gc_in_progress;
  if (D.18754 != 0) goto <D.18755>; else goto <D.18756>;
  <D.18755>:
  workers_wake_up_all ();
  <D.18756>:
  return;
  <D.18753>:
  D.18757 = &data->stealable_stack_mutex;
  pthread_mutex_lock (D.18757);
  goto <D.18250>;
  <D.18249>:
  {
    int num;

    D.18759 = section->end;
    D.18760 = data->stealable_stack_fill;
    D.18761 = 512 - D.18760;
    if (D.18759 < D.18761) goto <D.18762>; else goto <D.18763>;
    <D.18762>:
    iftmp.46 = section->end;
    goto <D.18764>;
    <D.18763>:
    D.18765 = data->stealable_stack_fill;
    iftmp.46 = 512 - D.18765;
    <D.18764>:
    num = iftmp.46;
    D.18766 = data->stealable_stack_fill;
    D.18767 = (sizetype) D.18766;
    D.18768 = &data->stealable_stack[D.18767];
    D.18759 = section->end;
    D.18769 = (sizetype) D.18759;
    D.18770 = &section->objects[D.18769];
    D.18771 = (long unsigned int) num;
    D.18772 = D.18771 * 8;
    D.18773 = -D.18772;
    D.18774 = D.18770 + D.18773;
    D.18771 = (long unsigned int) num;
    D.18772 = D.18771 * 8;
    memcpy (D.18768, D.18774, D.18772);
    D.18759 = section->end;
    D.18775 = D.18759 - num;
    section->end = D.18775;
    D.18776 = data->stealable_stack_fill;
    D.18777 = D.18776 + num;
    data->stealable_stack_fill = D.18777;
    D.18759 = section->end;
    if (D.18759 != 0) goto <D.18778>; else goto <D.18779>;
    <D.18778>:
    sgen_gray_object_enqueue_section (queue, section);
    goto <D.18780>;
    <D.18779>:
    sgen_gray_object_free_queue_section (section);
    <D.18780>:
  }
  <D.18250>:
  D.18781 = data->stealable_stack_fill;
  if (D.18781 <= 511) goto <D.18782>; else goto <D.18251>;
  <D.18782>:
  section = sgen_gray_object_dequeue_section (queue);
  if (section != 0B) goto <D.18249>; else goto <D.18251>;
  <D.18251>:
  D.18783 = sgen_gray_object_queue_is_empty (queue);
  if (D.18783 != 0) goto <D.18784>; else goto <D.18785>;
  <D.18784>:
  workers_steal (data, data, 0);
  <D.18785>:
  D.18757 = &data->stealable_stack_mutex;
  pthread_mutex_unlock (D.18757);
  D.18786 = workers_state.data.gc_in_progress;
  if (D.18786 != 0) goto <D.18787>; else goto <D.18788>;
  <D.18787>:
  workers_wake_up_all ();
  <D.18788>:
}


sgen_gray_object_queue_is_empty (struct SgenGrayQueue * queue)
{
  gboolean D.18790;
  struct GrayQueueSection * D.18791;
  _Bool D.18792;

  D.18791 = queue->first;
  D.18792 = D.18791 == 0B;
  D.18790 = (gboolean) D.18792;
  return D.18790;
}


init_private_gray_queue (struct WorkerData * data)
{
  struct SgenGrayQueue * D.18794;
  void (*<T2bc8>) (char *) iftmp.47;
  struct SgenMajorCollector * D.18796;
  int D.18797;

  D.18794 = &data->private_gray_queue;
  D.18796 = sgen_get_major_collector ();
  D.18797 = D.18796->is_concurrent;
  if (D.18797 != 0) goto <D.18798>; else goto <D.18799>;
  <D.18798>:
  iftmp.47 = concurrent_enqueue_check;
  goto <D.18800>;
  <D.18799>:
  iftmp.47 = 0B;
  <D.18800>:
  sgen_gray_object_queue_init_with_alloc_prepare (D.18794, 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 int D.18803;
  unsigned int D.18804;
  _Bool D.18805;
  long int D.18806;
  long int D.18807;
  unsigned char D.18810;
  unsigned char D.18811;
  int D.18812;
  int workers_num.50;
  unsigned int D.18816;
  int D.18819;
  unsigned int D.18820;
  unsigned int D.18821;
  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.18195>:
      new_state = workers_state;
      old_state = new_state;
      D.18803 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18804 = D.18803 & 256;
      D.18805 = D.18804 != 0;
      D.18806 = (long int) D.18805;
      D.18807 = __builtin_expect (D.18806, 0);
      if (D.18807 != 0) goto <D.18808>; else goto <D.18809>;
      <D.18808>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 125, "!old_state.data.done_posted");
      <D.18809>:
      D.18810 = new_state.data.num_waiting;
      D.18811 = D.18810 + 1;
      new_state.data.num_waiting = D.18811;
      D.18810 = new_state.data.num_waiting;
      D.18812 = (int) D.18810;
      workers_num.50 = workers_num;
      if (D.18812 == workers_num.50) goto <D.18814>; else goto <D.18815>;
      <D.18814>:
      D.18803 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18816 = D.18803 & 512;
      if (D.18816 == 0) goto <D.18817>; else goto <D.18818>;
      <D.18817>:
      new_state.data.done_posted = 1;
      <D.18818>:
      <D.18815>:
      D.18819 = set_state (old_state, new_state);
      if (D.18819 == 0) goto <D.18195>; else goto <D.18196>;
      <D.18196>:
      mono_memory_barrier ();
      D.18820 = BIT_FIELD_REF <new_state, 32, 0>;
      D.18821 = D.18820 & 256;
      if (D.18821 != 0) goto <D.18822>; else goto <D.18823>;
      <D.18822>:
      mono_sem_post (&workers_done_sem);
      <D.18823>:
      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.18824;
  <unnamed-unsigned:1> D.18825;

  D.18825 = workers_state.data.gc_in_progress;
  D.18824 = (gboolean) D.18825;
  return D.18824;
}


sgen_workers_start_marking ()
{
  int D.18827;
  int iftmp.51;
  int workers_started.52;
  <unnamed-unsigned:1> D.18836;
  _Bool D.18837;
  long int D.18838;
  long int D.18839;
  int workers_marking.53;
  _Bool D.18843;
  long int D.18844;
  long int D.18845;

  D.18827 = collection_needs_workers ();
  if (D.18827 == 0) goto <D.18828>; else goto <D.18829>;
  <D.18828>:
  return;
  <D.18829>:
  workers_started.52 = workers_started;
  if (workers_started.52 == 0) goto <D.18831>; else goto <D.18835>;
  <D.18835>:
  D.18836 = workers_state.data.gc_in_progress;
  if (D.18836 == 0) goto <D.18831>; else goto <D.18832>;
  <D.18831>:
  iftmp.51 = 1;
  goto <D.18833>;
  <D.18832>:
  iftmp.51 = 0;
  <D.18833>:
  D.18837 = iftmp.51 != 0;
  D.18838 = (long int) D.18837;
  D.18839 = __builtin_expect (D.18838, 0);
  if (D.18839 != 0) goto <D.18840>; else goto <D.18841>;
  <D.18840>:
  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.18841>:
  workers_marking.53 = workers_marking;
  D.18843 = workers_marking.53 != 0;
  D.18844 = (long int) D.18843;
  D.18845 = __builtin_expect (D.18844, 0);
  if (D.18845 != 0) goto <D.18846>; else goto <D.18847>;
  <D.18846>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 553, "!workers_marking");
  <D.18847>:
  workers_marking = 1;
  workers_wake_up_all ();
}


sgen_workers_join ()
{
  int D.18849;
  unsigned int D.18852;
  unsigned int D.18853;
  _Bool D.18854;
  long int D.18855;
  long int D.18856;
  unsigned int D.18859;
  _Bool D.18860;
  long int D.18861;
  long int D.18862;
  int D.18865;
  unsigned char D.18866;
  int D.18867;
  int workers_num.54;
  unsigned char D.18871;
  int D.18872;
  _Bool D.18873;
  long int D.18874;
  long int D.18875;
  _Bool D.18878;
  long int D.18879;
  long int D.18880;
  int workers_job_queue_num_entries.55;
  int D.18887;
  int D.18888;
  struct SgenMajorCollector * D.18891;
  void (*<Tbf>) (void *) D.18892;
  struct SgenMajorCollector * D.18895;
  void (*<Tbf>) (void *) D.18896;
  struct WorkerData * workers_data.56;
  long unsigned int D.18898;
  long unsigned int D.18899;
  struct WorkerData * D.18900;
  void * D.18901;
  int workers_job_queue_num_entries.57;
  _Bool D.18903;
  long int D.18904;
  long int D.18905;
  int D.18908;
  _Bool D.18909;
  long int D.18910;
  long int D.18911;
  int D.18914;
  _Bool D.18915;
  long int D.18916;
  long int D.18917;
  struct SgenGrayQueue * D.18920;
  int D.18921;
  _Bool D.18922;
  long int D.18923;
  long int D.18924;
  union State old_state;
  union State new_state;
  int i;
  void reawaken = <<< error >>>;

  try
    {
      D.18849 = collection_needs_workers ();
      if (D.18849 == 0) goto <D.18850>; else goto <D.18851>;
      <D.18850>:
      return;
      <D.18851>:
      <D.18311>:
      new_state = workers_state;
      old_state = new_state;
      D.18852 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18853 = D.18852 & 512;
      D.18854 = D.18853 == 0;
      D.18855 = (long int) D.18854;
      D.18856 = __builtin_expect (D.18855, 0);
      if (D.18856 != 0) goto <D.18857>; else goto <D.18858>;
      <D.18857>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 571, "old_state.data.gc_in_progress");
      <D.18858>:
      D.18852 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18859 = D.18852 & 256;
      D.18860 = D.18859 != 0;
      D.18861 = (long int) D.18860;
      D.18862 = __builtin_expect (D.18861, 0);
      if (D.18862 != 0) goto <D.18863>; else goto <D.18864>;
      <D.18863>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 572, "!old_state.data.done_posted");
      <D.18864>:
      new_state.data.gc_in_progress = 0;
      D.18865 = set_state (old_state, new_state);
      if (D.18865 == 0) goto <D.18311>; else goto <D.18312>;
      <D.18312>:
      D.18866 = new_state.data.num_waiting;
      D.18867 = (int) D.18866;
      workers_num.54 = workers_num;
      if (D.18867 == workers_num.54) goto <D.18869>; else goto <D.18870>;
      <D.18869>:
      reawaken:
      workers_wake_up_all ();
      <D.18870>:
      mono_sem_wait (&workers_done_sem, 0);
      new_state = workers_state;
      old_state = new_state;
      D.18871 = old_state.data.num_waiting;
      D.18872 = (int) D.18871;
      workers_num.54 = workers_num;
      D.18873 = D.18872 != workers_num.54;
      D.18874 = (long int) D.18873;
      D.18875 = __builtin_expect (D.18874, 0);
      if (D.18875 != 0) goto <D.18876>; else goto <D.18877>;
      <D.18876>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 593, "old_state.data.num_waiting == workers_num");
      <D.18877>:
      D.18852 = BIT_FIELD_REF <old_state, 32, 0>;
      D.18859 = D.18852 & 256;
      D.18878 = D.18859 == 0;
      D.18879 = (long int) D.18878;
      D.18880 = __builtin_expect (D.18879, 0);
      if (D.18880 != 0) goto <D.18881>; else goto <D.18882>;
      <D.18881>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 594, "old_state.data.done_posted");
      <D.18882>:
      workers_job_queue_num_entries.55 = workers_job_queue_num_entries;
      if (workers_job_queue_num_entries.55 != 0) goto <D.18883>; else goto <D.18886>;
      <D.18886>:
      D.18887 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      if (D.18887 == 0) goto <D.18883>; else goto <D.18884>;
      <D.18883>:
      new_state.data.done_posted = 0;
      D.18888 = set_state (old_state, new_state);
      if (D.18888 == 0) goto <D.18889>; else goto <D.18890>;
      <D.18889>:
      monoeg_assertion_message ("* Assertion: should not be reached at %s:%d\n", "sgen-workers.c", 613);
      <D.18890>:
      goto reawaken;
      <D.18884>:
      workers_marking = 0;
      D.18891 = sgen_get_major_collector ();
      D.18892 = D.18891->reset_worker_data;
      if (D.18892 != 0B) goto <D.18893>; else goto <D.18894>;
      <D.18893>:
      i = 0;
      goto <D.18315>;
      <D.18314>:
      D.18895 = sgen_get_major_collector ();
      D.18896 = D.18895->reset_worker_data;
      workers_data.56 = workers_data;
      D.18898 = (long unsigned int) i;
      D.18899 = D.18898 * 4192;
      D.18900 = workers_data.56 + D.18899;
      D.18901 = D.18900->major_collector_data;
      D.18896 (D.18901);
      i = i + 1;
      <D.18315>:
      workers_num.54 = workers_num;
      if (i < workers_num.54) goto <D.18314>; else goto <D.18316>;
      <D.18316>:
      <D.18894>:
      workers_job_queue_num_entries.57 = workers_job_queue_num_entries;
      D.18903 = workers_job_queue_num_entries.57 != 0;
      D.18904 = (long int) D.18903;
      D.18905 = __builtin_expect (D.18904, 0);
      if (D.18905 != 0) goto <D.18906>; else goto <D.18907>;
      <D.18906>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 626, "workers_job_queue_num_entries == 0");
      <D.18907>:
      D.18908 = sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue);
      D.18909 = D.18908 == 0;
      D.18910 = (long int) D.18909;
      D.18911 = __builtin_expect (D.18910, 0);
      if (D.18911 != 0) goto <D.18912>; else goto <D.18913>;
      <D.18912>:
      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.18913>:
      i = 0;
      goto <D.18318>;
      <D.18317>:
      workers_data.56 = workers_data;
      D.18898 = (long unsigned int) i;
      D.18899 = D.18898 * 4192;
      D.18900 = workers_data.56 + D.18899;
      D.18914 = D.18900->stealable_stack_fill;
      D.18915 = D.18914 != 0;
      D.18916 = (long int) D.18915;
      D.18917 = __builtin_expect (D.18916, 0);
      if (D.18917 != 0) goto <D.18918>; else goto <D.18919>;
      <D.18918>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 629, "!workers_data [i].stealable_stack_fill");
      <D.18919>:
      workers_data.56 = workers_data;
      D.18898 = (long unsigned int) i;
      D.18899 = D.18898 * 4192;
      D.18900 = workers_data.56 + D.18899;
      D.18920 = &D.18900->private_gray_queue;
      D.18921 = sgen_gray_object_queue_is_empty (D.18920);
      D.18922 = D.18921 == 0;
      D.18923 = (long int) D.18922;
      D.18924 = __builtin_expect (D.18923, 0);
      if (D.18924 != 0) goto <D.18925>; else goto <D.18926>;
      <D.18925>:
      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.18926>:
      i = i + 1;
      <D.18318>:
      workers_num.54 = workers_num;
      if (i < workers_num.54) goto <D.18317>; else goto <D.18319>;
      <D.18319>:
    }
  finally
    {
      old_state = {CLOBBER};
      new_state = {CLOBBER};
    }
}


sgen_workers_all_done ()
{
  unsigned int D.18930;
  unsigned int D.18931;
  _Bool D.18932;
  long int D.18933;
  long int D.18934;
  unsigned int D.18937;
  _Bool D.18938;
  long int D.18939;
  long int D.18940;
  gboolean D.18943;
  unsigned char D.18944;
  int D.18945;
  int workers_num.58;
  _Bool D.18947;
  union State state;

  try
    {
      state = workers_state;
      D.18930 = BIT_FIELD_REF <state, 32, 0>;
      D.18931 = D.18930 & 512;
      D.18932 = D.18931 == 0;
      D.18933 = (long int) D.18932;
      D.18934 = __builtin_expect (D.18933, 0);
      if (D.18934 != 0) goto <D.18935>; else goto <D.18936>;
      <D.18935>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 642, "state.data.gc_in_progress");
      <D.18936>:
      D.18930 = BIT_FIELD_REF <state, 32, 0>;
      D.18937 = D.18930 & 256;
      D.18938 = D.18937 != 0;
      D.18939 = (long int) D.18938;
      D.18940 = __builtin_expect (D.18939, 0);
      if (D.18940 != 0) goto <D.18941>; else goto <D.18942>;
      <D.18941>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "sgen-workers.c", 643, "!state.data.done_posted");
      <D.18942>:
      D.18944 = state.data.num_waiting;
      D.18945 = (int) D.18944;
      workers_num.58 = workers_num;
      D.18947 = D.18945 == workers_num.58;
      D.18943 = (gboolean) D.18947;
      return D.18943;
    }
  finally
    {
      state = {CLOBBER};
    }
}


sgen_is_worker_thread (MonoNativeThreadId thread)
{
  struct SgenMajorCollector * D.18950;
  gboolean (*<T2dab>) (MonoNativeThreadId) D.18951;
  struct SgenMajorCollector * D.18954;
  gboolean (*<T2dab>) (MonoNativeThreadId) D.18955;
  int D.18956;
  gboolean D.18959;
  struct WorkerData * workers_data.59;
  long unsigned int D.18961;
  long unsigned int D.18962;
  struct WorkerData * D.18963;
  long unsigned int D.18964;
  int workers_num.60;
  int i;

  D.18950 = sgen_get_major_collector ();
  D.18951 = D.18950->is_worker_thread;
  if (D.18951 != 0B) goto <D.18952>; else goto <D.18953>;
  <D.18952>:
  D.18954 = sgen_get_major_collector ();
  D.18955 = D.18954->is_worker_thread;
  D.18956 = D.18955 (thread);
  if (D.18956 != 0) goto <D.18957>; else goto <D.18958>;
  <D.18957>:
  D.18959 = 1;
  return D.18959;
  <D.18958>:
  <D.18953>:
  i = 0;
  goto <D.18329>;
  <D.18328>:
  workers_data.59 = workers_data;
  D.18961 = (long unsigned int) i;
  D.18962 = D.18961 * 4192;
  D.18963 = workers_data.59 + D.18962;
  D.18964 = D.18963->thread;
  if (D.18964 == thread) goto <D.18965>; else goto <D.18966>;
  <D.18965>:
  D.18959 = 1;
  return D.18959;
  <D.18966>:
  i = i + 1;
  <D.18329>:
  workers_num.60 = workers_num;
  if (i < workers_num.60) goto <D.18328>; else goto <D.18330>;
  <D.18330>:
  D.18959 = 0;
  return D.18959;
}


sgen_workers_get_distribute_section_gray_queue ()
{
  struct SgenSectionGrayQueue * D.18969;

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


sgen_workers_reset_data ()
{
  struct SgenMajorCollector * D.18971;
  void (*<Tbf>) (void *) D.18972;
  struct SgenMajorCollector * D.18975;
  void (*<Tbf>) (void *) D.18976;
  void * workers_gc_thread_major_collector_data.61;

  D.18971 = sgen_get_major_collector ();
  D.18972 = D.18971->reset_worker_data;
  if (D.18972 != 0B) goto <D.18973>; else goto <D.18974>;
  <D.18973>:
  D.18975 = sgen_get_major_collector ();
  D.18976 = D.18975->reset_worker_data;
  workers_gc_thread_major_collector_data.61 = workers_gc_thread_major_collector_data;
  D.18976 (workers_gc_thread_major_collector_data.61);
  <D.18974>:
}


