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.6167;
  long unsigned int D.6168;
  long unsigned int D.6169;
  void * D.6170;
  struct MonoValueHashTable * D.6171;
  struct MonoValueHashTable * hash;

  if (hash_func == 0B) goto <D.6163>; else goto <D.6164>;
  <D.6163>:
  hash_func = monoeg_g_direct_hash;
  <D.6164>:
  if (key_equal_func == 0B) goto <D.6165>; else goto <D.6166>;
  <D.6165>:
  key_equal_func = monoeg_g_direct_equal;
  <D.6166>:
  hash = monoeg_malloc0 (64);
  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.6167 = hash->table_size;
  D.6168 = (long unsigned int) D.6167;
  D.6169 = D.6168 * 8;
  D.6170 = monoeg_malloc0 (D.6169);
  hash->table = D.6170;
  D.6171 = hash;
  return D.6171;
}


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

  mask = 0;
  D.6173 = 1 << shift;
  hash_table->table_size = D.6173;
  i = 0;
  goto <D.6066>;
  <D.6065>:
  mask = mask << 1;
  mask = mask | 1;
  i = i + 1;
  <D.6066>:
  if (i < shift) goto <D.6065>; else goto <D.6067>;
  <D.6067>:
  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.6175;
  long int D.6176;
  long int D.6177;
  void * (*<T1079>) (void *) D.6180;
  void * D.6181;
  _Bool D.6182;
  long int D.6183;
  long int D.6184;
  guint (*<Te71>) (const void *) D.6189;
  int D.6190;
  unsigned int D.6191;
  struct Slot * D.6192;
  long unsigned int D.6193;
  long unsigned int D.6194;
  void * D.6195;
  long unsigned int D.6196;
  long unsigned int D.6197;
  int D.6200;
  void (*<Tdc5>) (void *) D.6204;
  void (*<Tdc5>) (void *) D.6207;
  void * D.6210;
  long unsigned int D.6211;
  long unsigned int D.6218;
  long unsigned int D.6219;
  int D.6221;
  int D.6222;
  int D.6223;
  int D.6224;
  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.6175 = value == 0B;
  D.6176 = (long int) D.6175;
  D.6177 = __builtin_expect (D.6176, 0);
  if (D.6177 != 0) goto <D.6178>; else goto <D.6179>;
  <D.6178>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 222, "value");
  <D.6179>:
  D.6180 = hash->key_extract_func;
  D.6181 = D.6180 (value);
  D.6182 = D.6181 != key;
  D.6183 = (long int) D.6182;
  D.6184 = __builtin_expect (D.6183, 0);
  if (D.6184 != 0) goto <D.6185>; else goto <D.6186>;
  <D.6185>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 223, "hash->key_extract_func (value) == key");
  <D.6186>:
  if (hash == 0B) goto <D.6187>; else goto <D.6188>;
  <D.6187>:
  monoeg_g_log (0B, 8, "%s:%d: assertion \'%s\' failed", "mono-value-hash.c", 225, "hash != NULL");
  return;
  <D.6188>:
  D.6189 = hash->hash_func;
  hashcode = D.6189 (key);
  D.6190 = hash->table_mask;
  D.6191 = (unsigned int) D.6190;
  s_index = D.6191 & hashcode;
  D.6192 = hash->table;
  D.6193 = (long unsigned int) s_index;
  D.6194 = D.6193 * 8;
  s = D.6192 + D.6194;
  equal = hash->key_equal_func;
  goto <D.6127>;
  <D.6126>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.6195 = s->value;
    D.6196 = (long unsigned int) D.6195;
    D.6197 = D.6196 & 18446744073709551612;
    s_value = (void *) D.6197;
    D.6180 = hash->key_extract_func;
    s_key = D.6180 (s_value);
    D.6189 = hash->hash_func;
    s_key_hash = D.6189 (s_key);
    if (s_key_hash == hashcode) goto <D.6199>; else goto <D.6198>;
    <D.6199>:
    D.6200 = equal (s_key, key);
    if (D.6200 != 0) goto <D.6201>; else goto <D.6198>;
    <D.6201>:
    if (replace != 0) goto <D.6202>; else goto <D.6203>;
    <D.6202>:
    D.6204 = hash->key_destroy_func;
    if (D.6204 != 0B) goto <D.6205>; else goto <D.6206>;
    <D.6205>:
    D.6204 = hash->key_destroy_func;
    D.6204 (s_key);
    <D.6206>:
    <D.6203>:
    D.6207 = hash->value_destroy_func;
    if (D.6207 != 0B) goto <D.6208>; else goto <D.6209>;
    <D.6208>:
    D.6207 = hash->value_destroy_func;
    D.6195 = s->value;
    D.6196 = (long unsigned int) D.6195;
    D.6197 = D.6196 & 18446744073709551612;
    D.6210 = (void *) D.6197;
    D.6207 (D.6210);
    <D.6209>:
    s->value = value;
    return;
    <D.6198>:
    D.6195 = s->value;
    D.6196 = (long unsigned int) D.6195;
    D.6211 = D.6196 & 1;
    if (D.6211 != 0) goto <D.6212>; else goto <D.6213>;
    <D.6212>:
    if (have_tombstone == 0) goto <D.6214>; else goto <D.6215>;
    <D.6214>:
    first_tombstone = s_index;
    have_tombstone = 1;
    <D.6215>:
    <D.6213>:
    step = step + 1;
    s_index = s_index + step;
    D.6190 = hash->table_mask;
    D.6191 = (unsigned int) D.6190;
    s_index = D.6191 & s_index;
    D.6192 = hash->table;
    D.6193 = (long unsigned int) s_index;
    D.6194 = D.6193 * 8;
    s = D.6192 + D.6194;
  }
  <D.6127>:
  D.6195 = s->value;
  D.6196 = (long unsigned int) D.6195;
  if (D.6196 != 0) goto <D.6126>; else goto <D.6128>;
  <D.6128>:
  if (have_tombstone != 0) goto <D.6216>; else goto <D.6217>;
  <D.6216>:
  D.6192 = hash->table;
  D.6218 = (long unsigned int) first_tombstone;
  D.6219 = D.6218 * 8;
  s = D.6192 + D.6219;
  goto <D.6220>;
  <D.6217>:
  D.6221 = hash->n_occupied;
  D.6222 = D.6221 + 1;
  hash->n_occupied = D.6222;
  <D.6220>:
  s->value = value;
  D.6223 = hash->in_use;
  D.6224 = D.6223 + 1;
  hash->in_use = D.6224;
  rehash (hash);
}


