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.5921;
  unsigned int D.5922;
  unsigned int D.5923;
  void * D.5924;
  struct MonoValueHashTable * D.5925;
  struct MonoValueHashTable * hash;

  if (hash_func == 0B) goto <D.5917>; else goto <D.5918>;
  <D.5917>:
  hash_func = monoeg_g_direct_hash;
  <D.5918>:
  if (key_equal_func == 0B) goto <D.5919>; else goto <D.5920>;
  <D.5919>:
  key_equal_func = monoeg_g_direct_equal;
  <D.5920>:
  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.5921 = hash->table_size;
  D.5922 = (unsigned int) D.5921;
  D.5923 = D.5922 * 4;
  D.5924 = monoeg_malloc0 (D.5923);
  hash->table = D.5924;
  D.5925 = hash;
  return D.5925;
}


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

  mask = 0;
  D.5927 = 1 << shift;
  hash_table->table_size = D.5927;
  i = 0;
  goto <D.5820>;
  <D.5819>:
  mask = mask << 1;
  mask = mask | 1;
  i = i + 1;
  <D.5820>:
  if (i < shift) goto <D.5819>; else goto <D.5821>;
  <D.5821>:
  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.5929;
  long int D.5930;
  long int D.5931;
  void * (*<T105f>) (void *) D.5934;
  void * D.5935;
  _Bool D.5936;
  long int D.5937;
  long int D.5938;
  guint (*<Te57>) (const void *) D.5943;
  int D.5944;
  unsigned int D.5945;
  struct Slot * D.5946;
  unsigned int D.5947;
  void * D.5948;
  unsigned int D.5949;
  unsigned int D.5950;
  int D.5953;
  void (*<Tdab>) (void *) D.5957;
  void (*<Tdab>) (void *) D.5960;
  void * D.5963;
  unsigned int D.5964;
  unsigned int D.5971;
  int D.5973;
  int D.5974;
  int D.5975;
  int D.5976;
  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.5929 = value == 0B;
  D.5930 = (long int) D.5929;
  D.5931 = __builtin_expect (D.5930, 0);
  if (D.5931 != 0) goto <D.5932>; else goto <D.5933>;
  <D.5932>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 222, "value");
  <D.5933>:
  D.5934 = hash->key_extract_func;
  D.5935 = D.5934 (value);
  D.5936 = D.5935 != key;
  D.5937 = (long int) D.5936;
  D.5938 = __builtin_expect (D.5937, 0);
  if (D.5938 != 0) goto <D.5939>; else goto <D.5940>;
  <D.5939>:
  monoeg_assertion_message ("* Assertion at %s:%d, condition `%s\' not met\n", "mono-value-hash.c", 223, "hash->key_extract_func (value) == key");
  <D.5940>:
  if (hash == 0B) goto <D.5941>; else goto <D.5942>;
  <D.5941>:
  monoeg_g_log (0B, 8, "%s:%d: assertion \'%s\' failed", "mono-value-hash.c", 225, "hash != NULL");
  return;
  <D.5942>:
  D.5943 = hash->hash_func;
  hashcode = D.5943 (key);
  D.5944 = hash->table_mask;
  D.5945 = (unsigned int) D.5944;
  s_index = D.5945 & hashcode;
  D.5946 = hash->table;
  D.5947 = s_index * 4;
  s = D.5946 + D.5947;
  equal = hash->key_equal_func;
  goto <D.5881>;
  <D.5880>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.5948 = s->value;
    D.5949 = (unsigned int) D.5948;
    D.5950 = D.5949 & 4294967292;
    s_value = (void *) D.5950;
    D.5934 = hash->key_extract_func;
    s_key = D.5934 (s_value);
    D.5943 = hash->hash_func;
    s_key_hash = D.5943 (s_key);
    if (s_key_hash == hashcode) goto <D.5952>; else goto <D.5951>;
    <D.5952>:
    D.5953 = equal (s_key, key);
    if (D.5953 != 0) goto <D.5954>; else goto <D.5951>;
    <D.5954>:
    if (replace != 0) goto <D.5955>; else goto <D.5956>;
    <D.5955>:
    D.5957 = hash->key_destroy_func;
    if (D.5957 != 0B) goto <D.5958>; else goto <D.5959>;
    <D.5958>:
    D.5957 = hash->key_destroy_func;
    D.5957 (s_key);
    <D.5959>:
    <D.5956>:
    D.5960 = hash->value_destroy_func;
    if (D.5960 != 0B) goto <D.5961>; else goto <D.5962>;
    <D.5961>:
    D.5960 = hash->value_destroy_func;
    D.5948 = s->value;
    D.5949 = (unsigned int) D.5948;
    D.5950 = D.5949 & 4294967292;
    D.5963 = (void *) D.5950;
    D.5960 (D.5963);
    <D.5962>:
    s->value = value;
    return;
    <D.5951>:
    D.5948 = s->value;
    D.5949 = (unsigned int) D.5948;
    D.5964 = D.5949 & 1;
    if (D.5964 != 0) goto <D.5965>; else goto <D.5966>;
    <D.5965>:
    if (have_tombstone == 0) goto <D.5967>; else goto <D.5968>;
    <D.5967>:
    first_tombstone = s_index;
    have_tombstone = 1;
    <D.5968>:
    <D.5966>:
    step = step + 1;
    s_index = s_index + step;
    D.5944 = hash->table_mask;
    D.5945 = (unsigned int) D.5944;
    s_index = D.5945 & s_index;
    D.5946 = hash->table;
    D.5947 = s_index * 4;
    s = D.5946 + D.5947;
  }
  <D.5881>:
  D.5948 = s->value;
  D.5949 = (unsigned int) D.5948;
  if (D.5949 != 0) goto <D.5880>; else goto <D.5882>;
  <D.5882>:
  if (have_tombstone != 0) goto <D.5969>; else goto <D.5970>;
  <D.5969>:
  D.5946 = hash->table;
  D.5971 = first_tombstone * 4;
  s = D.5946 + D.5971;
  goto <D.5972>;
  <D.5970>:
  D.5973 = hash->n_occupied;
  D.5974 = D.5973 + 1;
  hash->n_occupied = D.5974;
  <D.5972>:
  s->value = value;
  D.5975 = hash->in_use;
  D.5976 = D.5975 + 1;
  hash->in_use = D.5976;
  rehash (hash);
}


