mono_lock_free_alloc (struct MonoLockFreeAllocator * heap)
{
  void * D.5032;
  void * addr;

  <D.4976>:
  addr = alloc_from_active_or_partial (heap);
  if (addr != 0B) goto <D.4975>; else goto <D.5030>;
  <D.5030>:
  addr = alloc_from_new_sb (heap);
  if (addr != 0B) goto <D.4975>; else goto <D.5031>;
  <D.5031>:
  goto <D.4976>;
  <D.4975>:
  D.5032 = addr;
  return D.5032;
}


alloc_from_active_or_partial (struct MonoLockFreeAllocator * heap)
{
  struct _MonoLockFreeAllocDescriptor * * D.5036;
  void * D.5037;
  void * D.5042;
  volatile gint32 * D.5043;
  unsigned char D.5044;
  unsigned char D.5045;
  _Bool D.5048;
  long int D.5049;
  long int D.5050;
  <unnamed-unsigned:15> D.5053;
  int D.5054;
  _Bool D.5055;
  long int D.5056;
  long int D.5057;
  void * D.5060;
  <unnamed-unsigned:15> D.5061;
  unsigned int D.5062;
  unsigned int D.5063;
  unsigned int D.5064;
  unsigned int D.5065;
  _Bool D.5066;
  long int D.5067;
  long int D.5068;
  short unsigned int D.5071;
  <unnamed-unsigned:15> D.5072;
  <unnamed-unsigned:15> D.5073;
  <unnamed-unsigned:15> D.5074;
  unsigned int D.5075;
  unsigned int D.5076;
  int D.5079;
  unsigned char D.5080;
  unsigned char D.5081;
  void * D.5084;
  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.5034>; else goto <D.5035>;
      <D.5034>:
      D.5036 = &heap->active;
      D.5037 = InterlockedCompareExchangePointer (D.5036, 0B, desc);
      if (D.5037 != desc) goto retry; else goto <D.5038>;
      <D.5038>:
      goto <D.5039>;
      <D.5035>:
      desc = heap_get_partial (heap);
      if (desc == 0B) goto <D.5040>; else goto <D.5041>;
      <D.5040>:
      D.5042 = 0B;
      return D.5042;
      <D.5041>:
      <D.5039>:
      <D.4959>:
      {
        unsigned int next;

        D.5043 = &desc->anchor.value;
        old_anchor = MEM[(volatile union Anchor *)D.5043];
        new_anchor = old_anchor;
        D.5044 = BIT_FIELD_REF <old_anchor, 8, 24>;
        D.5045 = D.5044 & 192;
        if (D.5045 == 128) goto <D.5046>; else goto <D.5047>;
        <D.5046>:
        desc_retire (desc);
        goto retry;
        <D.5047>:
        D.5044 = BIT_FIELD_REF <old_anchor, 8, 24>;
        D.5045 = D.5044 & 192;
        D.5048 = D.5045 != 64;
        D.5049 = (long int) D.5048;
        D.5050 = __builtin_expect (D.5049, 0);
        if (D.5050 != 0) goto <D.5051>; else goto <D.5052>;
        <D.5051>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 383, "old_anchor.data.state == STATE_PARTIAL");
        <D.5052>:
        D.5053 = old_anchor.data.count;
        D.5054 = (int) D.5053;
        D.5055 = D.5054 <= 0;
        D.5056 = (long int) D.5055;
        D.5057 = __builtin_expect (D.5056, 0);
        if (D.5057 != 0) goto <D.5058>; else goto <D.5059>;
        <D.5058>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 384, "old_anchor.data.count > 0");
        <D.5059>:
        D.5060 = desc->sb;
        D.5061 = old_anchor.data.avail;
        D.5062 = (unsigned int) D.5061;
        D.5063 = desc->slot_size;
        D.5064 = D.5062 * D.5063;
        addr = D.5060 + D.5064;
        mono_memory_read_barrier ();
        next = MEM[(unsigned int *)addr];
        D.5063 = desc->slot_size;
        D.5065 = 16368 / D.5063;
        D.5066 = D.5065 <= next;
        D.5067 = (long int) D.5066;
        D.5068 = __builtin_expect (D.5067, 0);
        if (D.5068 != 0) goto <D.5069>; else goto <D.5070>;
        <D.5069>:
        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.5070>:
        D.5071 = (short unsigned int) next;
        D.5072 = (<unnamed-unsigned:15>) D.5071;
        new_anchor.data.avail = D.5072;
        D.5073 = new_anchor.data.count;
        D.5074 = D.5073 + 32767;
        new_anchor.data.count = D.5074;
        D.5075 = BIT_FIELD_REF <new_anchor, 32, 0>;
        D.5076 = D.5075 & 1073709056;
        if (D.5076 == 0) goto <D.5077>; else goto <D.5078>;
        <D.5077>:
        new_anchor.data.state = 0;
        <D.5078>:
      }
      D.5079 = set_anchor (desc, old_anchor, new_anchor);
      if (D.5079 == 0) goto <D.4959>; else goto <D.4960>;
      <D.4960>:
      D.5080 = BIT_FIELD_REF <new_anchor, 8, 24>;
      D.5081 = D.5080 & 192;
      if (D.5081 == 64) goto <D.5082>; else goto <D.5083>;
      <D.5082>:
      D.5036 = &heap->active;
      D.5084 = InterlockedCompareExchangePointer (D.5036, desc, 0B);
      if (D.5084 != 0B) goto <D.5085>; else goto <D.5086>;
      <D.5085>:
      heap_put_partial (desc);
      <D.5086>:
      <D.5083>:
      D.5042 = addr;
      return D.5042;
    }
  finally
    {
      old_anchor = {CLOBBER};
      new_anchor = {CLOBBER};
    }
}


