mono_value_hash_table_new (guint (*GHashFunc) (const void *) hash_func, gboolean (*GEqualFunc) (const void *, const void *) key_equal_func, void * (*MonoValueHashKeyExtractFunc) (void *) key_extract)
{
  int D.8663;
  unsigned int D.8664;
  unsigned int D.8665;
  void * D.8666;
  struct MonoValueHashTable * D.8667;
  struct MonoValueHashTable * hash;

  if (hash_func == 0B) goto <D.8659>; else goto <D.8660>;
  <D.8659>:
  hash_func = monoeg_g_direct_hash;
  <D.8660>:
  if (key_equal_func == 0B) goto <D.8661>; else goto <D.8662>;
  <D.8661>:
  key_equal_func = monoeg_g_direct_equal;
  <D.8662>:
  hash = monoeg_malloc0 (40);
  hash->hash_func = hash_func;
  hash->key_equal_func = key_equal_func;
  hash->key_extract_func = key_extract;
  mono_value_hash_table_set_shift (hash, 3);
  D.8663 = hash->table_size;
  D.8664 = (unsigned int) D.8663;
  D.8665 = D.8664 * 4;
  D.8666 = monoeg_malloc0 (D.8665);
  hash->table = D.8666;
  D.8667 = hash;
  return D.8667;
}


mono_value_hash_table_set_shift (struct MonoValueHashTable * hash_table, gint shift)
{
  int D.8669;
  int mask.0;
  gint i;
  guint mask;

  mask = 0;
  D.8669 = 1 << shift;
  hash_table->table_size = D.8669;
  i = 0;
  goto <D.8560>;
  <D.8559>:
  mask = mask << 1;
  mask = mask | 1;
  i = i + 1;
  <D.8560>:
  if (i < shift) goto <D.8559>; else goto <D.8561>;
  <D.8561>:
  mask.0 = (int) mask;
  hash_table->table_mask = mask.0;
}


mono_value_hash_table_insert (struct MonoValueHashTable * hash, void * key, void * value)
{
  mono_value_hash_table_insert_replace (hash, key, value, 1);
}


