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.5822;
  unsigned int D.5823;
  unsigned int D.5824;
  void * D.5825;
  struct MonoValueHashTable * D.5826;
  struct MonoValueHashTable * hash;

  if (hash_func == 0B) goto <D.5818>; else goto <D.5819>;
  <D.5818>:
  hash_func = monoeg_g_direct_hash;
  <D.5819>:
  if (key_equal_func == 0B) goto <D.5820>; else goto <D.5821>;
  <D.5820>:
  key_equal_func = monoeg_g_direct_equal;
  <D.5821>:
  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.5822 = hash->table_size;
  D.5823 = (unsigned int) D.5822;
  D.5824 = D.5823 * 4;
  D.5825 = monoeg_malloc0 (D.5824);
  hash->table = D.5825;
  D.5826 = hash;
  return D.5826;
}


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

  mask = 0;
  D.5828 = 1 << shift;
  hash_table->table_size = D.5828;
  i = 0;
  goto <D.5721>;
  <D.5720>:
  mask = mask << 1;
  mask = mask | 1;
  i = i + 1;
  <D.5721>:
  if (i < shift) goto <D.5720>; else goto <D.5722>;
  <D.5722>:
  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.5830;
  long int D.5831;
  long int D.5832;
  void * (*<Tfc1>) (void *) D.5835;
  void * D.5836;
  _Bool D.5837;
  long int D.5838;
  long int D.5839;
  guint (*<Tdb9>) (const void *) D.5844;
  int D.5845;
  unsigned int D.5846;
  struct Slot * D.5847;
  unsigned int D.5848;
  void * D.5849;
  unsigned int D.5850;
  unsigned int D.5851;
  int D.5854;
  void (*<Td0d>) (void *) D.5858;
  void (*<Td0d>) (void *) D.5861;
  void * D.5864;
  unsigned int D.5865;
  unsigned int D.5872;
  int D.5874;
  int D.5875;
  int D.5876;
  int D.5877;
  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.5830 = value == 0B;
  D.5831 = (long int) D.5830;
  D.5832 = __builtin_expect (D.5831, 0);
  if (D.5832 != 0) goto <D.5833>; else goto <D.5834>;
  <D.5833>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 222, "value");
  <D.5834>:
  D.5835 = hash->key_extract_func;
  D.5836 = D.5835 (value);
  D.5837 = D.5836 != key;
  D.5838 = (long int) D.5837;
  D.5839 = __builtin_expect (D.5838, 0);
  if (D.5839 != 0) goto <D.5840>; else goto <D.5841>;
  <D.5840>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 223, "hash->key_extract_func (value) == key");
  <D.5841>:
  if (hash == 0B) goto <D.5842>; else goto <D.5843>;
  <D.5842>:
  monoeg_g_log (0B, 8, "%s:%d: assertion \'%s\' failed", "mono-value-hash.c", 225, "hash != NULL");
  return;
  <D.5843>:
  D.5844 = hash->hash_func;
  hashcode = D.5844 (key);
  D.5845 = hash->table_mask;
  D.5846 = (unsigned int) D.5845;
  s_index = D.5846 & hashcode;
  D.5847 = hash->table;
  D.5848 = s_index * 4;
  s = D.5847 + D.5848;
  equal = hash->key_equal_func;
  goto <D.5782>;
  <D.5781>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.5849 = s->value;
    D.5850 = (unsigned int) D.5849;
    D.5851 = D.5850 & 4294967292;
    s_value = (void *) D.5851;
    D.5835 = hash->key_extract_func;
    s_key = D.5835 (s_value);
    D.5844 = hash->hash_func;
    s_key_hash = D.5844 (s_key);
    if (s_key_hash == hashcode) goto <D.5853>; else goto <D.5852>;
    <D.5853>:
    D.5854 = equal (s_key, key);
    if (D.5854 != 0) goto <D.5855>; else goto <D.5852>;
    <D.5855>:
    if (replace != 0) goto <D.5856>; else goto <D.5857>;
    <D.5856>:
    D.5858 = hash->key_destroy_func;
    if (D.5858 != 0B) goto <D.5859>; else goto <D.5860>;
    <D.5859>:
    D.5858 = hash->key_destroy_func;
    D.5858 (s_key);
    <D.5860>:
    <D.5857>:
    D.5861 = hash->value_destroy_func;
    if (D.5861 != 0B) goto <D.5862>; else goto <D.5863>;
    <D.5862>:
    D.5861 = hash->value_destroy_func;
    D.5849 = s->value;
    D.5850 = (unsigned int) D.5849;
    D.5851 = D.5850 & 4294967292;
    D.5864 = (void *) D.5851;
    D.5861 (D.5864);
    <D.5863>:
    s->value = value;
    return;
    <D.5852>:
    D.5849 = s->value;
    D.5850 = (unsigned int) D.5849;
    D.5865 = D.5850 & 1;
    if (D.5865 != 0) goto <D.5866>; else goto <D.5867>;
    <D.5866>:
    if (have_tombstone == 0) goto <D.5868>; else goto <D.5869>;
    <D.5868>:
    first_tombstone = s_index;
    have_tombstone = 1;
    <D.5869>:
    <D.5867>:
    step = step + 1;
    s_index = s_index + step;
    D.5845 = hash->table_mask;
    D.5846 = (unsigned int) D.5845;
    s_index = D.5846 & s_index;
    D.5847 = hash->table;
    D.5848 = s_index * 4;
    s = D.5847 + D.5848;
  }
  <D.5782>:
  D.5849 = s->value;
  D.5850 = (unsigned int) D.5849;
  if (D.5850 != 0) goto <D.5781>; else goto <D.5783>;
  <D.5783>:
  if (have_tombstone != 0) goto <D.5870>; else goto <D.5871>;
  <D.5870>:
  D.5847 = hash->table;
  D.5872 = first_tombstone * 4;
  s = D.5847 + D.5872;
  goto <D.5873>;
  <D.5871>:
  D.5874 = hash->n_occupied;
  D.5875 = D.5874 + 1;
  hash->n_occupied = D.5875;
  <D.5873>:
  s->value = value;
  D.5876 = hash->in_use;
  D.5877 = D.5876 + 1;
  hash->in_use = D.5877;
  rehash (hash);
}