heap_get_partial (struct MonoLockFreeAllocator * heap)
{
  struct Descriptor * D.5089;
  struct MonoLockFreeAllocSizeClass * D.5090;

  D.5090 = heap->sc;
  D.5089 = list_get_partial (D.5090);
  return D.5089;
}


list_get_partial (struct MonoLockFreeAllocSizeClass * sc)
{
  struct MonoLockFreeQueue * D.5092;
  struct Descriptor * D.5095;
  <unnamed-unsigned:2> D.5096;

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

    D.5092 = &sc->partial;
    desc = mono_lock_free_queue_dequeue (D.5092);
    if (desc == 0B) goto <D.5093>; else goto <D.5094>;
    <D.5093>:
    D.5095 = 0B;
    return D.5095;
    <D.5094>:
    D.5096 = desc->anchor.data.state;
    if (D.5096 != 2) goto <D.5097>; else goto <D.5098>;
    <D.5097>:
    D.5095 = desc;
    return D.5095;
    <D.5098>:
    desc_retire (desc);
  }
  goto <D.4925>;
}


desc_retire (struct Descriptor * desc)
{
  <unnamed-unsigned:2> D.5100;
  _Bool D.5101;
  long int D.5102;
  long int D.5103;
  int D.5106;
  _Bool D.5107;
  long int D.5108;
  long int D.5109;
  void * D.5112;

  D.5100 = desc->anchor.data.state;
  D.5101 = D.5100 != 2;
  D.5102 = (long int) D.5101;
  D.5103 = __builtin_expect (D.5102, 0);
  if (D.5103 != 0) goto <D.5104>; else goto <D.5105>;
  <D.5104>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 251, "desc->anchor.data.state == STATE_EMPTY");
  <D.5105>:
  D.5106 = desc->in_use;
  D.5107 = D.5106 == 0;
  D.5108 = (long int) D.5107;
  D.5109 = __builtin_expect (D.5108, 0);
  if (D.5109 != 0) goto <D.5110>; else goto <D.5111>;
  <D.5110>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 252, "desc->in_use");
  <D.5111>:
  desc->in_use = 0;
  D.5112 = desc->sb;
  free_sb (D.5112);
  mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, 0, 1);
}


desc_enqueue_avail (void * _desc)
{
  <unnamed-unsigned:2> D.5113;
  _Bool D.5114;
  long int D.5115;
  long int D.5116;
  int D.5119;
  _Bool D.5120;
  long int D.5121;
  long int D.5122;
  void * D.5125;
  struct Descriptor * desc;
  struct Descriptor * old_head;

  desc = _desc;
  D.5113 = desc->anchor.data.state;
  D.5114 = D.5113 != 2;
  D.5115 = (long int) D.5114;
  D.5116 = __builtin_expect (D.5115, 0);
  if (D.5116 != 0) goto <D.5117>; else goto <D.5118>;
  <D.5117>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 238, "desc->anchor.data.state == STATE_EMPTY");
  <D.5118>:
  D.5119 = desc->in_use;
  D.5120 = D.5119 != 0;
  D.5121 = (long int) D.5120;
  D.5122 = __builtin_expect (D.5121, 0);
  if (D.5122 != 0) goto <D.5123>; else goto <D.5124>;
  <D.5123>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 239, "!desc->in_use");
  <D.5124>:
  <D.4916>:
  old_head = desc_avail;
  desc->next = old_head;
  mono_memory_write_barrier ();
  D.5125 = InterlockedCompareExchangePointer (&desc_avail, desc, old_head);
  if (D.5125 != old_head) goto <D.4916>; else goto <D.4917>;
  <D.4917>:
}


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.5127;
  void * D.5128;
  _Bool D.5129;
  long int D.5130;
  long int D.5131;
  void * sb_header;

  sb.0 = (long unsigned int) sb;
  D.5127 = sb.0 & 4294950912;
  sb_header = (void *) D.5127;
  D.5128 = sb_header + 16;
  D.5129 = D.5128 != sb;
  D.5130 = (long int) D.5129;
  D.5131 = __builtin_expect (D.5130, 0);
  if (D.5131 != 0) goto <D.5132>; else goto <D.5133>;
  <D.5132>:
  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.5133>:
  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 char D.5134;
  unsigned char D.5135;
  unsigned char D.5138;
  unsigned char D.5139;
  _Bool D.5140;
  long int D.5141;
  long int D.5142;
  gboolean D.5145;
  int D.5146;
  int D.5147;
  volatile gint32 * D.5148;
  int D.5149;
  _Bool D.5150;

  D.5134 = BIT_FIELD_REF <old_anchor, 8, 24>;
  D.5135 = D.5134 & 192;
  if (D.5135 == 128) goto <D.5136>; else goto <D.5137>;
  <D.5136>:
  D.5138 = BIT_FIELD_REF <new_anchor, 8, 24>;
  D.5139 = D.5138 & 192;
  D.5140 = D.5139 != 128;
  D.5141 = (long int) D.5140;
  D.5142 = __builtin_expect (D.5141, 0);
  if (D.5142 != 0) goto <D.5143>; else goto <D.5144>;
  <D.5143>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 349, "new_anchor.data.state == STATE_EMPTY");
  <D.5144>:
  <D.5137>:
  D.5146 = old_anchor.value;
  D.5147 = new_anchor.value;
  D.5148 = &desc->anchor.value;
  D.5149 = InterlockedCompareExchange (D.5148, D.5147, D.5146);
  D.5146 = old_anchor.value;
  D.5150 = D.5149 == D.5146;
  D.5145 = (gboolean) D.5150;
  return D.5145;
}


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

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