mono_value_hash_table_insert_replace (struct MonoValueHashTable * hash, void * key, void * value, gboolean replace)
{
  _Bool D.8671;
  long int D.8672;
  long int D.8673;
  void * (*<T1ac0>) (void *) D.8676;
  void * D.8677;
  _Bool D.8678;
  long int D.8679;
  long int D.8680;
  guint (*<T18ba>) (const void *) D.8685;
  int D.8686;
  unsigned int D.8687;
  struct Slot * D.8688;
  unsigned int D.8689;
  void * D.8690;
  unsigned int D.8691;
  unsigned int D.8692;
  int D.8695;
  void (*<T180e>) (void *) D.8699;
  void (*<T180e>) (void *) D.8702;
  void * D.8705;
  unsigned int D.8706;
  unsigned int D.8713;
  int D.8715;
  int D.8716;
  int D.8717;
  int D.8718;
  guint hashcode;
  struct Slot * s;
  guint s_index;
  gboolean (*GEqualFunc) (const void *, const void *) equal;
  guint first_tombstone;
  gboolean have_tombstone;
  guint step;

  first_tombstone = 0;
  have_tombstone = 0;
  step = 0;
  D.8671 = value == 0B;
  D.8672 = (long int) D.8671;
  D.8673 = __builtin_expect (D.8672, 0);
  if (D.8673 != 0) goto <D.8674>; else goto <D.8675>;
  <D.8674>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 222, "value");
  <D.8675>:
  D.8676 = hash->key_extract_func;
  D.8677 = D.8676 (value);
  D.8678 = D.8677 != key;
  D.8679 = (long int) D.8678;
  D.8680 = __builtin_expect (D.8679, 0);
  if (D.8680 != 0) goto <D.8681>; else goto <D.8682>;
  <D.8681>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 223, "hash->key_extract_func (value) == key");
  <D.8682>:
  if (hash == 0B) goto <D.8683>; else goto <D.8684>;
  <D.8683>:
  monoeg_g_log (0B, 8, "%s:%d: assertion \'%s\' failed", "mono-value-hash.c", 225, "hash != NULL");
  return;
  <D.8684>:
  D.8685 = hash->hash_func;
  hashcode = D.8685 (key);
  D.8686 = hash->table_mask;
  D.8687 = (unsigned int) D.8686;
  s_index = D.8687 & hashcode;
  D.8688 = hash->table;
  D.8689 = s_index * 4;
  s = D.8688 + D.8689;
  equal = hash->key_equal_func;
  goto <D.8621>;
  <D.8620>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.8690 = s->value;
    D.8691 = (unsigned int) D.8690;
    D.8692 = D.8691 & 4294967292;
    s_value = (void *) D.8692;
    D.8676 = hash->key_extract_func;
    s_key = D.8676 (s_value);
    D.8685 = hash->hash_func;
    s_key_hash = D.8685 (s_key);
    if (s_key_hash == hashcode) goto <D.8694>; else goto <D.8693>;
    <D.8694>:
    D.8695 = equal (s_key, key);
    if (D.8695 != 0) goto <D.8696>; else goto <D.8693>;
    <D.8696>:
    if (replace != 0) goto <D.8697>; else goto <D.8698>;
    <D.8697>:
    D.8699 = hash->key_destroy_func;
    if (D.8699 != 0B) goto <D.8700>; else goto <D.8701>;
    <D.8700>:
    D.8699 = hash->key_destroy_func;
    D.8699 (s_key);
    <D.8701>:
    <D.8698>:
    D.8702 = hash->value_destroy_func;
    if (D.8702 != 0B) goto <D.8703>; else goto <D.8704>;
    <D.8703>:
    D.8702 = hash->value_destroy_func;
    D.8690 = s->value;
    D.8691 = (unsigned int) D.8690;
    D.8692 = D.8691 & 4294967292;
    D.8705 = (void *) D.8692;
    D.8702 (D.8705);
    <D.8704>:
    s->value = value;
    return;
    <D.8693>:
    D.8690 = s->value;
    D.8691 = (unsigned int) D.8690;
    D.8706 = D.8691 & 1;
    if (D.8706 != 0) goto <D.8707>; else goto <D.8708>;
    <D.8707>:
    if (have_tombstone == 0) goto <D.8709>; else goto <D.8710>;
    <D.8709>:
    first_tombstone = s_index;
    have_tombstone = 1;
    <D.8710>:
    <D.8708>:
    step = step + 1;
    s_index = s_index + step;
    D.8686 = hash->table_mask;
    D.8687 = (unsigned int) D.8686;
    s_index = D.8687 & s_index;
    D.8688 = hash->table;
    D.8689 = s_index * 4;
    s = D.8688 + D.8689;
  }
  <D.8621>:
  D.8690 = s->value;
  D.8691 = (unsigned int) D.8690;
  if (D.8691 != 0) goto <D.8620>; else goto <D.8622>;
  <D.8622>:
  if (have_tombstone != 0) goto <D.8711>; else goto <D.8712>;
  <D.8711>:
  D.8688 = hash->table;
  D.8713 = first_tombstone * 4;
  s = D.8688 + D.8713;
  goto <D.8714>;
  <D.8712>:
  D.8715 = hash->n_occupied;
  D.8716 = D.8715 + 1;
  hash->n_occupied = D.8716;
  <D.8714>:
  s->value = value;
  D.8717 = hash->in_use;
  D.8718 = D.8717 + 1;
  hash->in_use = D.8718;
  rehash (hash);
}


rehash (struct MonoValueHashTable * hash)
{
  int D.8723;
  int D.8724;
  int D.8726;
  int D.8727;
  int n_occupied;
  int table_size;

  n_occupied = hash->n_occupied;
  table_size = hash->table_size;
  D.8723 = hash->in_use;
  D.8724 = D.8723 * 4;
  if (D.8724 < table_size) goto <D.8725>; else goto <D.8720>;
  <D.8725>:
  if (table_size > 8) goto <D.8721>; else goto <D.8720>;
  <D.8720>:
  D.8726 = n_occupied / 16;
  D.8727 = D.8726 + n_occupied;
  if (D.8727 >= table_size) goto <D.8721>; else goto <D.8722>;
  <D.8721>:
  do_rehash (hash);
  <D.8722>:
}