rehash (struct MonoValueHashTable * hash)
{
  int D.5981;
  int D.5982;
  int D.5984;
  int D.5985;
  int n_occupied;
  int table_size;

  n_occupied = hash->n_occupied;
  table_size = hash->table_size;
  D.5981 = hash->in_use;
  D.5982 = D.5981 * 4;
  if (D.5982 < table_size) goto <D.5983>; else goto <D.5978>;
  <D.5983>:
  if (table_size > 8) goto <D.5979>; else goto <D.5978>;
  <D.5978>:
  D.5984 = n_occupied / 16;
  D.5985 = D.5984 + n_occupied;
  if (D.5985 >= table_size) goto <D.5979>; else goto <D.5980>;
  <D.5979>:
  do_rehash (hash);
  <D.5980>:
}


do_rehash (struct MonoValueHashTable * hash)
{
  int D.5986;
  int D.5987;
  int D.5988;
  unsigned int D.5989;
  unsigned int D.5990;
  void * D.5991;
  unsigned int i.1;
  unsigned int D.5993;
  void * D.5996;
  unsigned int D.5997;
  unsigned int D.5999;
  unsigned int D.6000;
  void * (*<T105f>) (void *) D.6001;
  guint (*<Te57>) (const void *) D.6002;
  unsigned int D.6003;
  int D.6004;
  unsigned int D.6005;
  struct Slot * D.6006;
  unsigned int D.6007;
  void * D.6008;
  unsigned int D.6009;
  int i;
  int old_size;
  struct Slot * old_table;

  old_size = hash->table_size;
  old_table = hash->table;
  D.5986 = hash->in_use;
  D.5987 = D.5986 * 2;
  mono_value_hash_table_set_shift_from_size (hash, D.5987);
  D.5988 = hash->table_size;
  D.5989 = (unsigned int) D.5988;
  D.5990 = D.5989 * 4;
  D.5991 = monoeg_malloc0 (D.5990);
  hash->table = D.5991;
  i = 0;
  goto <D.5857>;
  <D.5856>:
  {
    struct Slot * s;
    struct Slot * new_s;
    guint hash_val;
    guint step;
    void * s_value;
    void * s_key;

    i.1 = (unsigned int) i;
    D.5993 = i.1 * 4;
    s = old_table + D.5993;
    step = 0;
    D.5996 = s->value;
    D.5997 = (unsigned int) D.5996;
    if (D.5997 == 0) goto <D.5994>; else goto <D.5998>;
    <D.5998>:
    D.5996 = s->value;
    D.5997 = (unsigned int) D.5996;
    D.5999 = D.5997 & 1;
    if (D.5999 != 0) goto <D.5994>; else goto <D.5995>;
    <D.5994>:
    // predicted unlikely by continue predictor.
    goto <D.5852>;
    <D.5995>:
    D.5996 = s->value;
    D.5997 = (unsigned int) D.5996;
    D.6000 = D.5997 & 4294967292;
    s_value = (void *) D.6000;
    D.6001 = hash->key_extract_func;
    s_key = D.6001 (s_value);
    D.6002 = hash->hash_func;
    D.6003 = D.6002 (s_key);
    D.6004 = hash->table_mask;
    D.6005 = (unsigned int) D.6004;
    hash_val = D.6003 & D.6005;
    D.6006 = hash->table;
    D.6007 = hash_val * 4;
    new_s = D.6006 + D.6007;
    goto <D.5854>;
    <D.5853>:
    step = step + 1;
    hash_val = hash_val + step;
    D.6004 = hash->table_mask;
    D.6005 = (unsigned int) D.6004;
    hash_val = D.6005 & hash_val;
    D.6006 = hash->table;
    D.6007 = hash_val * 4;
    new_s = D.6006 + D.6007;
    <D.5854>:
    D.6008 = new_s->value;
    D.6009 = (unsigned int) D.6008;
    if (D.6009 != 0) goto <D.5853>; else goto <D.5855>;
    <D.5855>:
    *new_s = *s;
  }
  <D.5852>:
  i = i + 1;
  <D.5857>:
  if (i < old_size) goto <D.5856>; else goto <D.5858>;
  <D.5858>:
  monoeg_g_free (old_table);
  D.5986 = hash->in_use;
  hash->n_occupied = D.5986;
}


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

  i = 0;
  goto <D.5827>;
  <D.5826>:
  n = n >> 1;
  i = i + 1;
  <D.5827>:
  if (n != 0) goto <D.5826>; else goto <D.5828>;
  <D.5828>:
  D.6010 = i;
  return D.6010;
}


