__attribute__((visibility ("hidden")))
mono_lock_free_alloc (struct MonoLockFreeAllocator * heap)
{
  void * D.5549;
  void * addr;

  <D.5493>:
  addr = alloc_from_active_or_partial (heap);
  if (addr != 0B) goto <D.5492>; else goto <D.5547>;
  <D.5547>:
  addr = alloc_from_new_sb (heap);
  if (addr != 0B) goto <D.5492>; else goto <D.5548>;
  <D.5548>:
  goto <D.5493>;
  <D.5492>:
  D.5549 = addr;
  return D.5549;
}


alloc_from_active_or_partial (struct MonoLockFreeAllocator * heap)
{
  struct _MonoLockFreeAllocDescriptor * * D.5553;
  void * D.5554;
  void * D.5559;
  volatile gint32 * D.5560;
  unsigned int D.5561;
  unsigned int D.5562;
  _Bool D.5565;
  long int D.5566;
  long int D.5567;
  <unnamed-unsigned:15> D.5570;
  int D.5571;
  _Bool D.5572;
  long int D.5573;
  long int D.5574;
  void * D.5577;
  <unnamed-unsigned:15> D.5578;
  unsigned int D.5579;
  unsigned int D.5580;
  unsigned int D.5581;
  sizetype D.5582;
  unsigned int D.5583;
  _Bool D.5584;
  long int D.5585;
  long int D.5586;
  short unsigned int D.5589;
  <unnamed-unsigned:15> D.5590;
  <unnamed-unsigned:15> D.5591;
  <unnamed-unsigned:15> D.5592;
  unsigned int D.5593;
  unsigned int D.5594;
  int D.5597;
  unsigned int D.5598;
  void * D.5601;
  struct Descriptor * desc;
  union Anchor old_anchor;
  union Anchor new_anchor;
  void * addr;
  void retry = <<< error >>>;

  try
    {
      retry:
      desc = heap->active;
      if (desc != 0B) goto <D.5551>; else goto <D.5552>;
      <D.5551>:
      D.5553 = &heap->active;
      D.5554 = InterlockedCompareExchangePointer (D.5553, 0B, desc);
      if (D.5554 != desc) goto retry; else goto <D.5555>;
      <D.5555>:
      goto <D.5556>;
      <D.5552>:
      desc = heap_get_partial (heap);
      if (desc == 0B) goto <D.5557>; else goto <D.5558>;
      <D.5557>:
      D.5559 = 0B;
      return D.5559;
      <D.5558>:
      <D.5556>:
      <D.5476>:
      {
        unsigned int next;

        D.5560 = &desc->anchor.value;
        old_anchor = MEM[(volatile union Anchor *)D.5560];
        new_anchor = old_anchor;
        D.5561 = BIT_FIELD_REF <MEM[(void *)&old_anchor], 32, 0>;
        D.5562 = D.5561 & 3;
        if (D.5562 == 2) goto <D.5563>; else goto <D.5564>;
        <D.5563>:
        desc_retire (desc);
        goto retry;
        <D.5564>:
        D.5561 = BIT_FIELD_REF <MEM[(void *)&old_anchor], 32, 0>;
        D.5562 = D.5561 & 3;
        D.5565 = D.5562 != 1;
        D.5566 = (long int) D.5565;
        D.5567 = __builtin_expect (D.5566, 0);
        if (D.5567 != 0) goto <D.5568>; else goto <D.5569>;
        <D.5568>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 383, "old_anchor.data.state == STATE_PARTIAL");
        <D.5569>:
        D.5570 = old_anchor.data.count;
        D.5571 = (int) D.5570;
        D.5572 = D.5571 <= 0;
        D.5573 = (long int) D.5572;
        D.5574 = __builtin_expect (D.5573, 0);
        if (D.5574 != 0) goto <D.5575>; else goto <D.5576>;
        <D.5575>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 384, "old_anchor.data.count > 0");
        <D.5576>:
        D.5577 = desc->sb;
        D.5578 = old_anchor.data.avail;
        D.5579 = (unsigned int) D.5578;
        D.5580 = desc->slot_size;
        D.5581 = D.5579 * D.5580;
        D.5582 = (sizetype) D.5581;
        addr = D.5577 + D.5582;
        mono_memory_read_barrier ();
        next = MEM[(unsigned int *)addr];
        D.5580 = desc->slot_size;
        D.5583 = 16368 / D.5580;
        D.5584 = D.5583 <= next;
        D.5585 = (long int) D.5584;
        D.5586 = __builtin_expect (D.5585, 0);
        if (D.5586 != 0) goto <D.5587>; else goto <D.5588>;
        <D.5587>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 391, "next < SB_USABLE_SIZE / desc->slot_size");
        <D.5588>:
        D.5589 = (short unsigned int) next;
        D.5590 = (<unnamed-unsigned:15>) D.5589;
        new_anchor.data.avail = D.5590;
        D.5591 = new_anchor.data.count;
        D.5592 = D.5591 + 32767;
        new_anchor.data.count = D.5592;
        D.5593 = BIT_FIELD_REF <MEM[(void *)&new_anchor], 32, 0>;
        D.5594 = D.5593 & 131068;
        if (D.5594 == 0) goto <D.5595>; else goto <D.5596>;
        <D.5595>:
        new_anchor.data.state = 0;
        <D.5596>:
      }
      D.5597 = set_anchor (desc, old_anchor, new_anchor);
      if (D.5597 == 0) goto <D.5476>; else goto <D.5477>;
      <D.5477>:
      D.5593 = BIT_FIELD_REF <MEM[(void *)&new_anchor], 32, 0>;
      D.5598 = D.5593 & 3;
      if (D.5598 == 1) goto <D.5599>; else goto <D.5600>;
      <D.5599>:
      D.5553 = &heap->active;
      D.5601 = InterlockedCompareExchangePointer (D.5553, desc, 0B);
      if (D.5601 != 0B) goto <D.5602>; else goto <D.5603>;
      <D.5602>:
      heap_put_partial (desc);
      <D.5603>:
      <D.5600>:
      D.5559 = addr;
      return D.5559;
    }
  finally
    {
      old_anchor = {CLOBBER};
      new_anchor = {CLOBBER};
    }
}


