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

  <D.5326>:
  addr = alloc_from_active_or_partial (heap);
  if (addr != 0B) goto <D.5325>; else goto <D.5380>;
  <D.5380>:
  addr = alloc_from_new_sb (heap);
  if (addr != 0B) goto <D.5325>; else goto <D.5381>;
  <D.5381>:
  goto <D.5326>;
  <D.5325>:
  D.5382 = addr;
  return D.5382;
}


alloc_from_active_or_partial (struct MonoLockFreeAllocator * heap)
{
  struct _MonoLockFreeAllocDescriptor * * D.5386;
  void * D.5387;
  void * D.5392;
  volatile gint32 * D.5393;
  unsigned char D.5394;
  unsigned char D.5395;
  _Bool D.5398;
  long int D.5399;
  long int D.5400;
  <unnamed-unsigned:15> D.5403;
  int D.5404;
  _Bool D.5405;
  long int D.5406;
  long int D.5407;
  void * D.5410;
  <unnamed-unsigned:15> D.5411;
  unsigned int D.5412;
  unsigned int D.5413;
  unsigned int D.5414;
  sizetype D.5415;
  unsigned int D.5416;
  _Bool D.5417;
  long int D.5418;
  long int D.5419;
  short unsigned int D.5422;
  <unnamed-unsigned:15> D.5423;
  <unnamed-unsigned:15> D.5424;
  <unnamed-unsigned:15> D.5425;
  unsigned int D.5426;
  unsigned int D.5427;
  int D.5430;
  unsigned char D.5431;
  unsigned char D.5432;
  void * D.5435;
  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.5384>; else goto <D.5385>;
      <D.5384>:
      D.5386 = &heap->active;
      D.5387 = InterlockedCompareExchangePointer (D.5386, 0B, desc);
      if (D.5387 != desc) goto retry; else goto <D.5388>;
      <D.5388>:
      goto <D.5389>;
      <D.5385>:
      desc = heap_get_partial (heap);
      if (desc == 0B) goto <D.5390>; else goto <D.5391>;
      <D.5390>:
      D.5392 = 0B;
      return D.5392;
      <D.5391>:
      <D.5389>:
      <D.5309>:
      {
        unsigned int next;

        D.5393 = &desc->anchor.value;
        old_anchor = MEM[(volatile union Anchor *)D.5393];
        new_anchor = old_anchor;
        D.5394 = BIT_FIELD_REF <old_anchor, 8, 24>;
        D.5395 = D.5394 & 192;
        if (D.5395 == 128) goto <D.5396>; else goto <D.5397>;
        <D.5396>:
        desc_retire (desc);
        goto retry;
        <D.5397>:
        D.5394 = BIT_FIELD_REF <old_anchor, 8, 24>;
        D.5395 = D.5394 & 192;
        D.5398 = D.5395 != 64;
        D.5399 = (long int) D.5398;
        D.5400 = __builtin_expect (D.5399, 0);
        if (D.5400 != 0) goto <D.5401>; else goto <D.5402>;
        <D.5401>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 383, "old_anchor.data.state == STATE_PARTIAL");
        <D.5402>:
        D.5403 = old_anchor.data.count;
        D.5404 = (int) D.5403;
        D.5405 = D.5404 <= 0;
        D.5406 = (long int) D.5405;
        D.5407 = __builtin_expect (D.5406, 0);
        if (D.5407 != 0) goto <D.5408>; else goto <D.5409>;
        <D.5408>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 384, "old_anchor.data.count > 0");
        <D.5409>:
        D.5410 = desc->sb;
        D.5411 = old_anchor.data.avail;
        D.5412 = (unsigned int) D.5411;
        D.5413 = desc->slot_size;
        D.5414 = D.5412 * D.5413;
        D.5415 = (sizetype) D.5414;
        addr = D.5410 + D.5415;
        mono_memory_read_barrier ();
        next = MEM[(unsigned int *)addr];
        D.5413 = desc->slot_size;
        D.5416 = 16368 / D.5413;
        D.5417 = D.5416 <= next;
        D.5418 = (long int) D.5417;
        D.5419 = __builtin_expect (D.5418, 0);
        if (D.5419 != 0) goto <D.5420>; else goto <D.5421>;
        <D.5420>:
        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.5421>:
        D.5422 = (short unsigned int) next;
        D.5423 = (<unnamed-unsigned:15>) D.5422;
        new_anchor.data.avail = D.5423;
        D.5424 = new_anchor.data.count;
        D.5425 = D.5424 + 32767;
        new_anchor.data.count = D.5425;
        D.5426 = BIT_FIELD_REF <new_anchor, 32, 0>;
        D.5427 = D.5426 & 1073709056;
        if (D.5427 == 0) goto <D.5428>; else goto <D.5429>;
        <D.5428>:
        new_anchor.data.state = 0;
        <D.5429>:
      }
      D.5430 = set_anchor (desc, old_anchor, new_anchor);
      if (D.5430 == 0) goto <D.5309>; else goto <D.5310>;
      <D.5310>:
      D.5431 = BIT_FIELD_REF <new_anchor, 8, 24>;
      D.5432 = D.5431 & 192;
      if (D.5432 == 64) goto <D.5433>; else goto <D.5434>;
      <D.5433>:
      D.5386 = &heap->active;
      D.5435 = InterlockedCompareExchangePointer (D.5386, desc, 0B);
      if (D.5435 != 0B) goto <D.5436>; else goto <D.5437>;
      <D.5436>:
      heap_put_partial (desc);
      <D.5437>:
      <D.5434>:
      D.5392 = addr;
      return D.5392;
    }
  finally
    {
      old_anchor = {CLOBBER};
      new_anchor = {CLOBBER};
    }
}