mono_value_hash_table_lookup (struct MonoValueHashTable * hash, const void * key)
{
  void * D.6014;
  void * D.6015;
  unsigned int D.6016;
  unsigned int D.6017;
  struct Slot * slot;

  slot = lookup_internal (hash, key);
  if (slot != 0B) goto <D.6012>; else goto <D.6013>;
  <D.6012>:
  D.6015 = slot->value;
  D.6016 = (unsigned int) D.6015;
  D.6017 = D.6016 & 4294967292;
  D.6014 = (void *) D.6017;
  return D.6014;
  <D.6013>:
  D.6014 = 0B;
  return D.6014;
}


lookup_internal (struct MonoValueHashTable * hash, const void * key)
{
  guint (*<Te57>) (const void *) D.6019;
  int D.6020;
  unsigned int D.6021;
  struct Slot * D.6022;
  unsigned int D.6023;
  void * D.6024;
  unsigned int D.6025;
  unsigned int D.6026;
  void * (*<T105f>) (void *) D.6027;
  void * D.6030;
  int D.6031;
  struct Slot * D.6034;
  gboolean (*GEqualFunc) (const void *, const void *) equal;
  struct Slot * s;
  guint hashcode;
  guint s_index;
  guint step;

  step = 0;
  D.6019 = hash->hash_func;
  hashcode = D.6019 (key);
  D.6020 = hash->table_mask;
  D.6021 = (unsigned int) D.6020;
  s_index = D.6021 & hashcode;
  D.6022 = hash->table;
  D.6023 = s_index * 4;
  s = D.6022 + D.6023;
  equal = hash->key_equal_func;
  goto <D.5901>;
  <D.5900>:
  {
    void * s_value;
    void * s_key;
    guint s_key_hash;

    D.6024 = s->value;
    D.6025 = (unsigned int) D.6024;
    D.6026 = D.6025 & 4294967292;
    s_value = (void *) D.6026;
    D.6027 = hash->key_extract_func;
    s_key = D.6027 (s_value);
    D.6019 = hash->hash_func;
    s_key_hash = D.6019 (s_key);
    if (s_key_hash == hashcode) goto <D.6028>; else goto <D.6029>;
    <D.6028>:
    D.6027 = hash->key_extract_func;
    D.6030 = D.6027 (s_value);
    D.6031 = equal (D.6030, key);
    if (D.6031 != 0) goto <D.6032>; else goto <D.6033>;
    <D.6032>:
    D.6034 = s;
    return D.6034;
    <D.6033>:
    <D.6029>:
    step = step + 1;
    s_index = s_index + step;
    D.6020 = hash->table_mask;
    D.6021 = (unsigned int) D.6020;
    s_index = D.6021 & s_index;
    D.6022 = hash->table;
    D.6023 = s_index * 4;
    s = D.6022 + D.6023;
  }
  <D.5901>:
  D.6024 = s->value;
  D.6025 = (unsigned int) D.6024;
  if (D.6025 != 0) goto <D.5900>; else goto <D.5902>;
  <D.5902>:
  D.6034 = 0B;
  return D.6034;
}