heap_get_partial (struct MonoLockFreeAllocator * heap)
{
  struct Descriptor * D.5606;
  struct MonoLockFreeAllocSizeClass * D.5607;

  D.5607 = heap->sc;
  D.5606 = list_get_partial (D.5607);
  return D.5606;
}


list_get_partial (struct MonoLockFreeAllocSizeClass * sc)
{
  struct MonoLockFreeQueue * D.5609;
  struct Descriptor * D.5612;
  <unnamed-unsigned:2> D.5613;

  <D.5442>:
  {
    struct Descriptor * desc;

    D.5609 = &sc->partial;
    desc = mono_lock_free_queue_dequeue (D.5609);
    if (desc == 0B) goto <D.5610>; else goto <D.5611>;
    <D.5610>:
    D.5612 = 0B;
    return D.5612;
    <D.5611>:
    D.5613 = desc->anchor.data.state;
    if (D.5613 != 2) goto <D.5614>; else goto <D.5615>;
    <D.5614>:
    D.5612 = desc;
    return D.5612;
    <D.5615>:
    desc_retire (desc);
  }
  goto <D.5442>;
}


desc_retire (struct Descriptor * desc)
{
  <unnamed-unsigned:2> D.5617;
  _Bool D.5618;
  long int D.5619;
  long int D.5620;
  int D.5623;
  _Bool D.5624;
  long int D.5625;
  long int D.5626;
  void * D.5629;

  D.5617 = desc->anchor.data.state;
  D.5618 = D.5617 != 2;
  D.5619 = (long int) D.5618;
  D.5620 = __builtin_expect (D.5619, 0);
  if (D.5620 != 0) goto <D.5621>; else goto <D.5622>;
  <D.5621>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 251, "desc->anchor.data.state == STATE_EMPTY");
  <D.5622>:
  D.5623 = desc->in_use;
  D.5624 = D.5623 == 0;
  D.5625 = (long int) D.5624;
  D.5626 = __builtin_expect (D.5625, 0);
  if (D.5626 != 0) goto <D.5627>; else goto <D.5628>;
  <D.5627>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 252, "desc->in_use");
  <D.5628>:
  desc->in_use = 0;
  D.5629 = desc->sb;
  free_sb (D.5629);
  mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, 0, 1);
}


desc_enqueue_avail (void * _desc)
{
  <unnamed-unsigned:2> D.5630;
  _Bool D.5631;
  long int D.5632;
  long int D.5633;
  int D.5636;
  _Bool D.5637;
  long int D.5638;
  long int D.5639;
  void * D.5642;
  struct Descriptor * desc;
  struct Descriptor * old_head;

  desc = _desc;
  D.5630 = desc->anchor.data.state;
  D.5631 = D.5630 != 2;
  D.5632 = (long int) D.5631;
  D.5633 = __builtin_expect (D.5632, 0);
  if (D.5633 != 0) goto <D.5634>; else goto <D.5635>;
  <D.5634>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 238, "desc->anchor.data.state == STATE_EMPTY");
  <D.5635>:
  D.5636 = desc->in_use;
  D.5637 = D.5636 != 0;
  D.5638 = (long int) D.5637;
  D.5639 = __builtin_expect (D.5638, 0);
  if (D.5639 != 0) goto <D.5640>; else goto <D.5641>;
  <D.5640>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 239, "!desc->in_use");
  <D.5641>:
  <D.5433>:
  old_head = desc_avail;
  desc->next = old_head;
  mono_memory_write_barrier ();
  D.5642 = InterlockedCompareExchangePointer (&desc_avail, desc, old_head);
  if (D.5642 != old_head) goto <D.5433>; else goto <D.5434>;
  <D.5434>:
}


mono_memory_write_barrier ()
{
  mono_memory_barrier ();
}


mono_memory_barrier ()
{
  __sync_synchronize ();
}


free_sb (void * sb)
{
  long unsigned int sb.0;
  long unsigned int D.5644;
  void * D.5645;
  _Bool D.5646;
  long int D.5647;
  long int D.5648;
  void * sb_header;

  sb.0 = (long unsigned int) sb;
  D.5644 = sb.0 & 18446744073709535232;
  sb_header = (void *) D.5644;
  D.5645 = sb_header + 16;
  D.5646 = D.5645 != sb;
  D.5647 = (long int) D.5646;
  D.5648 = __builtin_expect (D.5647, 0);
  if (D.5648 != 0) goto <D.5649>; else goto <D.5650>;
  <D.5649>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 175, "(char*)sb_header + SB_HEADER_SIZE == sb");
  <D.5650>:
  mono_sgen_free_os_memory (sb_header, 16384);
}


mono_sgen_free_os_memory (void * addr, size_t size)
{
  mono_vfree (addr, size);
}


mono_memory_read_barrier ()
{
  mono_memory_barrier ();
}