InterlockedCompareExchangePointer (void * volatile * dest, void * exch, void * comp)
{
  void * D.5157;
  unsigned int exch.3;
  unsigned int comp.4;
  unsigned int D.5160;

  exch.3 = (unsigned int) exch;
  comp.4 = (unsigned int) comp;
  D.5160 = __sync_val_compare_and_swap_4 (dest, comp.4, exch.3);
  D.5157 = (void *) D.5160;
  return D.5157;
}


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


list_put_partial (struct Descriptor * desc)
{
  <unnamed-unsigned:2> D.5162;
  _Bool D.5163;
  long int D.5164;
  long int D.5165;

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


desc_put_partial (void * _desc)
{
  <unnamed-unsigned:2> D.5168;
  _Bool D.5169;
  long int D.5170;
  long int D.5171;
  struct MonoLockFreeQueueNode * D.5174;
  struct MonoLockFreeAllocator * D.5175;
  struct MonoLockFreeAllocSizeClass * D.5176;
  struct MonoLockFreeQueue * D.5177;
  struct Descriptor * desc;

  desc = _desc;
  D.5168 = desc->anchor.data.state;
  D.5169 = D.5168 == 0;
  D.5170 = (long int) D.5169;
  D.5171 = __builtin_expect (D.5170, 0);
  if (D.5171 != 0) goto <D.5172>; else goto <D.5173>;
  <D.5172>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 297, "desc->anchor.data.state != STATE_FULL");
  <D.5173>:
  D.5174 = &desc->node;
  mono_lock_free_queue_node_free (D.5174);
  D.5174 = &desc->node;
  D.5175 = desc->heap;
  D.5176 = D.5175->sc;
  D.5177 = &D.5176->partial;
  mono_lock_free_queue_enqueue (D.5177, D.5174);
}


alloc_from_new_sb (struct MonoLockFreeAllocator * heap)
{
  void * D.5178;
  struct MonoLockFreeAllocSizeClass * D.5179;
  unsigned int D.5180;
  void * D.5181;
  unsigned int D.5182;
  unsigned int * D.5183;
  unsigned int D.5184;
  unsigned int D.5185;
  unsigned int D.5186;
  short unsigned int D.5187;
  short unsigned int D.5188;
  <unnamed-unsigned:15> D.5189;
  struct _MonoLockFreeAllocDescriptor * * D.5190;
  void * D.5191;
  void * D.5194;
  unsigned int slot_size;
  unsigned int count;
  unsigned int i;
  struct Descriptor * desc;

  desc = desc_alloc ();
  D.5178 = alloc_sb (desc);
  desc->sb = D.5178;
  D.5179 = heap->sc;
  D.5180 = D.5179->slot_size;
  desc->slot_size = D.5180;
  slot_size = desc->slot_size;
  count = 16368 / slot_size;
  i = 1;
  goto <D.4969>;
  <D.4968>:
  D.5181 = desc->sb;
  D.5182 = i * slot_size;
  D.5183 = D.5181 + D.5182;
  D.5184 = i + 1;
  *D.5183 = D.5184;
  i = i + 1;
  <D.4969>:
  D.5185 = count + 4294967295;
  if (D.5185 > i) goto <D.4968>; else goto <D.4970>;
  <D.4970>:
  desc->heap = heap;
  desc->anchor.data.avail = 1;
  D.5179 = heap->sc;
  D.5180 = D.5179->slot_size;
  desc->slot_size = D.5180;
  desc->max_count = count;
  D.5186 = desc->max_count;
  D.5187 = (short unsigned int) D.5186;
  D.5188 = D.5187 + 65535;
  D.5189 = (<unnamed-unsigned:15>) D.5188;
  desc->anchor.data.count = D.5189;
  desc->anchor.data.state = 1;
  mono_memory_write_barrier ();
  D.5190 = &heap->active;
  D.5191 = InterlockedCompareExchangePointer (D.5190, desc, 0B);
  if (D.5191 == 0B) goto <D.5192>; else goto <D.5193>;
  <D.5192>:
  D.5194 = desc->sb;
  return D.5194;
  <D.5193>:
  desc->anchor.data.state = 2;
  desc_retire (desc);
  D.5194 = 0B;
  return D.5194;
}