heap_get_partial (struct MonoLockFreeAllocator * heap)
{
  struct Descriptor * D.5440;
  struct MonoLockFreeAllocSizeClass * D.5441;

  D.5441 = heap->sc;
  D.5440 = list_get_partial (D.5441);
  return D.5440;
}


list_get_partial (struct MonoLockFreeAllocSizeClass * sc)
{
  struct MonoLockFreeQueue * D.5443;
  struct Descriptor * D.5446;
  <unnamed-unsigned:2> D.5447;

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

    D.5443 = &sc->partial;
    desc = mono_lock_free_queue_dequeue (D.5443);
    if (desc == 0B) goto <D.5444>; else goto <D.5445>;
    <D.5444>:
    D.5446 = 0B;
    return D.5446;
    <D.5445>:
    D.5447 = desc->anchor.data.state;
    if (D.5447 != 2) goto <D.5448>; else goto <D.5449>;
    <D.5448>:
    D.5446 = desc;
    return D.5446;
    <D.5449>:
    desc_retire (desc);
  }
  goto <D.5275>;
}


desc_retire (struct Descriptor * desc)
{
  <unnamed-unsigned:2> D.5451;
  _Bool D.5452;
  long int D.5453;
  long int D.5454;
  int D.5457;
  _Bool D.5458;
  long int D.5459;
  long int D.5460;
  void * D.5463;

  D.5451 = desc->anchor.data.state;
  D.5452 = D.5451 != 2;
  D.5453 = (long int) D.5452;
  D.5454 = __builtin_expect (D.5453, 0);
  if (D.5454 != 0) goto <D.5455>; else goto <D.5456>;
  <D.5455>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 251, "desc->anchor.data.state == STATE_EMPTY");
  <D.5456>:
  D.5457 = desc->in_use;
  D.5458 = D.5457 == 0;
  D.5459 = (long int) D.5458;
  D.5460 = __builtin_expect (D.5459, 0);
  if (D.5460 != 0) goto <D.5461>; else goto <D.5462>;
  <D.5461>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 252, "desc->in_use");
  <D.5462>:
  desc->in_use = 0;
  D.5463 = desc->sb;
  free_sb (D.5463);
  mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, 0, 1);
}


desc_enqueue_avail (void * _desc)
{
  <unnamed-unsigned:2> D.5464;
  _Bool D.5465;
  long int D.5466;
  long int D.5467;
  int D.5470;
  _Bool D.5471;
  long int D.5472;
  long int D.5473;
  void * D.5476;
  struct Descriptor * desc;
  struct Descriptor * old_head;

  desc = _desc;
  D.5464 = desc->anchor.data.state;
  D.5465 = D.5464 != 2;
  D.5466 = (long int) D.5465;
  D.5467 = __builtin_expect (D.5466, 0);
  if (D.5467 != 0) goto <D.5468>; else goto <D.5469>;
  <D.5468>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 238, "desc->anchor.data.state == STATE_EMPTY");
  <D.5469>:
  D.5470 = desc->in_use;
  D.5471 = D.5470 != 0;
  D.5472 = (long int) D.5471;
  D.5473 = __builtin_expect (D.5472, 0);
  if (D.5473 != 0) goto <D.5474>; else goto <D.5475>;
  <D.5474>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 239, "!desc->in_use");
  <D.5475>:
  <D.5266>:
  old_head = desc_avail;
  desc->next = old_head;
  mono_memory_write_barrier ();
  D.5476 = InterlockedCompareExchangePointer (&desc_avail, desc, old_head);
  if (D.5476 != old_head) goto <D.5266>; else goto <D.5267>;
  <D.5267>:
}


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.5478;
  void * D.5479;
  _Bool D.5480;
  long int D.5481;
  long int D.5482;
  void * sb_header;

  sb.0 = (long unsigned int) sb;
  D.5478 = sb.0 & 18446744073709535232;
  sb_header = (void *) D.5478;
  D.5479 = sb_header + 16;
  D.5480 = D.5479 != sb;
  D.5481 = (long int) D.5480;
  D.5482 = __builtin_expect (D.5481, 0);
  if (D.5482 != 0) goto <D.5483>; else goto <D.5484>;
  <D.5483>:
  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.5484>:
  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.5485;
  unsigned char D.5486;
  unsigned char D.5489;
  unsigned char D.5490;
  _Bool D.5491;
  long int D.5492;
  long int D.5493;
  gboolean D.5496;
  int D.5497;
  int D.5498;
  volatile gint32 * D.5499;
  int D.5500;
  _Bool D.5501;

  D.5485 = BIT_FIELD_REF <old_anchor, 8, 24>;
  D.5486 = D.5485 & 192;
  if (D.5486 == 128) goto <D.5487>; else goto <D.5488>;
  <D.5487>:
  D.5489 = BIT_FIELD_REF <new_anchor, 8, 24>;
  D.5490 = D.5489 & 192;
  D.5491 = D.5490 != 128;
  D.5492 = (long int) D.5491;
  D.5493 = __builtin_expect (D.5492, 0);
  if (D.5493 != 0) goto <D.5494>; else goto <D.5495>;
  <D.5494>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 349, "new_anchor.data.state == STATE_EMPTY");
  <D.5495>:
  <D.5488>:
  D.5497 = old_anchor.value;
  D.5498 = new_anchor.value;
  D.5499 = &desc->anchor.value;
  D.5500 = InterlockedCompareExchange (D.5499, D.5498, D.5497);
  D.5497 = old_anchor.value;
  D.5501 = D.5500 == D.5497;
  D.5496 = (gboolean) D.5501;
  return D.5496;
}


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

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


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

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


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


