1 // PR debug/55717
2 // { dg-do compile }
3 // { dg-options "-O -g" }
4 
5 struct DebugOnly {};
6 template <class T>
7 struct StripConst { typedef T result; };
8 class TempAllocPolicy {};
9 template <class T>
10 class HashTableEntry
11 {
12   unsigned keyHash;
13   template <class, class, class>
14   friend class HashTable;
15   T t;
setLive(unsigned hn)16   void setLive (unsigned hn) { keyHash = hn; }
17 };
18 template <class T, class HashPolicy, class>
19 struct HashTable
20 {
21   typedef typename HashPolicy::KeyType Key;
22   typedef typename HashPolicy::Lookup Lookup;
23   typedef HashTableEntry <T> Entry;
24   struct Range
25   {
RangeHashTable::Range26     Range () {}
27     Entry *cur, end;
emptyHashTable::Range28     bool empty () { return false; }
frontHashTable::Range29     T front () { return T (); }
30   };
31   struct Enum : public Range
32   {
33     HashTable table;
34     bool removed;
35     template <class Map>
EnumHashTable::Enum36     Enum (Map map) : Range (map.all ()), table (map.impl), removed () {}
rekeyFrontHashTable::Enum37     void rekeyFront (Lookup l, Key)
38     {
39       T t = this->cur->t;
40       table.putNewInfallible (l, t);
41     }
rekeyFrontHashTable::Enum42     void rekeyFront (Key k)
43     {
44       rekeyFront (k, k);
45     }
46   };
47   unsigned entryCount;
48   unsigned sCollisionBit;
prepareHashHashTable49   unsigned prepareHash (Lookup l)
50   {
51     unsigned keyHash (HashPolicy::hash (l));
52     return keyHash & sCollisionBit;
53   }
54   static Entry *entryp;
findFreeEntryHashTable55   Entry *findFreeEntry (unsigned) { return entryp; }
putNewInfallibleHashTable56   void putNewInfallible (Lookup l, T)
57   {
58     unsigned keyHash = prepareHash (l);
59     Entry *entry = findFreeEntry (keyHash);
60     entry->setLive (keyHash);
61     entryCount++;
62   }
63 };
64 template <class Key>
65 struct HashMapEntry { Key key; };
66 template <class Key, class Value, class HashPolicy = DebugOnly, class AllocPolicy = TempAllocPolicy>
67 struct HashMap
68 {
69   typedef HashMapEntry <Key> Entry;
70   struct MapHashPolicy : HashPolicy
71   {
72     typedef Key KeyType;
73   };
74   typedef HashTable <Entry, MapHashPolicy, AllocPolicy> Impl;
75   Impl impl;
76   typedef typename Impl::Range Range;
allHashMap77   Range all () { return Range (); }
78   typedef typename Impl::Enum Enum;
79 };
80 class FreeOp;
81 struct AllocationSiteKey;
82 typedef HashMap <AllocationSiteKey, DebugOnly, AllocationSiteKey, TempAllocPolicy> AllocationSiteTable;
83 struct TypeCompartment
84 {
85   AllocationSiteTable *allocationSiteTable;
86   void sweep (FreeOp *);
87 };
88 struct JSScript { unsigned *code; };
89 bool IsScriptMarked (JSScript **);
90 struct AllocationSiteKey
91 {
92   JSScript *script;
93   unsigned offset : 24;
94   int kind;
95   typedef AllocationSiteKey Lookup;
hashAllocationSiteKey96   static unsigned hash (AllocationSiteKey key) { return (long (key.script->code + key.offset)) ^ key.kind; }
97 };
98 void
sweep(FreeOp *)99 TypeCompartment::sweep (FreeOp *)
100 {
101   for (AllocationSiteTable::Enum e (*allocationSiteTable); !e.empty ();)
102     {
103       AllocationSiteKey key = e.front ().key;
104       IsScriptMarked (&key.script);
105       e.rekeyFront (key);
106     }
107 }
108