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