michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jspropertytree_h michael@0: #define jspropertytree_h michael@0: michael@0: #include "jsalloc.h" michael@0: #include "jspubtd.h" michael@0: michael@0: #include "js/HashTable.h" michael@0: michael@0: namespace js { michael@0: michael@0: class Shape; michael@0: struct StackShape; michael@0: michael@0: struct ShapeHasher { michael@0: typedef Shape *Key; michael@0: typedef StackShape Lookup; michael@0: michael@0: static inline HashNumber hash(const Lookup &l); michael@0: static inline bool match(Key k, const Lookup &l); michael@0: }; michael@0: michael@0: typedef HashSet KidsHash; michael@0: michael@0: class KidsPointer { michael@0: private: michael@0: enum { michael@0: SHAPE = 0, michael@0: HASH = 1, michael@0: TAG = 1 michael@0: }; michael@0: michael@0: uintptr_t w; michael@0: michael@0: public: michael@0: bool isNull() const { return !w; } michael@0: void setNull() { w = 0; } michael@0: michael@0: bool isShape() const { return (w & TAG) == SHAPE && !isNull(); } michael@0: Shape *toShape() const { michael@0: JS_ASSERT(isShape()); michael@0: return reinterpret_cast(w & ~uintptr_t(TAG)); michael@0: } michael@0: void setShape(Shape *shape) { michael@0: JS_ASSERT(shape); michael@0: JS_ASSERT((reinterpret_cast(static_cast(shape)) & TAG) == 0); michael@0: w = reinterpret_cast(static_cast(shape)) | SHAPE; michael@0: } michael@0: michael@0: bool isHash() const { return (w & TAG) == HASH; } michael@0: KidsHash *toHash() const { michael@0: JS_ASSERT(isHash()); michael@0: return reinterpret_cast(w & ~uintptr_t(TAG)); michael@0: } michael@0: void setHash(KidsHash *hash) { michael@0: JS_ASSERT(hash); michael@0: JS_ASSERT((reinterpret_cast(hash) & TAG) == 0); michael@0: w = reinterpret_cast(hash) | HASH; michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: void checkConsistency(Shape *aKid) const; michael@0: #endif michael@0: }; michael@0: michael@0: class PropertyTree michael@0: { michael@0: friend class ::JSFunction; michael@0: michael@0: JSCompartment *compartment_; michael@0: michael@0: bool insertChild(ExclusiveContext *cx, Shape *parent, Shape *child); michael@0: michael@0: PropertyTree(); michael@0: michael@0: public: michael@0: /* michael@0: * Use a lower limit for objects that are accessed using SETELEM (o[x] = y). michael@0: * These objects are likely used as hashmaps and dictionary mode is more michael@0: * efficient in this case. michael@0: */ michael@0: enum { michael@0: MAX_HEIGHT = 512, michael@0: MAX_HEIGHT_WITH_ELEMENTS_ACCESS = 128 michael@0: }; michael@0: michael@0: PropertyTree(JSCompartment *comp) michael@0: : compartment_(comp) michael@0: { michael@0: } michael@0: michael@0: JSCompartment *compartment() { return compartment_; } michael@0: michael@0: Shape *newShape(ExclusiveContext *cx); michael@0: Shape *getChild(ExclusiveContext *cx, Shape *parent, StackShape &child); michael@0: Shape *lookupChild(ThreadSafeContext *cx, Shape *parent, const StackShape &child); michael@0: }; michael@0: michael@0: } /* namespace js */ michael@0: michael@0: #endif /* jspropertytree_h */