| // PR debug/55717 |
| // { dg-do compile } |
| // { dg-options "-O -g" } |
| |
| typedef unsigned uint32_t __attribute__((mode (__SI__))); |
| |
| struct DebugOnly {}; |
| template <class T> |
| struct StripConst { typedef T result; }; |
| class TempAllocPolicy {}; |
| template <class T> |
| class HashTableEntry |
| { |
| unsigned keyHash; |
| template <class, class, class> |
| friend class HashTable; |
| T t; |
| void setLive (unsigned hn) { keyHash = hn; } |
| }; |
| template <class T, class HashPolicy, class> |
| struct HashTable |
| { |
| typedef typename HashPolicy::KeyType Key; |
| typedef typename HashPolicy::Lookup Lookup; |
| typedef HashTableEntry <T> Entry; |
| struct Range |
| { |
| Range () {} |
| Entry *cur, end; |
| bool empty () { return false; } |
| T front () { return T (); } |
| }; |
| struct Enum : public Range |
| { |
| HashTable table; |
| bool removed; |
| template <class Map> |
| Enum (Map map) : Range (map.all ()), table (map.impl), removed () {} |
| void rekeyFront (Lookup l, Key) |
| { |
| T t = this->cur->t; |
| table.putNewInfallible (l, t); |
| } |
| void rekeyFront (Key k) |
| { |
| rekeyFront (k, k); |
| } |
| }; |
| unsigned entryCount; |
| unsigned sCollisionBit; |
| unsigned prepareHash (Lookup l) |
| { |
| unsigned keyHash (HashPolicy::hash (l)); |
| return keyHash & sCollisionBit; |
| } |
| static Entry *entryp; |
| Entry *findFreeEntry (unsigned) { return entryp; } |
| void putNewInfallible (Lookup l, T) |
| { |
| unsigned keyHash = prepareHash (l); |
| Entry *entry = findFreeEntry (keyHash); |
| entry->setLive (keyHash); |
| entryCount++; |
| } |
| }; |
| template <class Key> |
| struct HashMapEntry { Key key; }; |
| template <class Key, class Value, class HashPolicy = DebugOnly, class AllocPolicy = TempAllocPolicy> |
| struct HashMap |
| { |
| typedef HashMapEntry <Key> Entry; |
| struct MapHashPolicy : HashPolicy |
| { |
| typedef Key KeyType; |
| }; |
| typedef HashTable <Entry, MapHashPolicy, AllocPolicy> Impl; |
| Impl impl; |
| typedef typename Impl::Range Range; |
| Range all () { return Range (); } |
| typedef typename Impl::Enum Enum; |
| }; |
| class FreeOp; |
| struct AllocationSiteKey; |
| typedef HashMap <AllocationSiteKey, DebugOnly, AllocationSiteKey, TempAllocPolicy> AllocationSiteTable; |
| struct TypeCompartment |
| { |
| AllocationSiteTable *allocationSiteTable; |
| void sweep (FreeOp *); |
| }; |
| struct JSScript { unsigned *code; }; |
| bool IsScriptMarked (JSScript **); |
| struct AllocationSiteKey |
| { |
| JSScript *script; |
| uint32_t offset : 24; |
| int kind; |
| typedef AllocationSiteKey Lookup; |
| static unsigned hash (AllocationSiteKey key) { return (long (key.script->code + key.offset)) ^ key.kind; } |
| }; |
| void |
| TypeCompartment::sweep (FreeOp *) |
| { |
| for (AllocationSiteTable::Enum e (*allocationSiteTable); !e.empty ();) |
| { |
| AllocationSiteKey key = e.front ().key; |
| IsScriptMarked (&key.script); |
| e.rekeyFront (key); |
| } |
| } |