rehash (struct MonoValueHashTable * hash)
{
  int D.6229;
  int D.6230;
  int D.6232;
  int D.6233;
  int n_occupied;
  int table_size;

  n_occupied = hash->n_occupied;
  table_size = hash->table_size;
  D.6229 = hash->in_use;
  D.6230 = D.6229 * 4;
  if (D.6230 < table_size) goto <D.6231>; else goto <D.6226>;
  <D.6231>:
  if (table_size > 8) goto <D.6227>; else goto <D.6226>;
  <D.6226>:
  D.6232 = n_occupied / 16;
  D.6233 = D.6232 + n_occupied;
  if (D.6233 >= table_size) goto <D.6227>; else goto <D.6228>;
  <D.6227>:
  do_rehash (hash);
  <D.6228>:
}


do_rehash (struct MonoValueHashTable * hash)
{
  int D.6234;
  int D.6235;
  int D.6236;
  long unsigned int D.6237;
  long unsigned int D.6238;
  void * D.6239;
  long unsigned int D.6240;
  long unsigned int D.6241;
  void * D.6244;
  long unsigned int D.6245;
  long unsigned int D.6247;
  long unsigned int D.6248;
  void * (*<T1079>) (void *) D.6249;
  guint (*<Te71>) (const void *) D.6250;
  unsigned int D.6251;
  int D.6252;
  unsigned int D.6253;
  struct Slot * D.6254;
  long unsigned int D.6255;
  long unsigned int D.6256;
  void * D.6257;
  long unsigned int D.6258;
  int i;
  int old_size;
  struct Slot * old_table;

  old_size = hash->table_size;
  old_table = hash->table;
  D.6234 = hash->in_use;
  D.6235 = D.6234 * 2;
  mono_value_hash_table_set_shift_from_size (hash, D.6235);
  D.6236 = hash->table_size;
  D.6237 = (long unsigned int) D.6236;
  D.6238 = D.6237 * 8;
  D.6239 = monoeg_malloc0 (D.6238);
  hash->table = D.6239;
  i = 0;
  goto <D.6103>;
  <D.6102>:
  {
    struct Slot * s;
    struct Slot * new_s;
    guint hash_val;
    guint step;
    void * s_value;
    void * s_key;

    D.6240 = (long unsigned int) i;
    D.6241 = D.6240 * 8;
    s = old_table + D.6241;
    step = 0;
    D.6244 = s->value;
    D.6245 = (long unsigned int) D.6244;
    if (D.6245 == 0) goto <D.6242>; else goto <D.6246>;
    <D.6246>:
    D.6244 = s->value;
    D.6245 = (long unsigned int) D.6244;
    D.6247 = D.6245 & 1;
    if (D.6247 != 0) goto <D.6242>; else goto <D.6243>;
    <D.6242>:
    // predicted unlikely by continue predictor.
    goto <D.6098>;
    <D.6243>:
    D.6244 = s->value;
    D.6245 = (long unsigned int) D.6244;
    D.6248 = D.6245 & 18446744073709551612;
    s_value = (void *) D.6248;
    D.6249 = hash->key_extract_func;
    s_key = D.6249 (s_value);
    D.6250 = hash->hash_func;
    D.6251 = D.6250 (s_key);
    D.6252 = hash->table_mask;
    D.6253 = (unsigned int) D.6252;
    hash_val = D.6251 & D.6253;
    D.6254 = hash->table;
    D.6255 = (long unsigned int) hash_val;
    D.6256 = D.6255 * 8;
    new_s = D.6254 + D.6256;
    goto <D.6100>;
    <D.6099>:
    step = step + 1;
    hash_val = hash_val + step;
    D.6252 = hash->table_mask;
    D.6253 = (unsigned int) D.6252;
    hash_val = D.6253 & hash_val;
    D.6254 = hash->table;
    D.6255 = (long unsigned int) hash_val;
    D.6256 = D.6255 * 8;
    new_s = D.6254 + D.6256;
    <D.6100>:
    D.6257 = new_s->value;
    D.6258 = (long unsigned int) D.6257;
    if (D.6258 != 0) goto <D.6099>; else goto <D.6101>;
    <D.6101>:
    *new_s = *s;
  }
  <D.6098>:
  i = i + 1;
  <D.6103>:
  if (i < old_size) goto <D.6102>; else goto <D.6104>;
  <D.6104>:
  monoeg_g_free (old_table);
  D.6234 = hash->in_use;
  hash->n_occupied = D.6234;
}


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

  i = 0;
  goto <D.6073>;
  <D.6072>:
  n = n >> 1;
  i = i + 1;
  <D.6073>:
  if (n != 0) goto <D.6072>; else goto <D.6074>;
  <D.6074>:
  D.6259 = i;
  return D.6259;
}