desc_alloc ()
{
  void * D.5198;
  _Bool D.5199;
  unsigned int D.5201;
  struct Descriptor * iftmp.5;
  int D.5205;
  unsigned int D.5206;
  unsigned int D.5207;
  struct MonoLockFreeQueueNode * D.5209;
  struct Descriptor * D.5210;
  void * D.5211;
  _Bool D.5212;
  int D.5218;
  _Bool D.5219;
  long int D.5220;
  long int D.5221;
  struct Descriptor * D.5224;
  struct MonoThreadHazardPointers * hp;
  struct Descriptor * desc;

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

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

      next = desc->next;
      D.5198 = InterlockedCompareExchangePointer (&desc_avail, next, desc);
      D.5199 = D.5198 == desc;
      success = (gboolean) D.5199;
    }
    goto <D.5200>;
    <D.5197>:
    {
      size_t desc_size;
      struct Descriptor * d;
      int i;

      desc_size = 32;
      D.5201 = desc_size * 64;
      desc = mono_sgen_alloc_os_memory (D.5201, 1);
      d = desc;
      i = 0;
      goto <D.4907>;
      <D.4906>:
      {
        struct Descriptor * next;

        if (i != 63) goto <D.5203>; else goto <D.5204>;
        <D.5203>:
        D.5205 = i + 1;
        D.5206 = (unsigned int) D.5205;
        D.5207 = D.5206 * desc_size;
        iftmp.5 = desc + D.5207;
        goto <D.5208>;
        <D.5204>:
        iftmp.5 = 0B;
        <D.5208>:
        next = iftmp.5;
        d->next = next;
        D.5209 = &d->node;
        mono_lock_free_queue_node_init (D.5209, 1);
        d = next;
      }
      i = i + 1;
      <D.4907>:
      if (i <= 63) goto <D.4906>; else goto <D.4908>;
      <D.4908>:
      mono_memory_write_barrier ();
      D.5210 = desc->next;
      D.5211 = InterlockedCompareExchangePointer (&desc_avail, D.5210, 0B);
      D.5212 = D.5211 == 0B;
      success = (gboolean) D.5212;
      if (success == 0) goto <D.5213>; else goto <D.5214>;
      <D.5213>:
      D.5201 = desc_size * 64;
      mono_sgen_free_os_memory (desc, D.5201);
      <D.5214>:
    }
    <D.5200>:
    if (0 != 0) goto <D.5215>; else goto <D.5216>;
    <D.5215>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 220, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
    <D.5216>:
    hp->hazard_pointers[1] = 0B;
    if (success != 0) goto <D.4909>; else goto <D.5217>;
    <D.5217>:
  }
  goto <D.4910>;
  <D.4909>:
  D.5218 = desc->in_use;
  D.5219 = D.5218 != 0;
  D.5220 = (long int) D.5219;
  D.5221 = __builtin_expect (D.5220, 0);
  if (D.5221 != 0) goto <D.5222>; else goto <D.5223>;
  <D.5222>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 226, "!desc->in_use");
  <D.5223>:
  desc->in_use = 1;
  D.5224 = desc;
  return D.5224;
}


mono_sgen_alloc_os_memory (size_t size, int activate)
{
  void * D.5226;
  long unsigned int D.5227;
  int D.5228;

  D.5227 = prot_flags_for_activate (activate);
  D.5228 = (int) D.5227;
  D.5226 = mono_valloc (0B, size, D.5228);
  return D.5226;
}


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

  if (activate != 0) goto <D.5231>; else goto <D.5232>;
  <D.5231>:
  iftmp.6 = 3;
  goto <D.5233>;
  <D.5232>:
  iftmp.6 = 0;
  <D.5233>:
  prot_flags = iftmp.6;
  D.5234 = prot_flags | 80;
  return D.5234;
}


alloc_sb (struct Descriptor * desc)
{
  long unsigned int sb_header.7;
  long unsigned int D.5237;
  void * D.5238;
  _Bool D.5239;
  long int D.5240;
  long int D.5241;
  struct Descriptor * * D.5244;
  void * D.5245;
  void * sb_header;

  sb_header = mono_sgen_alloc_os_memory_aligned (16384, 16384, 1);
  sb_header.7 = (long unsigned int) sb_header;
  D.5237 = sb_header.7 & 4294950912;
  D.5238 = (void *) D.5237;
  D.5239 = D.5238 != sb_header;
  D.5240 = (long int) D.5239;
  D.5241 = __builtin_expect (D.5240, 0);
  if (D.5241 != 0) goto <D.5242>; else goto <D.5243>;
  <D.5242>:
  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.5243>:
  sb_header.7 = (long unsigned int) sb_header;
  D.5237 = sb_header.7 & 4294950912;
  D.5244 = (struct Descriptor * *) D.5237;
  *D.5244 = desc;
  D.5245 = sb_header + 16;
  return D.5245;
}