set_anchor (struct Descriptor * desc, union Anchor old_anchor, union Anchor new_anchor)
{
  unsigned int D.5651;
  unsigned int D.5652;
  unsigned int D.5655;
  unsigned int D.5656;
  _Bool D.5657;
  long int D.5658;
  long int D.5659;
  gboolean D.5662;
  volatile gint32 * D.5663;
  int D.5664;
  int D.5665;
  int D.5666;
  _Bool D.5667;

  D.5651 = BIT_FIELD_REF <MEM[(void *)&old_anchor], 32, 0>;
  D.5652 = D.5651 & 3;
  if (D.5652 == 2) goto <D.5653>; else goto <D.5654>;
  <D.5653>:
  D.5655 = BIT_FIELD_REF <MEM[(void *)&new_anchor], 32, 0>;
  D.5656 = D.5655 & 3;
  D.5657 = D.5656 != 2;
  D.5658 = (long int) D.5657;
  D.5659 = __builtin_expect (D.5658, 0);
  if (D.5659 != 0) goto <D.5660>; else goto <D.5661>;
  <D.5660>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 349, "new_anchor.data.state == STATE_EMPTY");
  <D.5661>:
  <D.5654>:
  D.5663 = &desc->anchor.value;
  D.5664 = new_anchor.value;
  D.5665 = old_anchor.value;
  D.5666 = InterlockedCompareExchange (D.5663, D.5664, D.5665);
  D.5665 = old_anchor.value;
  D.5667 = D.5666 == D.5665;
  D.5662 = (gboolean) D.5667;
  return D.5662;
}


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

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


InterlockedCompareExchangePointer (void * volatile * dest, void * exch, void * comp)
{
  void * D.5674;
  long unsigned int comp.3;
  long unsigned int exch.4;
  long unsigned int D.5677;

  comp.3 = (long unsigned int) comp;
  exch.4 = (long unsigned int) exch;
  D.5677 = __sync_val_compare_and_swap_8 (dest, comp.3, exch.4);
  D.5674 = (void *) D.5677;
  return D.5674;
}


heap_put_partial (struct Descriptor * desc)
{
  list_put_partial (desc);
}


list_put_partial (struct Descriptor * desc)
{
  <unnamed-unsigned:2> D.5679;
  _Bool D.5680;
  long int D.5681;
  long int D.5682;

  D.5679 = desc->anchor.data.state;
  D.5680 = D.5679 == 0;
  D.5681 = (long int) D.5680;
  D.5682 = __builtin_expect (D.5681, 0);
  if (D.5682 != 0) goto <D.5683>; else goto <D.5684>;
  <D.5683>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 306, "desc->anchor.data.state != STATE_FULL");
  <D.5684>:
  mono_thread_hazardous_free_or_queue (desc, desc_put_partial, 0, 1);
}


desc_put_partial (void * _desc)
{
  <unnamed-unsigned:2> D.5685;
  _Bool D.5686;
  long int D.5687;
  long int D.5688;
  struct MonoLockFreeQueueNode * D.5691;
  struct MonoLockFreeAllocator * D.5692;
  struct MonoLockFreeAllocSizeClass * D.5693;
  struct MonoLockFreeQueue * D.5694;
  struct Descriptor * desc;

  desc = _desc;
  D.5685 = desc->anchor.data.state;
  D.5686 = D.5685 == 0;
  D.5687 = (long int) D.5686;
  D.5688 = __builtin_expect (D.5687, 0);
  if (D.5688 != 0) goto <D.5689>; else goto <D.5690>;
  <D.5689>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 297, "desc->anchor.data.state != STATE_FULL");
  <D.5690>:
  D.5691 = &desc->node;
  mono_lock_free_queue_node_free (D.5691);
  D.5692 = desc->heap;
  D.5693 = D.5692->sc;
  D.5694 = &D.5693->partial;
  D.5691 = &desc->node;
  mono_lock_free_queue_enqueue (D.5694, D.5691);
}


alloc_from_new_sb (struct MonoLockFreeAllocator * heap)
{
  void * D.5695;
  struct MonoLockFreeAllocSizeClass * D.5696;
  unsigned int D.5697;
  void * D.5698;
  unsigned int D.5699;
  sizetype D.5700;
  unsigned int * D.5701;
  unsigned int D.5702;
  unsigned int D.5703;
  unsigned int D.5704;
  short unsigned int D.5705;
  short unsigned int D.5706;
  <unnamed-unsigned:15> D.5707;
  struct _MonoLockFreeAllocDescriptor * * D.5708;
  void * D.5709;
  void * D.5712;
  unsigned int slot_size;
  unsigned int count;
  unsigned int i;
  struct Descriptor * desc;

  desc = desc_alloc ();
  D.5695 = alloc_sb (desc);
  desc->sb = D.5695;
  D.5696 = heap->sc;
  D.5697 = D.5696->slot_size;
  desc->slot_size = D.5697;
  slot_size = desc->slot_size;
  count = 16368 / slot_size;
  i = 1;
  goto <D.5486>;
  <D.5485>:
  D.5698 = desc->sb;
  D.5699 = i * slot_size;
  D.5700 = (sizetype) D.5699;
  D.5701 = D.5698 + D.5700;
  D.5702 = i + 1;
  *D.5701 = D.5702;
  i = i + 1;
  <D.5486>:
  D.5703 = count + 4294967295;
  if (D.5703 > i) goto <D.5485>; else goto <D.5487>;
  <D.5487>:
  desc->heap = heap;
  desc->anchor.data.avail = 1;
  D.5696 = heap->sc;
  D.5697 = D.5696->slot_size;
  desc->slot_size = D.5697;
  desc->max_count = count;
  D.5704 = desc->max_count;
  D.5705 = (short unsigned int) D.5704;
  D.5706 = D.5705 + 65535;
  D.5707 = (<unnamed-unsigned:15>) D.5706;
  desc->anchor.data.count = D.5707;
  desc->anchor.data.state = 1;
  mono_memory_write_barrier ();
  D.5708 = &heap->active;
  D.5709 = InterlockedCompareExchangePointer (D.5708, desc, 0B);
  if (D.5709 == 0B) goto <D.5710>; else goto <D.5711>;
  <D.5710>:
  D.5712 = desc->sb;
  return D.5712;
  <D.5711>:
  desc->anchor.data.state = 2;
  desc_retire (desc);
  D.5712 = 0B;
  return D.5712;
}