rehash (struct MonoValueHashTable * hash)
{
  int D.5882;
  int D.5883;
  int D.5885;
  int D.5886;
  int n_occupied;
  int table_size;

  n_occupied = hash->n_occupied;
  table_size = hash->table_size;
  D.5882 = hash->in_use;
  D.5883 = D.5882 * 4;
  if (D.5883 < table_size) goto <D.5884>; else goto <D.5879>;
  <D.5884>:
  if (table_size > 8) goto <D.5880>; else goto <D.5879>;
  <D.5879>:
  D.5885 = n_occupied / 16;
  D.5886 = D.5885 + n_occupied;
  if (D.5886 >= table_size) goto <D.5880>; else goto <D.5881>;
  <D.5880>:
  do_rehash (hash);
  <D.5881>:
}


do_rehash (struct MonoValueHashTable * hash)
{
  int D.5887;
  int D.5888;
  int D.5889;
  unsigned int D.5890;
  unsigned int D.5891;
  void * D.5892;
  unsigned int i.1;
  unsigned int D.5894;
  void * D.5897;
  unsigned int D.5898;
  unsigned int D.5900;
  unsigned int D.5901;
  void * (*<Tfc1>) (void *) D.5902;
  guint (*<Tdb9>) (const void *) D.5903;
  unsigned int D.5904;
  int D.5905;
  unsigned int D.5906;
  struct Slot * D.5907;
  unsigned int D.5908;
  void * D.5909;
  unsigned int D.5910;
  int i;
  int old_size;
  struct Slot * old_table;

  old_size = hash->table_size;
  old_table = hash->table;
  D.5887 = hash->in_use;
  D.5888 = D.5887 * 2;
  mono_value_hash_table_set_shift_from_size (hash, D.5888);
  D.5889 = hash->table_size;
  D.5890 = (unsigned int) D.5889;
  D.5891 = D.5890 * 4;
  D.5892 = monoeg_malloc0 (D.5891);
  hash->table = D.5892;
  i = 0;
  goto <D.5758>;
  <D.5757>:
  {
    struct Slot * s;
    struct Slot * new_s;
    guint hash_val;
    guint step;
    void * s_value;
    void * s_key;

    i.1 = (unsigned int) i;
    D.5894 = i.1 * 4;
    s = old_table + D.5894;
    step = 0;
    D.5897 = s->value;
    D.5898 = (unsigned int) D.5897;
    if (D.5898 == 0) goto <D.5895>; else goto <D.5899>;
    <D.5899>:
    D.5897 = s->value;
    D.5898 = (unsigned int) D.5897;
    D.5900 = D.5898 & 1;
    if (D.5900 != 0) goto <D.5895>; else goto <D.5896>;
    <D.5895>:
    // predicted unlikely by continue predictor.
    goto <D.5753>;
    <D.5896>:
    D.5897 = s->value;
    D.5898 = (unsigned int) D.5897;
    D.5901 = D.5898 & 4294967292;
    s_value = (void *) D.5901;
    D.5902 = hash->key_extract_func;
    s_key = D.5902 (s_value);
    D.5903 = hash->hash_func;
    D.5904 = D.5903 (s_key);
    D.5905 = hash->table_mask;
    D.5906 = (unsigned int) D.5905;
    hash_val = D.5904 & D.5906;
    D.5907 = hash->table;
    D.5908 = hash_val * 4;
    new_s = D.5907 + D.5908;
    goto <D.5755>;
    <D.5754>:
    step = step + 1;
    hash_val = hash_val + step;
    D.5905 = hash->table_mask;
    D.5906 = (unsigned int) D.5905;
    hash_val = D.5906 & hash_val;
    D.5907 = hash->table;
    D.5908 = hash_val * 4;
    new_s = D.5907 + D.5908;
    <D.5755>:
    D.5909 = new_s->value;
    D.5910 = (unsigned int) D.5909;
    if (D.5910 != 0) goto <D.5754>; else goto <D.5756>;
    <D.5756>:
    *new_s = *s;
  }
  <D.5753>:
  i = i + 1;
  <D.5758>:
  if (i < old_size) goto <D.5757>; else goto <D.5759>;
  <D.5759>:
  monoeg_g_free (old_table);
  D.5887 = hash->in_use;
  hash->n_occupied = D.5887;
}


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.5911;
  gint i;

  i = 0;
  goto <D.5728>;
  <D.5727>:
  n = n >> 1;
  i = i + 1;
  <D.5728>:
  if (n != 0) goto <D.5727>; else goto <D.5729>;
  <D.5729>:
  D.5911 = i;
  return D.5911;
}