list_put_partial (struct Descriptor * desc)
{
  <unnamed-unsigned:2> D.5513;
  _Bool D.5514;
  long int D.5515;
  long int D.5516;

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


desc_put_partial (void * _desc)
{
  <unnamed-unsigned:2> D.5519;
  _Bool D.5520;
  long int D.5521;
  long int D.5522;
  struct MonoLockFreeQueueNode * D.5525;
  struct MonoLockFreeAllocator * D.5526;
  struct MonoLockFreeAllocSizeClass * D.5527;
  struct MonoLockFreeQueue * D.5528;
  struct Descriptor * desc;

  desc = _desc;
  D.5519 = desc->anchor.data.state;
  D.5520 = D.5519 == 0;
  D.5521 = (long int) D.5520;
  D.5522 = __builtin_expect (D.5521, 0);
  if (D.5522 != 0) goto <D.5523>; else goto <D.5524>;
  <D.5523>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 297, "desc->anchor.data.state != STATE_FULL");
  <D.5524>:
  D.5525 = &desc->node;
  mono_lock_free_queue_node_free (D.5525);
  D.5525 = &desc->node;
  D.5526 = desc->heap;
  D.5527 = D.5526->sc;
  D.5528 = &D.5527->partial;
  mono_lock_free_queue_enqueue (D.5528, D.5525);
}


alloc_from_new_sb (struct MonoLockFreeAllocator * heap)
{
  void * D.5529;
  struct MonoLockFreeAllocSizeClass * D.5530;
  unsigned int D.5531;
  void * D.5532;
  unsigned int D.5533;
  sizetype D.5534;
  unsigned int * D.5535;
  unsigned int D.5536;
  unsigned int D.5537;
  unsigned int D.5538;
  short unsigned int D.5539;
  short unsigned int D.5540;
  <unnamed-unsigned:15> D.5541;
  struct _MonoLockFreeAllocDescriptor * * D.5542;
  void * D.5543;
  void * D.5546;
  unsigned int slot_size;
  unsigned int count;
  unsigned int i;
  struct Descriptor * desc;

  desc = desc_alloc ();
  D.5529 = alloc_sb (desc);
  desc->sb = D.5529;
  D.5530 = heap->sc;
  D.5531 = D.5530->slot_size;
  desc->slot_size = D.5531;
  slot_size = desc->slot_size;
  count = 16368 / slot_size;
  i = 1;
  goto <D.5319>;
  <D.5318>:
  D.5532 = desc->sb;
  D.5533 = i * slot_size;
  D.5534 = (sizetype) D.5533;
  D.5535 = D.5532 + D.5534;
  D.5536 = i + 1;
  *D.5535 = D.5536;
  i = i + 1;
  <D.5319>:
  D.5537 = count + 4294967295;
  if (D.5537 > i) goto <D.5318>; else goto <D.5320>;
  <D.5320>:
  desc->heap = heap;
  desc->anchor.data.avail = 1;
  D.5530 = heap->sc;
  D.5531 = D.5530->slot_size;
  desc->slot_size = D.5531;
  desc->max_count = count;
  D.5538 = desc->max_count;
  D.5539 = (short unsigned int) D.5538;
  D.5540 = D.5539 + 65535;
  D.5541 = (<unnamed-unsigned:15>) D.5540;
  desc->anchor.data.count = D.5541;
  desc->anchor.data.state = 1;
  mono_memory_write_barrier ();
  D.5542 = &heap->active;
  D.5543 = InterlockedCompareExchangePointer (D.5542, desc, 0B);
  if (D.5543 == 0B) goto <D.5544>; else goto <D.5545>;
  <D.5544>:
  D.5546 = desc->sb;
  return D.5546;
  <D.5545>:
  desc->anchor.data.state = 2;
  desc_retire (desc);
  D.5546 = 0B;
  return D.5546;
}