desc_alloc ()
{
  void * D.5716;
  _Bool D.5717;
  long unsigned int D.5719;
  struct Descriptor * iftmp.5;
  int D.5723;
  long unsigned int D.5724;
  long unsigned int D.5725;
  struct MonoLockFreeQueueNode * D.5727;
  struct Descriptor * D.5728;
  void * D.5729;
  _Bool D.5730;
  int D.5736;
  _Bool D.5737;
  long int D.5738;
  long int D.5739;
  struct Descriptor * D.5742;
  struct MonoThreadHazardPointers * hp;
  struct Descriptor * desc;

  hp = mono_hazard_pointer_get ();
  <D.5427>:
  {
    gboolean success;

    desc = get_hazardous_pointer (&desc_avail, hp, 1);
    if (desc != 0B) goto <D.5714>; else goto <D.5715>;
    <D.5714>:
    {
      struct Descriptor * next;

      next = desc->next;
      D.5716 = InterlockedCompareExchangePointer (&desc_avail, next, desc);
      D.5717 = D.5716 == desc;
      success = (gboolean) D.5717;
    }
    goto <D.5718>;
    <D.5715>:
    {
      size_t desc_size;
      struct Descriptor * d;
      int i;

      desc_size = 56;
      D.5719 = desc_size * 64;
      desc = mono_sgen_alloc_os_memory (D.5719, 1);
      d = desc;
      i = 0;
      goto <D.5424>;
      <D.5423>:
      {
        struct Descriptor * next;

        if (i != 63) goto <D.5721>; else goto <D.5722>;
        <D.5721>:
        D.5723 = i + 1;
        D.5724 = (long unsigned int) D.5723;
        D.5725 = D.5724 * desc_size;
        iftmp.5 = desc + D.5725;
        goto <D.5726>;
        <D.5722>:
        iftmp.5 = 0B;
        <D.5726>:
        next = iftmp.5;
        d->next = next;
        D.5727 = &d->node;
        mono_lock_free_queue_node_init (D.5727, 1);
        d = next;
      }
      i = i + 1;
      <D.5424>:
      if (i <= 63) goto <D.5423>; else goto <D.5425>;
      <D.5425>:
      mono_memory_write_barrier ();
      D.5728 = desc->next;
      D.5729 = InterlockedCompareExchangePointer (&desc_avail, D.5728, 0B);
      D.5730 = D.5729 == 0B;
      success = (gboolean) D.5730;
      if (success == 0) goto <D.5731>; else goto <D.5732>;
      <D.5731>:
      D.5719 = desc_size * 64;
      mono_sgen_free_os_memory (desc, D.5719);
      <D.5732>:
    }
    <D.5718>:
    if (0 != 0) goto <D.5733>; else goto <D.5734>;
    <D.5733>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 220, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
    <D.5734>:
    hp->hazard_pointers[1] = 0B;
    if (success != 0) goto <D.5426>; else goto <D.5735>;
    <D.5735>:
  }
  goto <D.5427>;
  <D.5426>:
  D.5736 = desc->in_use;
  D.5737 = D.5736 != 0;
  D.5738 = (long int) D.5737;
  D.5739 = __builtin_expect (D.5738, 0);
  if (D.5739 != 0) goto <D.5740>; else goto <D.5741>;
  <D.5740>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 226, "!desc->in_use");
  <D.5741>:
  desc->in_use = 1;
  D.5742 = desc;
  return D.5742;
}


mono_sgen_alloc_os_memory (size_t size, int activate)
{
  void * D.5744;
  long unsigned int D.5745;
  int D.5746;

  D.5745 = prot_flags_for_activate (activate);
  D.5746 = (int) D.5745;
  D.5744 = mono_valloc (0B, size, D.5746);
  return D.5744;
}


prot_flags_for_activate (int activate)
{
  long unsigned int iftmp.6;
  long unsigned int D.5752;
  long unsigned int prot_flags;

  if (activate != 0) goto <D.5749>; else goto <D.5750>;
  <D.5749>:
  iftmp.6 = 3;
  goto <D.5751>;
  <D.5750>:
  iftmp.6 = 0;
  <D.5751>:
  prot_flags = iftmp.6;
  D.5752 = prot_flags | 80;
  return D.5752;
}