mono_value_hash_table_lookup (struct MonoValueHashTable * hash, const void * key)
{
  void * D.5915;
  void * D.5916;
  unsigned int D.5917;
  unsigned int D.5918;
  struct Slot * slot;

  slot = lookup_internal (hash, key);
  if (slot != 0B) goto <D.5913>; else goto <D.5914>;
  <D.5913>:
  D.5916 = slot->value;
  D.5917 = (unsigned int) D.5916;
  D.5918 = D.5917 & 4294967292;
  D.5915 = (void *) D.5918;
  return D.5915;
  <D.5914>:
  D.5915 = 0B;
  return D.5915;
}


lookup_internal (struct MonoValueHashTable * hash, const void * key)
{
  guint (*<Tdb9>) (const void *) D.5920;
  int D.5921;
  unsigned int D.5922;
  struct Slot * D.5923;
  unsigned int D.5924;
  void * D.5925;
  unsigned int D.5926;
  unsigned int D.5927;
  void * (*<Tfc1>) (void *) D.5928;
  void * D.5931;
  int D.5932;
  struct Slot * D.5935;
  gboolean (*GEqualFunc) (const void *, const void *) equal;
  struct Slot * s;
  guint hashcode;
  guint s_index;
  guint step;

  step = 0;
  D.5920 = hash->hash_func;
  hashcode = D.5920 (key);
  D.5921 = hash->table_mask;
  D.5922 = (unsigned int) D.5921;
  s_index = D.5922 & hashcode;
  D.5923 = hash->table;
  D.5924 = s_index * 4;
  s = D.5923 + D.5924;
  equal = hash->key_equal_func;
  goto <D.5802>;
  <D.5801>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.5925 = s->value;
    D.5926 = (unsigned int) D.5925;
    D.5927 = D.5926 & 4294967292;
    s_value = (void *) D.5927;
    D.5928 = hash->key_extract_func;
    s_key = D.5928 (s_value);
    D.5920 = hash->hash_func;
    s_key_hash = D.5920 (s_key);
    if (s_key_hash == hashcode) goto <D.5929>; else goto <D.5930>;
    <D.5929>:
    D.5928 = hash->key_extract_func;
    D.5931 = D.5928 (s_value);
    D.5932 = equal (D.5931, key);
    if (D.5932 != 0) goto <D.5933>; else goto <D.5934>;
    <D.5933>:
    D.5935 = s;
    return D.5935;
    <D.5934>:
    <D.5930>:
    step = step + 1;
    s_index = s_index + step;
    D.5921 = hash->table_mask;
    D.5922 = (unsigned int) D.5921;
    s_index = D.5922 & s_index;
    D.5923 = hash->table;
    D.5924 = s_index * 4;
    s = D.5923 + D.5924;
  }
  <D.5802>:
  D.5925 = s->value;
  D.5926 = (unsigned int) D.5925;
  if (D.5926 != 0) goto <D.5801>; else goto <D.5803>;
  <D.5803>:
  D.5935 = 0B;
  return D.5935;
}