mono_sgen_alloc_os_memory_aligned (size_t size, size_t alignment, gboolean activate)
{
  void * D.5247;
  long unsigned int D.5248;
  int D.5249;

  D.5248 = prot_flags_for_activate (activate);
  D.5249 = (int) D.5248;
  D.5247 = mono_valloc_aligned (size, alignment, D.5249);
  return D.5247;
}


mono_lock_free_free (void * ptr)
{
  long unsigned int ptr.8;
  long unsigned int D.5252;
  struct Descriptor * * D.5253;
  long unsigned int sb.9;
  long unsigned int D.5255;
  long unsigned int D.5256;
  _Bool D.5257;
  long int D.5258;
  long int D.5259;
  volatile gint32 * D.5262;
  <unnamed-unsigned:15> D.5263;
  unsigned int D.5264;
  int ptr.10;
  int sb.11;
  int D.5267;
  unsigned int D.5268;
  unsigned int D.5269;
  unsigned int D.5270;
  short unsigned int D.5271;
  <unnamed-unsigned:15> D.5272;
  <unnamed-unsigned:15> D.5273;
  unsigned int D.5274;
  unsigned int D.5275;
  _Bool D.5276;
  long int D.5277;
  long int D.5278;
  unsigned char D.5281;
  unsigned char D.5282;
  <unnamed-unsigned:15> D.5285;
  <unnamed-unsigned:15> D.5286;
  unsigned int D.5287;
  unsigned int D.5288;
  int D.5291;
  unsigned char D.5292;
  unsigned char D.5293;
  _Bool D.5296;
  long int D.5297;
  long int D.5298;
  struct _MonoLockFreeAllocDescriptor * * D.5301;
  void * D.5302;
  struct MonoLockFreeAllocSizeClass * D.5306;
  _Bool D.5310;
  long int D.5311;
  long int D.5312;
  struct MonoLockFreeAllocator * D.5315;
  struct _MonoLockFreeAllocDescriptor * * D.5316;
  void * D.5317;
  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.5252 = ptr.8 & 4294950912;
      D.5253 = (struct Descriptor * *) D.5252;
      desc = *D.5253;
      sb = desc->sb;
      ptr.8 = (long unsigned int) ptr;
      sb.9 = (long unsigned int) sb;
      D.5255 = ptr.8 ^ sb.9;
      D.5256 = D.5255 & 4294950912;
      D.5257 = D.5256 != 0;
      D.5258 = (long int) D.5257;
      D.5259 = __builtin_expect (D.5258, 0);
      if (D.5259 != 0) goto <D.5260>; else goto <D.5261>;
      <D.5260>:
      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.5261>:
      <D.4985>:
      D.5262 = &desc->anchor.value;
      old_anchor = MEM[(volatile union Anchor *)D.5262];
      new_anchor = old_anchor;
      D.5263 = old_anchor.data.avail;
      D.5264 = (unsigned int) D.5263;
      MEM[(unsigned int *)ptr] = D.5264;
      ptr.10 = (int) ptr;
      sb.11 = (int) sb;
      D.5267 = ptr.10 - sb.11;
      D.5268 = (unsigned int) D.5267;
      D.5269 = desc->slot_size;
      D.5270 = D.5268 / D.5269;
      D.5271 = (short unsigned int) D.5270;
      D.5272 = (<unnamed-unsigned:15>) D.5271;
      new_anchor.data.avail = D.5272;
      D.5273 = new_anchor.data.avail;
      D.5274 = (unsigned int) D.5273;
      D.5269 = desc->slot_size;
      D.5275 = 16368 / D.5269;
      D.5276 = D.5274 >= D.5275;
      D.5277 = (long int) D.5276;
      D.5278 = __builtin_expect (D.5277, 0);
      if (D.5278 != 0) goto <D.5279>; else goto <D.5280>;
      <D.5279>:
      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.5280>:
      D.5281 = BIT_FIELD_REF <old_anchor, 8, 24>;
      D.5282 = D.5281 & 192;
      if (D.5282 == 0) goto <D.5283>; else goto <D.5284>;
      <D.5283>:
      new_anchor.data.state = 1;
      <D.5284>:
      D.5285 = new_anchor.data.count;
      D.5286 = D.5285 + 1;
      new_anchor.data.count = D.5286;
      D.5285 = new_anchor.data.count;
      D.5287 = (unsigned int) D.5285;
      D.5288 = desc->max_count;
      if (D.5287 == D.5288) goto <D.5289>; else goto <D.5290>;
      <D.5289>:
      heap = desc->heap;
      new_anchor.data.state = 2;
      <D.5290>:
      D.5291 = set_anchor (desc, old_anchor, new_anchor);
      if (D.5291 == 0) goto <D.4985>; else goto <D.4986>;
      <D.4986>:
      D.5292 = BIT_FIELD_REF <new_anchor, 8, 24>;
      D.5293 = D.5292 & 192;
      if (D.5293 == 128) goto <D.5294>; else goto <D.5295>;
      <D.5294>:
      D.5281 = BIT_FIELD_REF <old_anchor, 8, 24>;
      D.5282 = D.5281 & 192;
      D.5296 = D.5282 == 128;
      D.5297 = (long int) D.5296;
      D.5298 = __builtin_expect (D.5297, 0);
      if (D.5298 != 0) goto <D.5299>; else goto <D.5300>;
      <D.5299>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 495, "old_anchor.data.state != STATE_EMPTY");
      <D.5300>:
      D.5301 = &heap->active;
      D.5302 = InterlockedCompareExchangePointer (D.5301, 0B, desc);
      if (D.5302 == desc) goto <D.5303>; else goto <D.5304>;
      <D.5303>:
      desc_retire (desc);
      goto <D.5305>;
      <D.5304>:
      D.5306 = heap->sc;
      list_remove_empty_desc (D.5306);
      <D.5305>:
      goto <D.5307>;
      <D.5295>:
      D.5281 = BIT_FIELD_REF <old_anchor, 8, 24>;
      D.5282 = D.5281 & 192;
      if (D.5282 == 0) goto <D.5308>; else goto <D.5309>;
      <D.5308>:
      D.5292 = BIT_FIELD_REF <new_anchor, 8, 24>;
      D.5293 = D.5292 & 192;
      D.5310 = D.5293 != 64;
      D.5311 = (long int) D.5310;
      D.5312 = __builtin_expect (D.5311, 0);
      if (D.5312 != 0) goto <D.5313>; else goto <D.5314>;
      <D.5313>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 513, "new_anchor.data.state == STATE_PARTIAL");
      <D.5314>:
      D.5315 = desc->heap;
      D.5316 = &D.5315->active;
      D.5317 = InterlockedCompareExchangePointer (D.5316, desc, 0B);
      if (D.5317 != 0B) goto <D.5318>; else goto <D.5319>;
      <D.5318>:
      heap_put_partial (desc);
      <D.5319>:
      <D.5309>:
      <D.5307>:
    }
  finally
    {
      old_anchor = {CLOBBER};
      new_anchor = {CLOBBER};
    }
}