alloc_sb (struct Descriptor * desc)
{
  long unsigned int sb_header.7;
  long unsigned int D.5755;
  void * D.5756;
  _Bool D.5757;
  long int D.5758;
  long int D.5759;
  struct Descriptor * * D.5762;
  void * D.5763;
  void * sb_header;

  sb_header = mono_sgen_alloc_os_memory_aligned (16384, 16384, 1);
  sb_header.7 = (long unsigned int) sb_header;
  D.5755 = sb_header.7 & 18446744073709535232;
  D.5756 = (void *) D.5755;
  D.5757 = D.5756 != sb_header;
  D.5758 = (long int) D.5757;
  D.5759 = __builtin_expect (D.5758, 0);
  if (D.5759 != 0) goto <D.5760>; else goto <D.5761>;
  <D.5760>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 165, "sb_header == SB_HEADER_FOR_ADDR (sb_header)");
  <D.5761>:
  sb_header.7 = (long unsigned int) sb_header;
  D.5755 = sb_header.7 & 18446744073709535232;
  D.5762 = (struct Descriptor * *) D.5755;
  *D.5762 = desc;
  D.5763 = sb_header + 16;
  return D.5763;
}


mono_sgen_alloc_os_memory_aligned (size_t size, size_t alignment, gboolean activate)
{
  void * D.5765;
  long unsigned int D.5766;
  int D.5767;

  D.5766 = prot_flags_for_activate (activate);
  D.5767 = (int) D.5766;
  D.5765 = mono_valloc_aligned (size, alignment, D.5767);
  return D.5765;
}


__attribute__((visibility ("hidden")))
mono_lock_free_free (void * ptr)
{
  long unsigned int ptr.8;
  long unsigned int D.5770;
  struct Descriptor * * D.5771;
  long unsigned int sb.9;
  long unsigned int D.5773;
  long unsigned int D.5774;
  _Bool D.5775;
  long int D.5776;
  long int D.5777;
  volatile gint32 * D.5780;
  <unnamed-unsigned:15> D.5781;
  unsigned int D.5782;
  long int ptr.10;
  long int sb.11;
  long int D.5785;
  unsigned int D.5786;
  long int D.5787;
  long int D.5788;
  short unsigned int D.5789;
  <unnamed-unsigned:15> D.5790;
  <unnamed-unsigned:15> D.5791;
  unsigned int D.5792;
  unsigned int D.5793;
  _Bool D.5794;
  long int D.5795;
  long int D.5796;
  unsigned int D.5799;
  unsigned int D.5800;
  <unnamed-unsigned:15> D.5803;
  <unnamed-unsigned:15> D.5804;
  unsigned int D.5805;
  unsigned int D.5806;
  int D.5809;
  unsigned int D.5810;
  unsigned int D.5811;
  _Bool D.5814;
  long int D.5815;
  long int D.5816;
  struct _MonoLockFreeAllocDescriptor * * D.5819;
  void * D.5820;
  struct MonoLockFreeAllocSizeClass * D.5824;
  _Bool D.5828;
  long int D.5829;
  long int D.5830;
  struct MonoLockFreeAllocator * D.5833;
  struct _MonoLockFreeAllocDescriptor * * D.5834;
  void * D.5835;
  union Anchor old_anchor;
  union Anchor new_anchor;
  struct Descriptor * desc;
  void * sb;
  struct MonoLockFreeAllocator * heap;

  try
    {
      heap = 0B;
      ptr.8 = (long unsigned int) ptr;
      D.5770 = ptr.8 & 18446744073709535232;
      D.5771 = (struct Descriptor * *) D.5770;
      desc = *D.5771;
      sb = desc->sb;
      ptr.8 = (long unsigned int) ptr;
      sb.9 = (long unsigned int) sb;
      D.5773 = ptr.8 ^ sb.9;
      D.5774 = D.5773 & 18446744073709535232;
      D.5775 = D.5774 != 0;
      D.5776 = (long int) D.5775;
      D.5777 = __builtin_expect (D.5776, 0);
      if (D.5777 != 0) goto <D.5778>; else goto <D.5779>;
      <D.5778>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 477, "SB_HEADER_FOR_ADDR (ptr) == SB_HEADER_FOR_ADDR (sb)");
      <D.5779>:
      <D.5502>:
      D.5780 = &desc->anchor.value;
      old_anchor = MEM[(volatile union Anchor *)D.5780];
      new_anchor = old_anchor;
      D.5781 = old_anchor.data.avail;
      D.5782 = (unsigned int) D.5781;
      MEM[(unsigned int *)ptr] = D.5782;
      ptr.10 = (long int) ptr;
      sb.11 = (long int) sb;
      D.5785 = ptr.10 - sb.11;
      D.5786 = desc->slot_size;
      D.5787 = (long int) D.5786;
      D.5788 = D.5785 / D.5787;
      D.5789 = (short unsigned int) D.5788;
      D.5790 = (<unnamed-unsigned:15>) D.5789;
      new_anchor.data.avail = D.5790;
      D.5791 = new_anchor.data.avail;
      D.5792 = (unsigned int) D.5791;
      D.5786 = desc->slot_size;
      D.5793 = 16368 / D.5786;
      D.5794 = D.5792 >= D.5793;
      D.5795 = (long int) D.5794;
      D.5796 = __builtin_expect (D.5795, 0);
      if (D.5796 != 0) goto <D.5797>; else goto <D.5798>;
      <D.5797>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 483, "new_anchor.data.avail < SB_USABLE_SIZE / desc->slot_size");
      <D.5798>:
      D.5799 = BIT_FIELD_REF <MEM[(void *)&old_anchor], 32, 0>;
      D.5800 = D.5799 & 3;
      if (D.5800 == 0) goto <D.5801>; else goto <D.5802>;
      <D.5801>:
      new_anchor.data.state = 1;
      <D.5802>:
      D.5803 = new_anchor.data.count;
      D.5804 = D.5803 + 1;
      new_anchor.data.count = D.5804;
      D.5803 = new_anchor.data.count;
      D.5805 = (unsigned int) D.5803;
      D.5806 = desc->max_count;
      if (D.5805 == D.5806) goto <D.5807>; else goto <D.5808>;
      <D.5807>:
      heap = desc->heap;
      new_anchor.data.state = 2;
      <D.5808>:
      D.5809 = set_anchor (desc, old_anchor, new_anchor);
      if (D.5809 == 0) goto <D.5502>; else goto <D.5503>;
      <D.5503>:
      D.5810 = BIT_FIELD_REF <MEM[(void *)&new_anchor], 32, 0>;
      D.5811 = D.5810 & 3;
      if (D.5811 == 2) goto <D.5812>; else goto <D.5813>;
      <D.5812>:
      D.5799 = BIT_FIELD_REF <MEM[(void *)&old_anchor], 32, 0>;
      D.5800 = D.5799 & 3;
      D.5814 = D.5800 == 2;
      D.5815 = (long int) D.5814;
      D.5816 = __builtin_expect (D.5815, 0);
      if (D.5816 != 0) goto <D.5817>; else goto <D.5818>;
      <D.5817>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 495, "old_anchor.data.state != STATE_EMPTY");
      <D.5818>:
      D.5819 = &heap->active;
      D.5820 = InterlockedCompareExchangePointer (D.5819, 0B, desc);
      if (D.5820 == desc) goto <D.5821>; else goto <D.5822>;
      <D.5821>:
      desc_retire (desc);
      goto <D.5823>;
      <D.5822>:
      D.5824 = heap->sc;
      list_remove_empty_desc (D.5824);
      <D.5823>:
      goto <D.5825>;
      <D.5813>:
      D.5799 = BIT_FIELD_REF <MEM[(void *)&old_anchor], 32, 0>;
      D.5800 = D.5799 & 3;
      if (D.5800 == 0) goto <D.5826>; else goto <D.5827>;
      <D.5826>:
      D.5810 = BIT_FIELD_REF <MEM[(void *)&new_anchor], 32, 0>;
      D.5811 = D.5810 & 3;
      D.5828 = D.5811 != 1;
      D.5829 = (long int) D.5828;
      D.5830 = __builtin_expect (D.5829, 0);
      if (D.5830 != 0) goto <D.5831>; else goto <D.5832>;
      <D.5831>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 513, "new_anchor.data.state == STATE_PARTIAL");
      <D.5832>:
      D.5833 = desc->heap;
      D.5834 = &D.5833->active;
      D.5835 = InterlockedCompareExchangePointer (D.5834, desc, 0B);
      if (D.5835 != 0B) goto <D.5836>; else goto <D.5837>;
      <D.5836>:
      heap_put_partial (desc);
      <D.5837>:
      <D.5827>:
      <D.5825>:
    }
  finally
    {
      old_anchor = {CLOBBER};
      new_anchor = {CLOBBER};
    }
}