mono_value_hash_table_destroy (struct MonoValueHashTable * hash)
{
  struct Slot * D.5939;
  unsigned int i.2;
  unsigned int D.5941;
  void * D.5942;
  unsigned int D.5943;
  unsigned int D.5946;
  void (*<Td0d>) (void *) D.5949;
  void * (*<Tfc1>) (void *) D.5952;
  unsigned int D.5953;
  void * D.5954;
  void * D.5955;
  void (*<Td0d>) (void *) D.5956;
  int D.5959;
  int i;

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

    D.5939 = hash->table;
    i.2 = (unsigned int) i;
    D.5941 = i.2 * 4;
    s = D.5939 + D.5941;
    D.5942 = s->value;
    D.5943 = (unsigned int) D.5942;
    if (D.5943 != 0) goto <D.5944>; else goto <D.5945>;
    <D.5944>:
    D.5942 = s->value;
    D.5943 = (unsigned int) D.5942;
    D.5946 = D.5943 & 1;
    if (D.5946 == 0) goto <D.5947>; else goto <D.5948>;
    <D.5947>:
    D.5949 = hash->key_destroy_func;
    if (D.5949 != 0B) goto <D.5950>; else goto <D.5951>;
    <D.5950>:
    D.5949 = hash->key_destroy_func;
    D.5952 = hash->key_extract_func;
    D.5942 = s->value;
    D.5943 = (unsigned int) D.5942;
    D.5953 = D.5943 & 4294967292;
    D.5954 = (void *) D.5953;
    D.5955 = D.5952 (D.5954);
    D.5949 (D.5955);
    <D.5951>:
    D.5956 = hash->value_destroy_func;
    if (D.5956 != 0B) goto <D.5957>; else goto <D.5958>;
    <D.5957>:
    D.5956 = hash->value_destroy_func;
    D.5942 = s->value;
    D.5943 = (unsigned int) D.5942;
    D.5953 = D.5943 & 4294967292;
    D.5954 = (void *) D.5953;
    D.5956 (D.5954);
    <D.5958>:
    <D.5948>:
    <D.5945>:
  }
  i = i + 1;
  <D.5815>:
  D.5959 = hash->table_size;
  if (D.5959 > i) goto <D.5814>; else goto <D.5816>;
  <D.5816>:
  D.5939 = hash->table;
  monoeg_g_free (D.5939);
  monoeg_g_free (hash);
}