desc_alloc ()
{
  void * D.5550;
  _Bool D.5551;
  long unsigned int D.5553;
  struct Descriptor * iftmp.5;
  int D.5557;
  long unsigned int D.5558;
  long unsigned int D.5559;
  struct MonoLockFreeQueueNode * D.5561;
  struct Descriptor * D.5562;
  void * D.5563;
  _Bool D.5564;
  int D.5570;
  _Bool D.5571;
  long int D.5572;
  long int D.5573;
  struct Descriptor * D.5576;
  struct MonoThreadHazardPointers * hp;
  struct Descriptor * desc;

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

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

      next = desc->next;
      D.5550 = InterlockedCompareExchangePointer (&desc_avail, next, desc);
      D.5551 = D.5550 == desc;
      success = (gboolean) D.5551;
    }
    goto <D.5552>;
    <D.5549>:
    {
      size_t desc_size;
      struct Descriptor * d;
      int i;

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

        if (i != 63) goto <D.5555>; else goto <D.5556>;
        <D.5555>:
        D.5557 = i + 1;
        D.5558 = (long unsigned int) D.5557;
        D.5559 = D.5558 * desc_size;
        iftmp.5 = desc + D.5559;
        goto <D.5560>;
        <D.5556>:
        iftmp.5 = 0B;
        <D.5560>:
        next = iftmp.5;
        d->next = next;
        D.5561 = &d->node;
        mono_lock_free_queue_node_init (D.5561, 1);
        d = next;
      }
      i = i + 1;
      <D.5257>:
      if (i <= 63) goto <D.5256>; else goto <D.5258>;
      <D.5258>:
      mono_memory_write_barrier ();
      D.5562 = desc->next;
      D.5563 = InterlockedCompareExchangePointer (&desc_avail, D.5562, 0B);
      D.5564 = D.5563 == 0B;
      success = (gboolean) D.5564;
      if (success == 0) goto <D.5565>; else goto <D.5566>;
      <D.5565>:
      D.5553 = desc_size * 64;
      mono_sgen_free_os_memory (desc, D.5553);
      <D.5566>:
    }
    <D.5552>:
    if (0 != 0) goto <D.5567>; else goto <D.5568>;
    <D.5567>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 220, "(1) >= 0 && (1) < HAZARD_POINTER_COUNT");
    <D.5568>:
    hp->hazard_pointers[1] = 0B;
    if (success != 0) goto <D.5259>; else goto <D.5569>;
    <D.5569>:
  }
  goto <D.5260>;
  <D.5259>:
  D.5570 = desc->in_use;
  D.5571 = D.5570 != 0;
  D.5572 = (long int) D.5571;
  D.5573 = __builtin_expect (D.5572, 0);
  if (D.5573 != 0) goto <D.5574>; else goto <D.5575>;
  <D.5574>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 226, "!desc->in_use");
  <D.5575>:
  desc->in_use = 1;
  D.5576 = desc;
  return D.5576;
}


mono_sgen_alloc_os_memory (size_t size, int activate)
{
  void * D.5578;
  long unsigned int D.5579;
  int D.5580;

  D.5579 = prot_flags_for_activate (activate);
  D.5580 = (int) D.5579;
  D.5578 = mono_valloc (0B, size, D.5580);
  return D.5578;
}


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

  if (activate != 0) goto <D.5583>; else goto <D.5584>;
  <D.5583>:
  iftmp.6 = 3;
  goto <D.5585>;
  <D.5584>:
  iftmp.6 = 0;
  <D.5585>:
  prot_flags = iftmp.6;
  D.5586 = prot_flags | 80;
  return D.5586;
}


alloc_sb (struct Descriptor * desc)
{
  long unsigned int sb_header.7;
  long unsigned int D.5589;
  void * D.5590;
  _Bool D.5591;
  long int D.5592;
  long int D.5593;
  struct Descriptor * * D.5596;
  void * D.5597;
  void * sb_header;

  sb_header = mono_sgen_alloc_os_memory_aligned (16384, 16384, 1);
  sb_header.7 = (long unsigned int) sb_header;
  D.5589 = sb_header.7 & 18446744073709535232;
  D.5590 = (void *) D.5589;
  D.5591 = D.5590 != sb_header;
  D.5592 = (long int) D.5591;
  D.5593 = __builtin_expect (D.5592, 0);
  if (D.5593 != 0) goto <D.5594>; else goto <D.5595>;
  <D.5594>:
  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.5595>:
  sb_header.7 = (long unsigned int) sb_header;
  D.5589 = sb_header.7 & 18446744073709535232;
  D.5596 = (struct Descriptor * *) D.5589;
  *D.5596 = desc;
  D.5597 = sb_header + 16;
  return D.5597;
}