list_remove_empty_desc (struct MonoLockFreeAllocSizeClass * sc)
{
  struct MonoLockFreeQueue * D.5838;
  <unnamed-unsigned:2> D.5841;
  struct MonoLockFreeAllocator * D.5845;
  struct MonoLockFreeAllocSizeClass * D.5846;
  _Bool D.5847;
  long int D.5848;
  long int D.5849;
  int num_non_empty;

  num_non_empty = 0;
  <D.5455>:
  {
    struct Descriptor * desc;

    D.5838 = &sc->partial;
    desc = mono_lock_free_queue_dequeue (D.5838);
    if (desc == 0B) goto <D.5839>; else goto <D.5840>;
    <D.5839>:
    return;
    <D.5840>:
    D.5841 = desc->anchor.data.state;
    if (D.5841 == 2) goto <D.5842>; else goto <D.5843>;
    <D.5842>:
    desc_retire (desc);
    goto <D.5844>;
    <D.5843>:
    D.5845 = desc->heap;
    D.5846 = D.5845->sc;
    D.5847 = D.5846 != sc;
    D.5848 = (long int) D.5847;
    D.5849 = __builtin_expect (D.5848, 0);
    if (D.5849 != 0) goto <D.5850>; else goto <D.5851>;
    <D.5850>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 325, "desc->heap->sc == sc");
    <D.5851>:
    mono_thread_hazardous_free_or_queue (desc, desc_put_partial, 0, 1);
    num_non_empty = num_non_empty + 1;
    if (num_non_empty > 1) goto <D.5852>; else goto <D.5853>;
    <D.5852>:
    return;
    <D.5853>:
    <D.5844>:
  }
  goto <D.5455>;
}