mono_value_hash_table_destroy (struct MonoValueHashTable * hash)
{
  struct Slot * D.6038;
  unsigned int i.2;
  unsigned int D.6040;
  void * D.6041;
  unsigned int D.6042;
  unsigned int D.6045;
  void (*<Tdab>) (void *) D.6048;
  void * (*<T105f>) (void *) D.6051;
  unsigned int D.6052;
  void * D.6053;
  void * D.6054;
  void (*<Tdab>) (void *) D.6055;
  int D.6058;
  int i;

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

    D.6038 = hash->table;
    i.2 = (unsigned int) i;
    D.6040 = i.2 * 4;
    s = D.6038 + D.6040;
    D.6041 = s->value;
    D.6042 = (unsigned int) D.6041;
    if (D.6042 != 0) goto <D.6043>; else goto <D.6044>;
    <D.6043>:
    D.6041 = s->value;
    D.6042 = (unsigned int) D.6041;
    D.6045 = D.6042 & 1;
    if (D.6045 == 0) goto <D.6046>; else goto <D.6047>;
    <D.6046>:
    D.6048 = hash->key_destroy_func;
    if (D.6048 != 0B) goto <D.6049>; else goto <D.6050>;
    <D.6049>:
    D.6048 = hash->key_destroy_func;
    D.6051 = hash->key_extract_func;
    D.6041 = s->value;
    D.6042 = (unsigned int) D.6041;
    D.6052 = D.6042 & 4294967292;
    D.6053 = (void *) D.6052;
    D.6054 = D.6051 (D.6053);
    D.6048 (D.6054);
    <D.6050>:
    D.6055 = hash->value_destroy_func;
    if (D.6055 != 0B) goto <D.6056>; else goto <D.6057>;
    <D.6056>:
    D.6055 = hash->value_destroy_func;
    D.6041 = s->value;
    D.6042 = (unsigned int) D.6041;
    D.6052 = D.6042 & 4294967292;
    D.6053 = (void *) D.6052;
    D.6055 (D.6053);
    <D.6057>:
    <D.6047>:
    <D.6044>:
  }
  i = i + 1;
  <D.5914>:
  D.6058 = hash->table_size;
  if (D.6058 > i) goto <D.5913>; else goto <D.5915>;
  <D.5915>:
  D.6038 = hash->table;
  monoeg_g_free (D.6038);
  monoeg_g_free (hash);
}