mono_sgen_alloc_os_memory_aligned (size_t size, size_t alignment, gboolean activate)
{
  void * D.5599;
  long unsigned int D.5600;
  int D.5601;

  D.5600 = prot_flags_for_activate (activate);
  D.5601 = (int) D.5600;
  D.5599 = mono_valloc_aligned (size, alignment, D.5601);
  return D.5599;
}


mono_lock_free_free (void * ptr)
{
  long unsigned int ptr.8;
  long unsigned int D.5604;
  struct Descriptor * * D.5605;
  long unsigned int sb.9;
  long unsigned int D.5607;
  long unsigned int D.5608;
  _Bool D.5609;
  long int D.5610;
  long int D.5611;
  volatile gint32 * D.5614;
  <unnamed-unsigned:15> D.5615;
  unsigned int D.5616;
  long int ptr.10;
  long int sb.11;
  long int D.5619;
  unsigned int D.5620;
  long int D.5621;
  long int D.5622;
  short unsigned int D.5623;
  <unnamed-unsigned:15> D.5624;
  <unnamed-unsigned:15> D.5625;
  unsigned int D.5626;
  unsigned int D.5627;
  _Bool D.5628;
  long int D.5629;
  long int D.5630;
  unsigned char D.5633;
  unsigned char D.5634;
  <unnamed-unsigned:15> D.5637;
  <unnamed-unsigned:15> D.5638;
  unsigned int D.5639;
  unsigned int D.5640;
  int D.5643;
  unsigned char D.5644;
  unsigned char D.5645;
  _Bool D.5648;
  long int D.5649;
  long int D.5650;
  struct _MonoLockFreeAllocDescriptor * * D.5653;
  void * D.5654;
  struct MonoLockFreeAllocSizeClass * D.5658;
  _Bool D.5662;
  long int D.5663;
  long int D.5664;
  struct MonoLockFreeAllocator * D.5667;
  struct _MonoLockFreeAllocDescriptor * * D.5668;
  void * D.5669;
  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.5604 = ptr.8 & 18446744073709535232;
      D.5605 = (struct Descriptor * *) D.5604;
      desc = *D.5605;
      sb = desc->sb;
      ptr.8 = (long unsigned int) ptr;
      sb.9 = (long unsigned int) sb;
      D.5607 = ptr.8 ^ sb.9;
      D.5608 = D.5607 & 18446744073709535232;
      D.5609 = D.5608 != 0;
      D.5610 = (long int) D.5609;
      D.5611 = __builtin_expect (D.5610, 0);
      if (D.5611 != 0) goto <D.5612>; else goto <D.5613>;
      <D.5612>:
      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.5613>:
      <D.5335>:
      D.5614 = &desc->anchor.value;
      old_anchor = MEM[(volatile union Anchor *)D.5614];
      new_anchor = old_anchor;
      D.5615 = old_anchor.data.avail;
      D.5616 = (unsigned int) D.5615;
      MEM[(unsigned int *)ptr] = D.5616;
      ptr.10 = (long int) ptr;
      sb.11 = (long int) sb;
      D.5619 = ptr.10 - sb.11;
      D.5620 = desc->slot_size;
      D.5621 = (long int) D.5620;
      D.5622 = D.5619 / D.5621;
      D.5623 = (short unsigned int) D.5622;
      D.5624 = (<unnamed-unsigned:15>) D.5623;
      new_anchor.data.avail = D.5624;
      D.5625 = new_anchor.data.avail;
      D.5626 = (unsigned int) D.5625;
      D.5620 = desc->slot_size;
      D.5627 = 16368 / D.5620;
      D.5628 = D.5626 >= D.5627;
      D.5629 = (long int) D.5628;
      D.5630 = __builtin_expect (D.5629, 0);
      if (D.5630 != 0) goto <D.5631>; else goto <D.5632>;
      <D.5631>:
      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.5632>:
      D.5633 = BIT_FIELD_REF <old_anchor, 8, 24>;
      D.5634 = D.5633 & 192;
      if (D.5634 == 0) goto <D.5635>; else goto <D.5636>;
      <D.5635>:
      new_anchor.data.state = 1;
      <D.5636>:
      D.5637 = new_anchor.data.count;
      D.5638 = D.5637 + 1;
      new_anchor.data.count = D.5638;
      D.5637 = new_anchor.data.count;
      D.5639 = (unsigned int) D.5637;
      D.5640 = desc->max_count;
      if (D.5639 == D.5640) goto <D.5641>; else goto <D.5642>;
      <D.5641>:
      heap = desc->heap;
      new_anchor.data.state = 2;
      <D.5642>:
      D.5643 = set_anchor (desc, old_anchor, new_anchor);
      if (D.5643 == 0) goto <D.5335>; else goto <D.5336>;
      <D.5336>:
      D.5644 = BIT_FIELD_REF <new_anchor, 8, 24>;
      D.5645 = D.5644 & 192;
      if (D.5645 == 128) goto <D.5646>; else goto <D.5647>;
      <D.5646>:
      D.5633 = BIT_FIELD_REF <old_anchor, 8, 24>;
      D.5634 = D.5633 & 192;
      D.5648 = D.5634 == 128;
      D.5649 = (long int) D.5648;
      D.5650 = __builtin_expect (D.5649, 0);
      if (D.5650 != 0) goto <D.5651>; else goto <D.5652>;
      <D.5651>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 495, "old_anchor.data.state != STATE_EMPTY");
      <D.5652>:
      D.5653 = &heap->active;
      D.5654 = InterlockedCompareExchangePointer (D.5653, 0B, desc);
      if (D.5654 == desc) goto <D.5655>; else goto <D.5656>;
      <D.5655>:
      desc_retire (desc);
      goto <D.5657>;
      <D.5656>:
      D.5658 = heap->sc;
      list_remove_empty_desc (D.5658);
      <D.5657>:
      goto <D.5659>;
      <D.5647>:
      D.5633 = BIT_FIELD_REF <old_anchor, 8, 24>;
      D.5634 = D.5633 & 192;
      if (D.5634 == 0) goto <D.5660>; else goto <D.5661>;
      <D.5660>:
      D.5644 = BIT_FIELD_REF <new_anchor, 8, 24>;
      D.5645 = D.5644 & 192;
      D.5662 = D.5645 != 64;
      D.5663 = (long int) D.5662;
      D.5664 = __builtin_expect (D.5663, 0);
      if (D.5664 != 0) goto <D.5665>; else goto <D.5666>;
      <D.5665>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 513, "new_anchor.data.state == STATE_PARTIAL");
      <D.5666>:
      D.5667 = desc->heap;
      D.5668 = &D.5667->active;
      D.5669 = InterlockedCompareExchangePointer (D.5668, desc, 0B);
      if (D.5669 != 0B) goto <D.5670>; else goto <D.5671>;
      <D.5670>:
      heap_put_partial (desc);
      <D.5671>:
      <D.5661>:
      <D.5659>:
    }
  finally
    {
      old_anchor = {CLOBBER};
      new_anchor = {CLOBBER};
    }
}