__attribute__((visibility ("hidden")))
mono_lock_free_allocator_check_consistency (struct MonoLockFreeAllocator * heap)
{
  <unnamed-unsigned:2> D.5857;
  _Bool D.5858;
  long int D.5859;
  long int D.5860;
  int iftmp.12;
  <unnamed-unsigned:2> D.5866;
  <unnamed-unsigned:2> D.5868;
  _Bool D.5870;
  long int D.5871;
  long int D.5872;
  struct MonoLockFreeAllocSizeClass * D.5875;
  struct MonoLockFreeQueue * D.5876;
  gboolean D.5877;
  struct Descriptor * active;
  struct Descriptor * desc;

  active = heap->active;
  if (active != 0B) goto <D.5855>; else goto <D.5856>;
  <D.5855>:
  D.5857 = active->anchor.data.state;
  D.5858 = D.5857 != 1;
  D.5859 = (long int) D.5858;
  D.5860 = __builtin_expect (D.5859, 0);
  if (D.5860 != 0) goto <D.5861>; else goto <D.5862>;
  <D.5861>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 599, "active->anchor.data.state == STATE_PARTIAL");
  <D.5862>:
  descriptor_check_consistency (active, 0);
  <D.5856>:
  goto <D.5536>;
  <D.5535>:
  D.5866 = desc->anchor.data.state;
  if (D.5866 != 1) goto <D.5867>; else goto <D.5864>;
  <D.5867>:
  D.5868 = desc->anchor.data.state;
  if (D.5868 != 2) goto <D.5869>; else goto <D.5864>;
  <D.5869>:
  iftmp.12 = 1;
  goto <D.5865>;
  <D.5864>:
  iftmp.12 = 0;
  <D.5865>:
  D.5870 = iftmp.12 != 0;
  D.5871 = (long int) D.5870;
  D.5872 = __builtin_expect (D.5871, 0);
  if (D.5872 != 0) goto <D.5873>; else goto <D.5874>;
  <D.5873>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 603, "desc->anchor.data.state == STATE_PARTIAL || desc->anchor.data.state == STATE_EMPTY");
  <D.5874>:
  descriptor_check_consistency (desc, 0);
  <D.5536>:
  D.5875 = heap->sc;
  D.5876 = &D.5875->partial;
  desc = mono_lock_free_queue_dequeue (D.5876);
  if (desc != 0B) goto <D.5535>; else goto <D.5537>;
  <D.5537>:
  D.5877 = 1;
  return D.5877;
}


