1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 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 jspropertytree_h 8 #define jspropertytree_h 9 10 #include "jsalloc.h" 11 #include "jspubtd.h" 12 13 #include "js/HashTable.h" 14 15 namespace js { 16 17 class Shape; 18 struct StackShape; 19 20 struct ShapeHasher : public DefaultHasher<Shape*> { 21 typedef Shape* Key; 22 typedef StackShape Lookup; 23 24 static inline HashNumber hash(const Lookup& l); 25 static inline bool match(Key k, const Lookup& l); 26 }; 27 28 typedef HashSet<Shape*, ShapeHasher, SystemAllocPolicy> KidsHash; 29 30 class KidsPointer { 31 private: 32 enum { 33 SHAPE = 0, 34 HASH = 1, 35 TAG = 1 36 }; 37 38 uintptr_t w; 39 40 public: isNull()41 bool isNull() const { return !w; } setNull()42 void setNull() { w = 0; } 43 isShape()44 bool isShape() const { return (w & TAG) == SHAPE && !isNull(); } toShape()45 Shape* toShape() const { 46 MOZ_ASSERT(isShape()); 47 return reinterpret_cast<Shape*>(w & ~uintptr_t(TAG)); 48 } setShape(Shape * shape)49 void setShape(Shape* shape) { 50 MOZ_ASSERT(shape); 51 MOZ_ASSERT((reinterpret_cast<uintptr_t>(static_cast<Shape*>(shape)) & TAG) == 0); 52 w = reinterpret_cast<uintptr_t>(static_cast<Shape*>(shape)) | SHAPE; 53 } 54 isHash()55 bool isHash() const { return (w & TAG) == HASH; } toHash()56 KidsHash* toHash() const { 57 MOZ_ASSERT(isHash()); 58 return reinterpret_cast<KidsHash*>(w & ~uintptr_t(TAG)); 59 } setHash(KidsHash * hash)60 void setHash(KidsHash* hash) { 61 MOZ_ASSERT(hash); 62 MOZ_ASSERT((reinterpret_cast<uintptr_t>(hash) & TAG) == 0); 63 w = reinterpret_cast<uintptr_t>(hash) | HASH; 64 } 65 66 #ifdef DEBUG 67 void checkConsistency(Shape* aKid) const; 68 #endif 69 }; 70 71 class PropertyTree 72 { 73 friend class ::JSFunction; 74 75 JSCompartment* compartment_; 76 77 bool insertChild(ExclusiveContext* cx, Shape* parent, Shape* child); 78 79 PropertyTree(); 80 81 public: 82 /* 83 * Use a lower limit for objects that are accessed using SETELEM (o[x] = y). 84 * These objects are likely used as hashmaps and dictionary mode is more 85 * efficient in this case. 86 */ 87 enum { 88 MAX_HEIGHT = 512, 89 MAX_HEIGHT_WITH_ELEMENTS_ACCESS = 128 90 }; 91 PropertyTree(JSCompartment * comp)92 explicit PropertyTree(JSCompartment* comp) 93 : compartment_(comp) 94 { 95 } 96 compartment()97 JSCompartment* compartment() { return compartment_; } 98 99 Shape* getChild(ExclusiveContext* cx, Shape* parent, JS::Handle<StackShape> child); 100 }; 101 102 } /* namespace js */ 103 104 #endif /* jspropertytree_h */ 105