do_rehash (struct MonoValueHashTable * hash)
{
  int D.8728;
  int D.8729;
  int D.8730;
  unsigned int D.8731;
  unsigned int D.8732;
  void * D.8733;
  unsigned int i.1;
  unsigned int D.8735;
  void * D.8738;
  unsigned int D.8739;
  unsigned int D.8741;
  unsigned int D.8742;
  void * (*<T1ac0>) (void *) D.8743;
  guint (*<T18ba>) (const void *) D.8744;
  unsigned int D.8745;
  int D.8746;
  unsigned int D.8747;
  struct Slot * D.8748;
  unsigned int D.8749;
  void * D.8750;
  unsigned int D.8751;
  int i;
  int old_size;
  struct Slot * old_table;

  old_size = hash->table_size;
  old_table = hash->table;
  D.8728 = hash->in_use;
  D.8729 = D.8728 * 2;
  mono_value_hash_table_set_shift_from_size (hash, D.8729);
  D.8730 = hash->table_size;
  D.8731 = (unsigned int) D.8730;
  D.8732 = D.8731 * 4;
  D.8733 = monoeg_malloc0 (D.8732);
  hash->table = D.8733;
  i = 0;
  goto <D.8597>;
  <D.8596>:
  {
    struct Slot * s;
    struct Slot * new_s;
    guint hash_val;
    guint step;
    void * s_value;
    void * s_key;

    i.1 = (unsigned int) i;
    D.8735 = i.1 * 4;
    s = old_table + D.8735;
    step = 0;
    D.8738 = s->value;
    D.8739 = (unsigned int) D.8738;
    if (D.8739 == 0) goto <D.8736>; else goto <D.8740>;
    <D.8740>:
    D.8738 = s->value;
    D.8739 = (unsigned int) D.8738;
    D.8741 = D.8739 & 1;
    if (D.8741 != 0) goto <D.8736>; else goto <D.8737>;
    <D.8736>:
    // predicted unlikely by continue predictor.
    goto <D.8592>;
    <D.8737>:
    D.8738 = s->value;
    D.8739 = (unsigned int) D.8738;
    D.8742 = D.8739 & 4294967292;
    s_value = (void *) D.8742;
    D.8743 = hash->key_extract_func;
    s_key = D.8743 (s_value);
    D.8744 = hash->hash_func;
    D.8745 = D.8744 (s_key);
    D.8746 = hash->table_mask;
    D.8747 = (unsigned int) D.8746;
    hash_val = D.8745 & D.8747;
    D.8748 = hash->table;
    D.8749 = hash_val * 4;
    new_s = D.8748 + D.8749;
    goto <D.8594>;
    <D.8593>:
    step = step + 1;
    hash_val = hash_val + step;
    D.8746 = hash->table_mask;
    D.8747 = (unsigned int) D.8746;
    hash_val = D.8747 & hash_val;
    D.8748 = hash->table;
    D.8749 = hash_val * 4;
    new_s = D.8748 + D.8749;
    <D.8594>:
    D.8750 = new_s->value;
    D.8751 = (unsigned int) D.8750;
    if (D.8751 != 0) goto <D.8593>; else goto <D.8595>;
    <D.8595>:
    *new_s = *s;
  }
  <D.8592>:
  i = i + 1;
  <D.8597>:
  if (i < old_size) goto <D.8596>; else goto <D.8598>;
  <D.8598>:
  monoeg_g_free (old_table);
  D.8728 = hash->in_use;
  hash->n_occupied = D.8728;
}


mono_value_hash_table_set_shift_from_size (struct MonoValueHashTable * hash_table, gint size)
{
  gint shift;

  shift = mono_value_hash_table_find_closest_shift (size);
  shift = MAX_EXPR <shift, 3>;
  mono_value_hash_table_set_shift (hash_table, shift);
}


mono_value_hash_table_find_closest_shift (gint n)
{
  gint D.8752;
  gint i;

  i = 0;
  goto <D.8567>;
  <D.8566>:
  n = n >> 1;
  i = i + 1;
  <D.8567>:
  if (n != 0) goto <D.8566>; else goto <D.8568>;
  <D.8568>:
  D.8752 = i;
  return D.8752;
}


mono_value_hash_table_lookup (struct MonoValueHashTable * hash, const void * key)
{
  void * D.8756;
  void * D.8757;
  unsigned int D.8758;
  unsigned int D.8759;
  struct Slot * slot;

  slot = lookup_internal (hash, key);
  if (slot != 0B) goto <D.8754>; else goto <D.8755>;
  <D.8754>:
  D.8757 = slot->value;
  D.8758 = (unsigned int) D.8757;
  D.8759 = D.8758 & 4294967292;
  D.8756 = (void *) D.8759;
  return D.8756;
  <D.8755>:
  D.8756 = 0B;
  return D.8756;
}