list_remove_empty_desc (struct MonoLockFreeAllocSizeClass * sc)
{
  struct MonoLockFreeQueue * D.5672;
  <unnamed-unsigned:2> D.5675;
  struct MonoLockFreeAllocator * D.5679;
  struct MonoLockFreeAllocSizeClass * D.5680;
  _Bool D.5681;
  long int D.5682;
  long int D.5683;
  int num_non_empty;

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

    D.5672 = &sc->partial;
    desc = mono_lock_free_queue_dequeue (D.5672);
    if (desc == 0B) goto <D.5673>; else goto <D.5674>;
    <D.5673>:
    return;
    <D.5674>:
    D.5675 = desc->anchor.data.state;
    if (D.5675 == 2) goto <D.5676>; else goto <D.5677>;
    <D.5676>:
    desc_retire (desc);
    goto <D.5678>;
    <D.5677>:
    D.5679 = desc->heap;
    D.5680 = D.5679->sc;
    D.5681 = D.5680 != sc;
    D.5682 = (long int) D.5681;
    D.5683 = __builtin_expect (D.5682, 0);
    if (D.5683 != 0) goto <D.5684>; else goto <D.5685>;
    <D.5684>:
    monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 325, "desc->heap->sc == sc");
    <D.5685>:
    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.5686>; else goto <D.5687>;
    <D.5686>:
    return;
    <D.5687>:
    <D.5678>:
  }
  goto <D.5288>;
}


mono_lock_free_allocator_check_consistency (struct MonoLockFreeAllocator * heap)
{
  <unnamed-unsigned:2> D.5691;
  _Bool D.5692;
  long int D.5693;
  long int D.5694;
  int iftmp.12;
  <unnamed-unsigned:2> D.5700;
  <unnamed-unsigned:2> D.5702;
  _Bool D.5704;
  long int D.5705;
  long int D.5706;
  struct MonoLockFreeAllocSizeClass * D.5709;
  struct MonoLockFreeQueue * D.5710;
  gboolean D.5711;
  struct Descriptor * active;
  struct Descriptor * desc;

  active = heap->active;
  if (active != 0B) goto <D.5689>; else goto <D.5690>;
  <D.5689>:
  D.5691 = active->anchor.data.state;
  D.5692 = D.5691 != 1;
  D.5693 = (long int) D.5692;
  D.5694 = __builtin_expect (D.5693, 0);
  if (D.5694 != 0) goto <D.5695>; else goto <D.5696>;
  <D.5695>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 599, "active->anchor.data.state == STATE_PARTIAL");
  <D.5696>:
  descriptor_check_consistency (active, 0);
  <D.5690>:
  goto <D.5369>;
  <D.5368>:
  D.5700 = desc->anchor.data.state;
  if (D.5700 != 1) goto <D.5701>; else goto <D.5698>;
  <D.5701>:
  D.5702 = desc->anchor.data.state;
  if (D.5702 != 2) goto <D.5703>; else goto <D.5698>;
  <D.5703>:
  iftmp.12 = 1;
  goto <D.5699>;
  <D.5698>:
  iftmp.12 = 0;
  <D.5699>:
  D.5704 = iftmp.12 != 0;
  D.5705 = (long int) D.5704;
  D.5706 = __builtin_expect (D.5705, 0);
  if (D.5706 != 0) goto <D.5707>; else goto <D.5708>;
  <D.5707>:
  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.5708>:
  descriptor_check_consistency (desc, 0);
  <D.5369>:
  D.5709 = heap->sc;
  D.5710 = &D.5709->partial;
  desc = mono_lock_free_queue_dequeue (D.5710);
  if (desc != 0B) goto <D.5368>; else goto <D.5370>;
  <D.5370>:
  D.5711 = 1;
  return D.5711;
}