list_remove_empty_desc (struct MonoLockFreeAllocSizeClass * sc)
{
  struct MonoLockFreeQueue * D.5320;
  <unnamed-unsigned:2> D.5323;
  struct MonoLockFreeAllocator * D.5327;
  struct MonoLockFreeAllocSizeClass * D.5328;
  _Bool D.5329;
  long int D.5330;
  long int D.5331;
  int num_non_empty;

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

    D.5320 = &sc->partial;
    desc = mono_lock_free_queue_dequeue (D.5320);
    if (desc == 0B) goto <D.5321>; else goto <D.5322>;
    <D.5321>:
    return;
    <D.5322>:
    D.5323 = desc->anchor.data.state;
    if (D.5323 == 2) goto <D.5324>; else goto <D.5325>;
    <D.5324>:
    desc_retire (desc);
    goto <D.5326>;
    <D.5325>:
    D.5327 = desc->heap;
    D.5328 = D.5327->sc;
    D.5329 = D.5328 != sc;
    D.5330 = (long int) D.5329;
    D.5331 = __builtin_expect (D.5330, 0);
    if (D.5331 != 0) goto <D.5332>; else goto <D.5333>;
    <D.5332>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 325, "desc->heap->sc == sc");
    <D.5333>:
    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.5334>; else goto <D.5335>;
    <D.5334>:
    return;
    <D.5335>:
    <D.5326>:
  }
  goto <D.4938>;
}