mono_value_hash_table_lookup (struct MonoValueHashTable * hash, const void * key)
{
  void * D.6263;
  void * D.6264;
  long unsigned int D.6265;
  long unsigned int D.6266;
  struct Slot * slot;

  slot = lookup_internal (hash, key);
  if (slot != 0B) goto <D.6261>; else goto <D.6262>;
  <D.6261>:
  D.6264 = slot->value;
  D.6265 = (long unsigned int) D.6264;
  D.6266 = D.6265 & 18446744073709551612;
  D.6263 = (void *) D.6266;
  return D.6263;
  <D.6262>:
  D.6263 = 0B;
  return D.6263;
}


lookup_internal (struct MonoValueHashTable * hash, const void * key)
{
  guint (*<Te71>) (const void *) D.6268;
  int D.6269;
  unsigned int D.6270;
  struct Slot * D.6271;
  long unsigned int D.6272;
  long unsigned int D.6273;
  void * D.6274;
  long unsigned int D.6275;
  long unsigned int D.6276;
  void * (*<T1079>) (void *) D.6277;
  void * D.6280;
  int D.6281;
  struct Slot * D.6284;
  gboolean (*GEqualFunc) (const void *, const void *) equal;
  struct Slot * s;
  guint hashcode;
  guint s_index;
  guint step;

  step = 0;
  D.6268 = hash->hash_func;
  hashcode = D.6268 (key);
  D.6269 = hash->table_mask;
  D.6270 = (unsigned int) D.6269;
  s_index = D.6270 & hashcode;
  D.6271 = hash->table;
  D.6272 = (long unsigned int) s_index;
  D.6273 = D.6272 * 8;
  s = D.6271 + D.6273;
  equal = hash->key_equal_func;
  goto <D.6147>;
  <D.6146>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.6274 = s->value;
    D.6275 = (long unsigned int) D.6274;
    D.6276 = D.6275 & 18446744073709551612;
    s_value = (void *) D.6276;
    D.6277 = hash->key_extract_func;
    s_key = D.6277 (s_value);
    D.6268 = hash->hash_func;
    s_key_hash = D.6268 (s_key);
    if (s_key_hash == hashcode) goto <D.6278>; else goto <D.6279>;
    <D.6278>:
    D.6277 = hash->key_extract_func;
    D.6280 = D.6277 (s_value);
    D.6281 = equal (D.6280, key);
    if (D.6281 != 0) goto <D.6282>; else goto <D.6283>;
    <D.6282>:
    D.6284 = s;
    return D.6284;
    <D.6283>:
    <D.6279>:
    step = step + 1;
    s_index = s_index + step;
    D.6269 = hash->table_mask;
    D.6270 = (unsigned int) D.6269;
    s_index = D.6270 & s_index;
    D.6271 = hash->table;
    D.6272 = (long unsigned int) s_index;
    D.6273 = D.6272 * 8;
    s = D.6271 + D.6273;
  }
  <D.6147>:
  D.6274 = s->value;
  D.6275 = (long unsigned int) D.6274;
  if (D.6275 != 0) goto <D.6146>; else goto <D.6148>;
  <D.6148>:
  D.6284 = 0B;
  return D.6284;
}