lookup_internal (struct MonoValueHashTable * hash, const void * key)
{
  guint (*<T18ba>) (const void *) D.8761;
  int D.8762;
  unsigned int D.8763;
  struct Slot * D.8764;
  unsigned int D.8765;
  void * D.8766;
  unsigned int D.8767;
  unsigned int D.8768;
  void * (*<T1ac0>) (void *) D.8769;
  void * D.8772;
  int D.8773;
  struct Slot * D.8776;
  gboolean (*GEqualFunc) (const void *, const void *) equal;
  struct Slot * s;
  guint hashcode;
  guint s_index;
  guint step;

  step = 0;
  D.8761 = hash->hash_func;
  hashcode = D.8761 (key);
  D.8762 = hash->table_mask;
  D.8763 = (unsigned int) D.8762;
  s_index = D.8763 & hashcode;
  D.8764 = hash->table;
  D.8765 = s_index * 4;
  s = D.8764 + D.8765;
  equal = hash->key_equal_func;
  goto <D.8641>;
  <D.8640>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.8766 = s->value;
    D.8767 = (unsigned int) D.8766;
    D.8768 = D.8767 & 4294967292;
    s_value = (void *) D.8768;
    D.8769 = hash->key_extract_func;
    s_key = D.8769 (s_value);
    D.8761 = hash->hash_func;
    s_key_hash = D.8761 (s_key);
    if (s_key_hash == hashcode) goto <D.8770>; else goto <D.8771>;
    <D.8770>:
    D.8769 = hash->key_extract_func;
    D.8772 = D.8769 (s_value);
    D.8773 = equal (D.8772, key);
    if (D.8773 != 0) goto <D.8774>; else goto <D.8775>;
    <D.8774>:
    D.8776 = s;
    return D.8776;
    <D.8775>:
    <D.8771>:
    step = step + 1;
    s_index = s_index + step;
    D.8762 = hash->table_mask;
    D.8763 = (unsigned int) D.8762;
    s_index = D.8763 & s_index;
    D.8764 = hash->table;
    D.8765 = s_index * 4;
    s = D.8764 + D.8765;
  }
  <D.8641>:
  D.8766 = s->value;
  D.8767 = (unsigned int) D.8766;
  if (D.8767 != 0) goto <D.8640>; else goto <D.8642>;
  <D.8642>:
  D.8776 = 0B;
  return D.8776;
}


mono_value_hash_table_destroy (struct MonoValueHashTable * hash)
{
  struct Slot * D.8780;
  unsigned int i.2;
  unsigned int D.8782;
  void * D.8783;
  unsigned int D.8784;
  unsigned int D.8787;
  void (*<T180e>) (void *) D.8790;
  void * (*<T1ac0>) (void *) D.8793;
  unsigned int D.8794;
  void * D.8795;
  void * D.8796;
  void (*<T180e>) (void *) D.8797;
  int D.8800;
  int i;

  if (hash == 0B) goto <D.8778>; else goto <D.8779>;
  <D.8778>:
  monoeg_g_log (0B, 8, "%s:%d: assertion \'%s\' failed", "mono-value-hash.c", 324, "hash != NULL");
  return;
  <D.8779>:
  i = 0;
  goto <D.8654>;
  <D.8653>:
  {
    struct Slot * s;

    D.8780 = hash->table;
    i.2 = (unsigned int) i;
    D.8782 = i.2 * 4;
    s = D.8780 + D.8782;
    D.8783 = s->value;
    D.8784 = (unsigned int) D.8783;
    if (D.8784 != 0) goto <D.8785>; else goto <D.8786>;
    <D.8785>:
    D.8783 = s->value;
    D.8784 = (unsigned int) D.8783;
    D.8787 = D.8784 & 1;
    if (D.8787 == 0) goto <D.8788>; else goto <D.8789>;
    <D.8788>:
    D.8790 = hash->key_destroy_func;
    if (D.8790 != 0B) goto <D.8791>; else goto <D.8792>;
    <D.8791>:
    D.8790 = hash->key_destroy_func;
    D.8793 = hash->key_extract_func;
    D.8783 = s->value;
    D.8784 = (unsigned int) D.8783;
    D.8794 = D.8784 & 4294967292;
    D.8795 = (void *) D.8794;
    D.8796 = D.8793 (D.8795);
    D.8790 (D.8796);
    <D.8792>:
    D.8797 = hash->value_destroy_func;
    if (D.8797 != 0B) goto <D.8798>; else goto <D.8799>;
    <D.8798>:
    D.8797 = hash->value_destroy_func;
    D.8783 = s->value;
    D.8784 = (unsigned int) D.8783;
    D.8794 = D.8784 & 4294967292;
    D.8795 = (void *) D.8794;
    D.8797 (D.8795);
    <D.8799>:
    <D.8789>:
    <D.8786>:
  }
  i = i + 1;
  <D.8654>:
  D.8800 = hash->table_size;
  if (D.8800 > i) goto <D.8653>; else goto <D.8655>;
  <D.8655>:
  D.8780 = hash->table;
  monoeg_g_free (D.8780);
  monoeg_g_free (hash);
}