mono_lock_free_allocator_check_consistency (struct MonoLockFreeAllocator * heap)
{
  <unnamed-unsigned:2> D.5339;
  _Bool D.5340;
  long int D.5341;
  long int D.5342;
  int iftmp.12;
  <unnamed-unsigned:2> D.5348;
  <unnamed-unsigned:2> D.5350;
  _Bool D.5352;
  long int D.5353;
  long int D.5354;
  struct MonoLockFreeAllocSizeClass * D.5357;
  struct MonoLockFreeQueue * D.5358;
  gboolean D.5359;
  struct Descriptor * active;
  struct Descriptor * desc;

  active = heap->active;
  if (active != 0B) goto <D.5337>; else goto <D.5338>;
  <D.5337>:
  D.5339 = active->anchor.data.state;
  D.5340 = D.5339 != 1;
  D.5341 = (long int) D.5340;
  D.5342 = __builtin_expect (D.5341, 0);
  if (D.5342 != 0) goto <D.5343>; else goto <D.5344>;
  <D.5343>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 599, "active->anchor.data.state == STATE_PARTIAL");
  <D.5344>:
  descriptor_check_consistency (active, 0);
  <D.5338>:
  goto <D.5019>;
  <D.5018>:
  D.5348 = desc->anchor.data.state;
  if (D.5348 != 1) goto <D.5349>; else goto <D.5346>;
  <D.5349>:
  D.5350 = desc->anchor.data.state;
  if (D.5350 != 2) goto <D.5351>; else goto <D.5346>;
  <D.5351>:
  iftmp.12 = 1;
  goto <D.5347>;
  <D.5346>:
  iftmp.12 = 0;
  <D.5347>:
  D.5352 = iftmp.12 != 0;
  D.5353 = (long int) D.5352;
  D.5354 = __builtin_expect (D.5353, 0);
  if (D.5354 != 0) goto <D.5355>; else goto <D.5356>;
  <D.5355>:
  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.5356>:
  descriptor_check_consistency (desc, 0);
  <D.5019>:
  D.5357 = heap->sc;
  D.5358 = &D.5357->partial;
  desc = mono_lock_free_queue_dequeue (D.5358);
  if (desc != 0B) goto <D.5018>; else goto <D.5020>;
  <D.5020>:
  D.5359 = 1;
  return D.5359;
}