descriptor_check_consistency (struct Descriptor * desc, gboolean print)
{
  <unnamed-unsigned:15> D.5713;
  unsigned int D.5714;
  unsigned int D.5715;
  int max_count.13;
  long int D.5717;
  long int D.5718;
  sizetype D.5719;
  sizetype D.5720;
  bitsizetype D.5721;
  bitsizetype D.5722;
  sizetype D.5723;
  gboolean[0:D.5719] * linked.14;
  struct MonoLockFreeAllocator * D.5732;
  struct MonoLockFreeAllocSizeClass * D.5733;
  unsigned int D.5734;
  <unnamed-unsigned:2> D.5744;
  int D.5745;
  <unnamed-unsigned:15> D.5780;
  void * D.5781;
  unsigned int D.5782;
  sizetype D.5783;
  unsigned int max_count.15;
  int D.5792;
  void * saved_stack.16;
  int count;
  int max_count;
  gboolean linked[0:D.5719] [value-expr: *linked.14];
  int i;
  int last;
  unsigned int index;
  struct Descriptor * avail;

  saved_stack.16 = __builtin_stack_save ();
  try
    {
      D.5713 = desc->anchor.data.count;
      count = (int) D.5713;
      D.5714 = desc->slot_size;
      D.5715 = 16368 / D.5714;
      max_count = (int) D.5715;
      max_count.13 = max_count;
      D.5717 = (long int) max_count.13;
      D.5718 = D.5717 + -1;
      D.5719 = (sizetype) D.5718;
      D.5720 = (sizetype) max_count.13;
      D.5721 = (bitsizetype) D.5720;
      D.5722 = D.5721 * 32;
      D.5720 = (sizetype) max_count.13;
      D.5723 = D.5720 * 4;
      D.5720 = (sizetype) max_count.13;
      D.5721 = (bitsizetype) D.5720;
      D.5722 = D.5721 * 32;
      D.5720 = (sizetype) max_count.13;
      D.5723 = D.5720 * 4;
      linked.14 = __builtin_alloca_with_align (D.5723, 32);
      avail = desc_avail;
      goto <D.5349>;
      <D.5348>:
      if (desc == avail) goto <D.5725>; else goto <D.5726>;
      <D.5725>:
      if (print != 0) goto <D.5727>; else goto <D.5728>;
      <D.5727>:
      monoeg_g_print ("descriptor is in the available list\n");
      goto <D.5729>;
      <D.5728>:
      if (1 != 0) goto <D.5730>; else goto <D.5731>;
      <D.5730>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 546, "FALSE");
      <D.5731>:
      <D.5729>:
      <D.5726>:
      avail = avail->next;
      <D.5349>:
      if (avail != 0B) goto <D.5348>; else goto <D.5350>;
      <D.5350>:
      D.5714 = desc->slot_size;
      D.5732 = desc->heap;
      D.5733 = D.5732->sc;
      D.5734 = D.5733->slot_size;
      if (D.5714 != D.5734) goto <D.5735>; else goto <D.5736>;
      <D.5735>:
      if (print != 0) goto <D.5737>; else goto <D.5738>;
      <D.5737>:
      monoeg_g_print ("slot size doesn\'t match size class\n");
      goto <D.5739>;
      <D.5738>:
      if (1 != 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", 549, "FALSE");
      <D.5741>:
      <D.5739>:
      <D.5736>:
      if (print != 0) goto <D.5742>; else goto <D.5743>;
      <D.5742>:
      monoeg_g_print ("descriptor %p is ", desc);
      <D.5743>:
      D.5744 = desc->anchor.data.state;
      D.5745 = (int) D.5744;
      switch (D.5745) <default: <D.5355>, case 0: <D.5351>, case 1: <D.5353>, case 2: <D.5354>>
      <D.5351>:
      if (print != 0) goto <D.5746>; else goto <D.5747>;
      <D.5746>:
      monoeg_g_print ("full\n");
      <D.5747>:
      if (count != 0) goto <D.5748>; else goto <D.5749>;
      <D.5748>:
      if (print != 0) goto <D.5750>; else goto <D.5751>;
      <D.5750>:
      monoeg_g_print ("count is not zero: %d\n", count);
      goto <D.5752>;
      <D.5751>:
      if (1 != 0) goto <D.5753>; else goto <D.5754>;
      <D.5753>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 558, "FALSE");
      <D.5754>:
      <D.5752>:
      <D.5749>:
      goto <D.5352>;
      <D.5353>:
      if (print != 0) goto <D.5755>; else goto <D.5756>;
      <D.5755>:
      monoeg_g_print ("partial\n");
      <D.5756>:
      if (count >= max_count) goto <D.5757>; else goto <D.5758>;
      <D.5757>:
      if (print != 0) goto <D.5759>; else goto <D.5760>;
      <D.5759>:
      monoeg_g_print ("count too high: is %d but must be below %d\n", count, max_count);
      goto <D.5761>;
      <D.5760>:
      if (1 != 0) goto <D.5762>; else goto <D.5763>;
      <D.5762>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 563, "FALSE");
      <D.5763>:
      <D.5761>:
      <D.5758>:
      goto <D.5352>;
      <D.5354>:
      if (print != 0) goto <D.5764>; else goto <D.5765>;
      <D.5764>:
      monoeg_g_print ("empty\n");
      <D.5765>:
      if (count != max_count) goto <D.5766>; else goto <D.5767>;
      <D.5766>:
      if (print != 0) goto <D.5768>; else goto <D.5769>;
      <D.5768>:
      monoeg_g_print ("count is wrong: is %d but should be %d\n", count, max_count);
      goto <D.5770>;
      <D.5769>:
      if (1 != 0) goto <D.5771>; else goto <D.5772>;
      <D.5771>:
      monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 568, "FALSE");
      <D.5772>:
      <D.5770>:
      <D.5767>:
      goto <D.5352>;
      <D.5355>:
      if (1 != 0) goto <D.5773>; else goto <D.5774>;
      <D.5773>:
      if (print != 0) goto <D.5775>; else goto <D.5776>;
      <D.5775>:
      monoeg_g_print ("invalid state\n");
      goto <D.5777>;
      <D.5776>:
      if (1 != 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", 571, "FALSE");
      <D.5779>:
      <D.5777>:
      <D.5774>:
      <D.5352>:
      i = 0;
      goto <D.5357>;
      <D.5356>:
      *linked.14[i] = 0;
      i = i + 1;
      <D.5357>:
      if (i < max_count) goto <D.5356>; else goto <D.5358>;
      <D.5358>:
      D.5780 = desc->anchor.data.avail;
      index = (unsigned int) D.5780;
      last = -1;
      i = 0;
      goto <D.5362>;
      <D.5361>:
      {
        void * addr;

        D.5781 = desc->sb;
        D.5714 = desc->slot_size;
        D.5782 = D.5714 * index;
        D.5783 = (sizetype) D.5782;
        addr = D.5781 + D.5783;
        max_count.15 = (unsigned int) max_count;
        if (max_count.15 <= index) goto <D.5785>; else goto <D.5786>;
        <D.5785>:
        if (print != 0) goto <D.5787>; else goto <D.5788>;
        <D.5787>:
        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.5789>;
        <D.5788>:
        if (1 != 0) goto <D.5790>; else goto <D.5791>;
        <D.5790>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 583, "FALSE");
        <D.5791>:
        <D.5789>:
        <D.5786>:
        D.5792 = *linked.14[index];
        if (D.5792 != 0) goto <D.5793>; else goto <D.5794>;
        <D.5793>:
        if (print != 0) goto <D.5795>; else goto <D.5796>;
        <D.5795>:
        monoeg_g_print ("%dth available slot %d linked twice\n", i, index);
        goto <D.5797>;
        <D.5796>:
        if (1 != 0) goto <D.5798>; else goto <D.5799>;
        <D.5798>:
        monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "lock-free-alloc.c", 584, "FALSE");
        <D.5799>:
        <D.5797>:
        <D.5794>:
        D.5792 = *linked.14[index];
        if (D.5792 != 0) goto <D.5360>; else goto <D.5800>;
        <D.5800>:
        *linked.14[index] = 1;
        last = (int) index;
        index = MEM[(unsigned int *)addr];
      }
      i = i + 1;
      <D.5362>:
      if (i < count) goto <D.5361>; else goto <D.5360>;
      <D.5360>:
    }
  finally
    {
      __builtin_stack_restore (saved_stack.16);
    }
}


mono_lock_free_allocator_init_size_class (struct MonoLockFreeAllocSizeClass * sc, unsigned int slot_size)
{
  _Bool D.5803;
  long int D.5804;
  long int D.5805;
  struct MonoLockFreeQueue * D.5808;

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


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