descriptor_check_consistency (struct Descriptor * desc, gboolean print)
{
  <unnamed-unsigned:15> D.5879;
  unsigned int D.5880;
  unsigned int D.5881;
  int max_count.13;
  long int D.5883;
  long int D.5884;
  sizetype D.5885;
  sizetype D.5886;
  bitsizetype D.5887;
  bitsizetype D.5888;
  sizetype D.5889;
  gboolean[0:D.5885] * linked.14;
  struct MonoLockFreeAllocator * D.5898;
  struct MonoLockFreeAllocSizeClass * D.5899;
  unsigned int D.5900;
  <unnamed-unsigned:2> D.5910;
  int D.5911;
  <unnamed-unsigned:15> D.5946;
  void * D.5947;
  unsigned int D.5948;
  sizetype D.5949;
  unsigned int max_count.15;
  int D.5958;
  void * saved_stack.16;
  int count;
  int max_count;
  gboolean linked[0:D.5885] [value-expr: *linked.14];
  int i;
  int last;
  unsigned int index;
  struct Descriptor * avail;

  saved_stack.16 = __builtin_stack_save ();
  try
    {
      D.5879 = desc->anchor.data.count;
      count = (int) D.5879;
      D.5880 = desc->slot_size;
      D.5881 = 16368 / D.5880;
      max_count = (int) D.5881;
      max_count.13 = max_count;
      D.5883 = (long int) max_count.13;
      D.5884 = D.5883 + -1;
      D.5885 = (sizetype) D.5884;
      D.5886 = (sizetype) max_count.13;
      D.5887 = (bitsizetype) D.5886;
      D.5888 = D.5887 * 32;
      D.5886 = (sizetype) max_count.13;
      D.5889 = D.5886 * 4;
      D.5886 = (sizetype) max_count.13;
      D.5887 = (bitsizetype) D.5886;
      D.5888 = D.5887 * 32;
      D.5886 = (sizetype) max_count.13;
      D.5889 = D.5886 * 4;
      linked.14 = __builtin_alloca_with_align (D.5889, 32);
      avail = desc_avail;
      goto <D.5516>;
      <D.5515>:
      if (desc == avail) goto <D.5891>; else goto <D.5892>;
      <D.5891>:
      if (print != 0) goto <D.5893>; else goto <D.5894>;
      <D.5893>:
      monoeg_g_print ("descriptor is in the available list\n");
      goto <D.5895>;
      <D.5894>:
      if (1 != 0) goto <D.5896>; else goto <D.5897>;
      <D.5896>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 546, "FALSE");
      <D.5897>:
      <D.5895>:
      <D.5892>:
      avail = avail->next;
      <D.5516>:
      if (avail != 0B) goto <D.5515>; else goto <D.5517>;
      <D.5517>:
      D.5880 = desc->slot_size;
      D.5898 = desc->heap;
      D.5899 = D.5898->sc;
      D.5900 = D.5899->slot_size;
      if (D.5880 != D.5900) goto <D.5901>; else goto <D.5902>;
      <D.5901>:
      if (print != 0) goto <D.5903>; else goto <D.5904>;
      <D.5903>:
      monoeg_g_print ("slot size doesn\'t match size class\n");
      goto <D.5905>;
      <D.5904>:
      if (1 != 0) goto <D.5906>; else goto <D.5907>;
      <D.5906>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 549, "FALSE");
      <D.5907>:
      <D.5905>:
      <D.5902>:
      if (print != 0) goto <D.5908>; else goto <D.5909>;
      <D.5908>:
      monoeg_g_print ("descriptor %p is ", desc);
      <D.5909>:
      D.5910 = desc->anchor.data.state;
      D.5911 = (int) D.5910;
      switch (D.5911) <default: <D.5522>, case 0: <D.5518>, case 1: <D.5520>, case 2: <D.5521>>
      <D.5518>:
      if (print != 0) goto <D.5912>; else goto <D.5913>;
      <D.5912>:
      monoeg_g_print ("full\n");
      <D.5913>:
      if (count != 0) goto <D.5914>; else goto <D.5915>;
      <D.5914>:
      if (print != 0) goto <D.5916>; else goto <D.5917>;
      <D.5916>:
      monoeg_g_print ("count is not zero: %d\n", count);
      goto <D.5918>;
      <D.5917>:
      if (1 != 0) goto <D.5919>; else goto <D.5920>;
      <D.5919>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 558, "FALSE");
      <D.5920>:
      <D.5918>:
      <D.5915>:
      goto <D.5519>;
      <D.5520>:
      if (print != 0) goto <D.5921>; else goto <D.5922>;
      <D.5921>:
      monoeg_g_print ("partial\n");
      <D.5922>:
      if (count >= max_count) goto <D.5923>; else goto <D.5924>;
      <D.5923>:
      if (print != 0) goto <D.5925>; else goto <D.5926>;
      <D.5925>:
      monoeg_g_print ("count too high: is %d but must be below %d\n", count, max_count);
      goto <D.5927>;
      <D.5926>:
      if (1 != 0) goto <D.5928>; else goto <D.5929>;
      <D.5928>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 563, "FALSE");
      <D.5929>:
      <D.5927>:
      <D.5924>:
      goto <D.5519>;
      <D.5521>:
      if (print != 0) goto <D.5930>; else goto <D.5931>;
      <D.5930>:
      monoeg_g_print ("empty\n");
      <D.5931>:
      if (count != max_count) goto <D.5932>; else goto <D.5933>;
      <D.5932>:
      if (print != 0) goto <D.5934>; else goto <D.5935>;
      <D.5934>:
      monoeg_g_print ("count is wrong: is %d but should be %d\n", count, max_count);
      goto <D.5936>;
      <D.5935>:
      if (1 != 0) goto <D.5937>; else goto <D.5938>;
      <D.5937>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 568, "FALSE");
      <D.5938>:
      <D.5936>:
      <D.5933>:
      goto <D.5519>;
      <D.5522>:
      if (1 != 0) goto <D.5939>; else goto <D.5940>;
      <D.5939>:
      if (print != 0) goto <D.5941>; else goto <D.5942>;
      <D.5941>:
      monoeg_g_print ("invalid state\n");
      goto <D.5943>;
      <D.5942>:
      if (1 != 0) goto <D.5944>; else goto <D.5945>;
      <D.5944>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 571, "FALSE");
      <D.5945>:
      <D.5943>:
      <D.5940>:
      <D.5519>:
      i = 0;
      goto <D.5524>;
      <D.5523>:
      *linked.14[i] = 0;
      i = i + 1;
      <D.5524>:
      if (i < max_count) goto <D.5523>; else goto <D.5525>;
      <D.5525>:
      D.5946 = desc->anchor.data.avail;
      index = (unsigned int) D.5946;
      last = -1;
      i = 0;
      goto <D.5529>;
      <D.5528>:
      {
        void * addr;

        D.5947 = desc->sb;
        D.5880 = desc->slot_size;
        D.5948 = D.5880 * index;
        D.5949 = (sizetype) D.5948;
        addr = D.5947 + D.5949;
        max_count.15 = (unsigned int) max_count;
        if (index >= max_count.15) goto <D.5951>; else goto <D.5952>;
        <D.5951>:
        if (print != 0) goto <D.5953>; else goto <D.5954>;
        <D.5953>:
        monoeg_g_print ("index %d for %dth available slot, linked from %d, not in range [0 .. %d)\n", index, i, last, max_count);
        goto <D.5955>;
        <D.5954>:
        if (1 != 0) goto <D.5956>; else goto <D.5957>;
        <D.5956>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 583, "FALSE");
        <D.5957>:
        <D.5955>:
        <D.5952>:
        D.5958 = *linked.14[index];
        if (D.5958 != 0) goto <D.5959>; else goto <D.5960>;
        <D.5959>:
        if (print != 0) goto <D.5961>; else goto <D.5962>;
        <D.5961>:
        monoeg_g_print ("%dth available slot %d linked twice\n", i, index);
        goto <D.5963>;
        <D.5962>:
        if (1 != 0) goto <D.5964>; else goto <D.5965>;
        <D.5964>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 584, "FALSE");
        <D.5965>:
        <D.5963>:
        <D.5960>:
        D.5958 = *linked.14[index];
        if (D.5958 != 0) goto <D.5527>; else goto <D.5966>;
        <D.5966>:
        *linked.14[index] = 1;
        last = (int) index;
        index = MEM[(unsigned int *)addr];
      }
      i = i + 1;
      <D.5529>:
      if (i < count) goto <D.5528>; else goto <D.5527>;
      <D.5527>:
    }
  finally
    {
      __builtin_stack_restore (saved_stack.16);
    }
}


__attribute__((visibility ("hidden")))
mono_lock_free_allocator_init_size_class (struct MonoLockFreeAllocSizeClass * sc, unsigned int slot_size)
{
  _Bool D.5969;
  long int D.5970;
  long int D.5971;
  struct MonoLockFreeQueue * D.5974;

  D.5969 = slot_size > 8184;
  D.5970 = (long int) D.5969;
  D.5971 = __builtin_expect (D.5970, 0);
  if (D.5971 != 0) goto <D.5972>; else goto <D.5973>;
  <D.5972>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 612, "slot_size <= SB_USABLE_SIZE / 2");
  <D.5973>:
  D.5974 = &sc->partial;
  mono_lock_free_queue_init (D.5974);
  sc->slot_size = slot_size;
}


__attribute__((visibility ("hidden")))
mono_lock_free_allocator_init_allocator (struct MonoLockFreeAllocator * heap, struct MonoLockFreeAllocSizeClass * sc)
{
  heap->sc = sc;
  heap->active = 0B;
}