descriptor_check_consistency (struct Descriptor * desc, gboolean print)
{
  <unnamed-unsigned:15> D.5361;
  unsigned int D.5362;
  unsigned int D.5363;
  int max_count.13;
  int D.5365;
  sizetype D.5366;
  sizetype max_count.14;
  bitsizetype D.5368;
  bitsizetype D.5369;
  sizetype D.5370;
  gboolean[0:D.5366] * linked.15;
  struct MonoLockFreeAllocator * D.5379;
  struct MonoLockFreeAllocSizeClass * D.5380;
  unsigned int D.5381;
  <unnamed-unsigned:2> D.5391;
  int D.5392;
  <unnamed-unsigned:15> D.5427;
  void * D.5428;
  unsigned int D.5429;
  unsigned int max_count.16;
  int D.5438;
  void * saved_stack.17;
  int count;
  int max_count;
  gboolean linked[0:D.5366] [value-expr: *linked.15];
  int i;
  int last;
  unsigned int index;
  struct Descriptor * avail;

  saved_stack.17 = __builtin_stack_save ();
  try
    {
      D.5361 = desc->anchor.data.count;
      count = (int) D.5361;
      D.5362 = desc->slot_size;
      D.5363 = 16368 / D.5362;
      max_count = (int) D.5363;
      max_count.13 = max_count;
      D.5365 = max_count.13 + -1;
      D.5366 = (sizetype) D.5365;
      max_count.14 = (sizetype) max_count.13;
      D.5368 = (bitsizetype) max_count.14;
      D.5369 = D.5368 * 32;
      max_count.14 = (sizetype) max_count.13;
      D.5370 = max_count.14 * 4;
      max_count.14 = (sizetype) max_count.13;
      D.5368 = (bitsizetype) max_count.14;
      D.5369 = D.5368 * 32;
      max_count.14 = (sizetype) max_count.13;
      D.5370 = max_count.14 * 4;
      linked.15 = __builtin_alloca_with_align (D.5370, 32);
      avail = desc_avail;
      goto <D.4999>;
      <D.4998>:
      if (desc == avail) goto <D.5372>; else goto <D.5373>;
      <D.5372>:
      if (print != 0) goto <D.5374>; else goto <D.5375>;
      <D.5374>:
      monoeg_g_print ("descriptor is in the available list\n");
      goto <D.5376>;
      <D.5375>:
      if (1 != 0) goto <D.5377>; else goto <D.5378>;
      <D.5377>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 546, "FALSE");
      <D.5378>:
      <D.5376>:
      <D.5373>:
      avail = avail->next;
      <D.4999>:
      if (avail != 0B) goto <D.4998>; else goto <D.5000>;
      <D.5000>:
      D.5362 = desc->slot_size;
      D.5379 = desc->heap;
      D.5380 = D.5379->sc;
      D.5381 = D.5380->slot_size;
      if (D.5362 != D.5381) goto <D.5382>; else goto <D.5383>;
      <D.5382>:
      if (print != 0) goto <D.5384>; else goto <D.5385>;
      <D.5384>:
      monoeg_g_print ("slot size doesn\'t match size class\n");
      goto <D.5386>;
      <D.5385>:
      if (1 != 0) goto <D.5387>; else goto <D.5388>;
      <D.5387>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 549, "FALSE");
      <D.5388>:
      <D.5386>:
      <D.5383>:
      if (print != 0) goto <D.5389>; else goto <D.5390>;
      <D.5389>:
      monoeg_g_print ("descriptor %p is ", desc);
      <D.5390>:
      D.5391 = desc->anchor.data.state;
      D.5392 = (int) D.5391;
      switch (D.5392) <default: <D.5005>, case 0: <D.5001>, case 1: <D.5003>, case 2: <D.5004>>
      <D.5001>:
      if (print != 0) goto <D.5393>; else goto <D.5394>;
      <D.5393>:
      monoeg_g_print ("full\n");
      <D.5394>:
      if (count != 0) goto <D.5395>; else goto <D.5396>;
      <D.5395>:
      if (print != 0) goto <D.5397>; else goto <D.5398>;
      <D.5397>:
      monoeg_g_print ("count is not zero: %d\n", count);
      goto <D.5399>;
      <D.5398>:
      if (1 != 0) goto <D.5400>; else goto <D.5401>;
      <D.5400>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 558, "FALSE");
      <D.5401>:
      <D.5399>:
      <D.5396>:
      goto <D.5002>;
      <D.5003>:
      if (print != 0) goto <D.5402>; else goto <D.5403>;
      <D.5402>:
      monoeg_g_print ("partial\n");
      <D.5403>:
      if (count >= max_count) goto <D.5404>; else goto <D.5405>;
      <D.5404>:
      if (print != 0) goto <D.5406>; else goto <D.5407>;
      <D.5406>:
      monoeg_g_print ("count too high: is %d but must be below %d\n", count, max_count);
      goto <D.5408>;
      <D.5407>:
      if (1 != 0) goto <D.5409>; else goto <D.5410>;
      <D.5409>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 563, "FALSE");
      <D.5410>:
      <D.5408>:
      <D.5405>:
      goto <D.5002>;
      <D.5004>:
      if (print != 0) goto <D.5411>; else goto <D.5412>;
      <D.5411>:
      monoeg_g_print ("empty\n");
      <D.5412>:
      if (count != max_count) goto <D.5413>; else goto <D.5414>;
      <D.5413>:
      if (print != 0) goto <D.5415>; else goto <D.5416>;
      <D.5415>:
      monoeg_g_print ("count is wrong: is %d but should be %d\n", count, max_count);
      goto <D.5417>;
      <D.5416>:
      if (1 != 0) goto <D.5418>; else goto <D.5419>;
      <D.5418>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 568, "FALSE");
      <D.5419>:
      <D.5417>:
      <D.5414>:
      goto <D.5002>;
      <D.5005>:
      if (1 != 0) goto <D.5420>; else goto <D.5421>;
      <D.5420>:
      if (print != 0) goto <D.5422>; else goto <D.5423>;
      <D.5422>:
      monoeg_g_print ("invalid state\n");
      goto <D.5424>;
      <D.5423>:
      if (1 != 0) goto <D.5425>; else goto <D.5426>;
      <D.5425>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 571, "FALSE");
      <D.5426>:
      <D.5424>:
      <D.5421>:
      <D.5002>:
      i = 0;
      goto <D.5007>;
      <D.5006>:
      *linked.15[i] = 0;
      i = i + 1;
      <D.5007>:
      if (i < max_count) goto <D.5006>; else goto <D.5008>;
      <D.5008>:
      D.5427 = desc->anchor.data.avail;
      index = (unsigned int) D.5427;
      last = -1;
      i = 0;
      goto <D.5012>;
      <D.5011>:
      {
        void * addr;

        D.5428 = desc->sb;
        D.5362 = desc->slot_size;
        D.5429 = D.5362 * index;
        addr = D.5428 + D.5429;
        max_count.16 = (unsigned int) max_count;
        if (max_count.16 <= index) goto <D.5431>; else goto <D.5432>;
        <D.5431>:
        if (print != 0) goto <D.5433>; else goto <D.5434>;
        <D.5433>:
        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.5435>;
        <D.5434>:
        if (1 != 0) goto <D.5436>; else goto <D.5437>;
        <D.5436>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 583, "FALSE");
        <D.5437>:
        <D.5435>:
        <D.5432>:
        D.5438 = *linked.15[index];
        if (D.5438 != 0) goto <D.5439>; else goto <D.5440>;
        <D.5439>:
        if (print != 0) goto <D.5441>; else goto <D.5442>;
        <D.5441>:
        monoeg_g_print ("%dth available slot %d linked twice\n", i, index);
        goto <D.5443>;
        <D.5442>:
        if (1 != 0) goto <D.5444>; else goto <D.5445>;
        <D.5444>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 584, "FALSE");
        <D.5445>:
        <D.5443>:
        <D.5440>:
        D.5438 = *linked.15[index];
        if (D.5438 != 0) goto <D.5010>; else goto <D.5446>;
        <D.5446>:
        *linked.15[index] = 1;
        last = (int) index;
        index = MEM[(unsigned int *)addr];
      }
      i = i + 1;
      <D.5012>:
      if (i < count) goto <D.5011>; else goto <D.5010>;
      <D.5010>:
    }
  finally
    {
      __builtin_stack_restore (saved_stack.17);
    }
}


mono_lock_free_allocator_init_size_class (struct MonoLockFreeAllocSizeClass * sc, unsigned int slot_size)
{
  _Bool D.5449;
  long int D.5450;
  long int D.5451;
  struct MonoLockFreeQueue * D.5454;

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


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