mono_value_hash_table_destroy (struct MonoValueHashTable * hash)
{
  struct Slot * D.6288;
  long unsigned int D.6289;
  long unsigned int D.6290;
  void * D.6291;
  long unsigned int D.6292;
  long unsigned int D.6295;
  void (*<Tdc5>) (void *) D.6298;
  void * (*<T1079>) (void *) D.6301;
  long unsigned int D.6302;
  void * D.6303;
  void * D.6304;
  void (*<Tdc5>) (void *) D.6305;
  int D.6308;
  int i;

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

    D.6288 = hash->table;
    D.6289 = (long unsigned int) i;
    D.6290 = D.6289 * 8;
    s = D.6288 + D.6290;
    D.6291 = s->value;
    D.6292 = (long unsigned int) D.6291;
    if (D.6292 != 0) goto <D.6293>; else goto <D.6294>;
    <D.6293>:
    D.6291 = s->value;
    D.6292 = (long unsigned int) D.6291;
    D.6295 = D.6292 & 1;
    if (D.6295 == 0) goto <D.6296>; else goto <D.6297>;
    <D.6296>:
    D.6298 = hash->key_destroy_func;
    if (D.6298 != 0B) goto <D.6299>; else goto <D.6300>;
    <D.6299>:
    D.6298 = hash->key_destroy_func;
    D.6301 = hash->key_extract_func;
    D.6291 = s->value;
    D.6292 = (long unsigned int) D.6291;
    D.6302 = D.6292 & 18446744073709551612;
    D.6303 = (void *) D.6302;
    D.6304 = D.6301 (D.6303);
    D.6298 (D.6304);
    <D.6300>:
    D.6305 = hash->value_destroy_func;
    if (D.6305 != 0B) goto <D.6306>; else goto <D.6307>;
    <D.6306>:
    D.6305 = hash->value_destroy_func;
    D.6291 = s->value;
    D.6292 = (long unsigned int) D.6291;
    D.6302 = D.6292 & 18446744073709551612;
    D.6303 = (void *) D.6302;
    D.6305 (D.6303);
    <D.6307>:
    <D.6297>:
    <D.6294>:
  }
  i = i + 1;
  <D.6160>:
  D.6308 = hash->table_size;
  if (D.6308 > i) goto <D.6159>; else goto <D.6161>;
  <D.6161>:
  D.6288 = hash->table;
  monoeg_g_free (D.6288);
  monoeg_g_free (hash);
}


