1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef vm_ShapeZone_h 8 #define vm_ShapeZone_h 9 10 #include "mozilla/MemoryReporting.h" 11 12 #include "gc/Barrier.h" 13 #include "js/GCHashTable.h" 14 #include "vm/PropertyKey.h" 15 #include "vm/PropMap.h" 16 #include "vm/Shape.h" 17 #include "vm/TaggedProto.h" 18 19 namespace js { 20 21 // Hash policy for the per-zone baseShapes set. 22 struct BaseShapeHasher { 23 struct Lookup { 24 const JSClass* clasp; 25 JS::Realm* realm; 26 TaggedProto proto; 27 LookupBaseShapeHasher::Lookup28 Lookup(const JSClass* clasp, JS::Realm* realm, TaggedProto proto) 29 : clasp(clasp), realm(realm), proto(proto) {} 30 }; 31 hashBaseShapeHasher32 static HashNumber hash(const Lookup& lookup) { 33 HashNumber hash = MovableCellHasher<TaggedProto>::hash(lookup.proto); 34 return mozilla::AddToHash(hash, lookup.clasp, lookup.realm); 35 } matchBaseShapeHasher36 static bool match(const WeakHeapPtr<BaseShape*>& key, const Lookup& lookup) { 37 return key.unbarrieredGet()->clasp() == lookup.clasp && 38 key.unbarrieredGet()->realm() == lookup.realm && 39 key.unbarrieredGet()->proto() == lookup.proto; 40 } 41 }; 42 using BaseShapeSet = JS::WeakCache< 43 JS::GCHashSet<WeakHeapPtr<BaseShape*>, BaseShapeHasher, SystemAllocPolicy>>; 44 45 // Hash policy for the per-zone initialPropMaps set, mapping property key + info 46 // to a shared property map. 47 struct InitialPropMapHasher { 48 struct Lookup { 49 PropertyKey key; 50 PropertyInfo prop; 51 LookupInitialPropMapHasher::Lookup52 Lookup(PropertyKey key, PropertyInfo prop) : key(key), prop(prop) {} 53 }; hashInitialPropMapHasher54 static HashNumber hash(const Lookup& lookup) { 55 HashNumber hash = HashPropertyKey(lookup.key); 56 return mozilla::AddToHash(hash, lookup.prop.toRaw()); 57 } matchInitialPropMapHasher58 static bool match(const WeakHeapPtr<SharedPropMap*>& key, 59 const Lookup& lookup) { 60 const SharedPropMap* map = key.unbarrieredGet(); 61 return map->matchProperty(0, lookup.key, lookup.prop); 62 } 63 }; 64 using InitialPropMapSet = 65 JS::WeakCache<JS::GCHashSet<WeakHeapPtr<SharedPropMap*>, 66 InitialPropMapHasher, SystemAllocPolicy>>; 67 68 // Hash policy for the per-zone initialShapes set storing initial shapes for 69 // objects in the zone. 70 // 71 // These are empty shapes, except for certain classes (e.g. String, RegExp) 72 // which may add certain baked-in properties. See insertInitialShape. 73 struct InitialShapeHasher { 74 struct Lookup { 75 const JSClass* clasp; 76 JS::Realm* realm; 77 TaggedProto proto; 78 uint32_t nfixed; 79 ObjectFlags objectFlags; 80 LookupInitialShapeHasher::Lookup81 Lookup(const JSClass* clasp, JS::Realm* realm, const TaggedProto& proto, 82 uint32_t nfixed, ObjectFlags objectFlags) 83 : clasp(clasp), 84 realm(realm), 85 proto(proto), 86 nfixed(nfixed), 87 objectFlags(objectFlags) {} 88 }; 89 hashInitialShapeHasher90 static HashNumber hash(const Lookup& lookup) { 91 HashNumber hash = MovableCellHasher<TaggedProto>::hash(lookup.proto); 92 return mozilla::AddToHash(hash, lookup.clasp, lookup.realm, lookup.nfixed, 93 lookup.objectFlags.toRaw()); 94 } matchInitialShapeHasher95 static bool match(const WeakHeapPtr<Shape*>& key, const Lookup& lookup) { 96 const Shape* shape = key.unbarrieredGet(); 97 return lookup.clasp == shape->getObjectClass() && 98 lookup.realm == shape->realm() && lookup.proto == shape->proto() && 99 lookup.nfixed == shape->numFixedSlots() && 100 lookup.objectFlags == shape->objectFlags(); 101 } 102 }; 103 using InitialShapeSet = JS::WeakCache< 104 JS::GCHashSet<WeakHeapPtr<Shape*>, InitialShapeHasher, SystemAllocPolicy>>; 105 106 // Hash policy for the per-zone propMapShapes set storing shared shapes with 107 // shared property maps. 108 struct PropMapShapeHasher { 109 struct Lookup { 110 BaseShape* base; 111 SharedPropMap* map; 112 uint32_t mapLength; 113 uint32_t nfixed; 114 ObjectFlags objectFlags; 115 LookupPropMapShapeHasher::Lookup116 Lookup(BaseShape* base, uint32_t nfixed, SharedPropMap* map, 117 uint32_t mapLength, ObjectFlags objectFlags) 118 : base(base), 119 map(map), 120 mapLength(mapLength), 121 nfixed(nfixed), 122 objectFlags(objectFlags) {} 123 }; 124 hashPropMapShapeHasher125 static HashNumber hash(const Lookup& lookup) { 126 return mozilla::HashGeneric(lookup.base, lookup.map, lookup.mapLength, 127 lookup.nfixed, lookup.objectFlags.toRaw()); 128 } matchPropMapShapeHasher129 static bool match(const WeakHeapPtr<Shape*>& key, const Lookup& lookup) { 130 const Shape* shape = key.unbarrieredGet(); 131 return lookup.base == shape->base() && 132 lookup.nfixed == shape->numFixedSlots() && 133 lookup.map == shape->propMap() && 134 lookup.mapLength == shape->propMapLength() && 135 lookup.objectFlags == shape->objectFlags(); 136 } rekeyPropMapShapeHasher137 static void rekey(WeakHeapPtr<Shape*>& k, const WeakHeapPtr<Shape*>& newKey) { 138 k = newKey; 139 } 140 }; 141 using PropMapShapeSet = JS::WeakCache< 142 JS::GCHashSet<WeakHeapPtr<Shape*>, PropMapShapeHasher, SystemAllocPolicy>>; 143 144 struct ShapeZone { 145 // Set of all base shapes in the Zone. 146 BaseShapeSet baseShapes; 147 148 // Set used to look up a shared property map based on the first property's 149 // PropertyKey and PropertyInfo. 150 InitialPropMapSet initialPropMaps; 151 152 // Set of initial shapes in the Zone. 153 InitialShapeSet initialShapes; 154 155 // Set of SharedPropMapShapes in the Zone. 156 PropMapShapeSet propMapShapes; 157 158 using ShapeWithCacheVector = js::Vector<js::Shape*, 0, js::SystemAllocPolicy>; 159 ShapeWithCacheVector shapesWithCache; 160 161 explicit ShapeZone(Zone* zone); 162 163 void purgeShapeCaches(JSFreeOp* fop); 164 165 void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, 166 size_t* initialPropMapTable, size_t* shapeTables); 167 168 void fixupPropMapShapeTableAfterMovingGC(); 169 170 #ifdef JSGC_HASH_TABLE_CHECKS 171 void checkTablesAfterMovingGC(); 172 #endif 173 }; 174 175 } // namespace js 176 177 #endif /* vm_ShapeZone_h */ 178