add bitset operations and tests
[hiphop-php.git] / hphp / runtime / vm / name-value-table.h
blob037011b2bc171744eac5eb085bf663a68339a360
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_RUNTIME_VM_NAMEVALUETABLE_H_
18 #define incl_HPHP_RUNTIME_VM_NAMEVALUETABLE_H_
20 #include <folly/Bits.h>
22 #include "hphp/runtime/base/typed-value.h"
24 namespace HPHP {
26 //////////////////////////////////////////////////////////////////////
28 struct ActRec;
29 struct StringData;
32 * This class implements a name to TypedValue map. Basically a hashtable from
33 * StringData* to TypedValue.
35 * This is for use in variable environments in bytecode.cpp, and is also used
36 * for the global variable environment ($GLOBALS via GlobalsArray).
38 * The table may be optionally attached to an ActRec, in which case it will
39 * contain a kNamedLocalDataType TypedValue per every named local defined in
40 * ActRec's function. This is to keep storage for locals in functions with a
41 * VarEnv in their normal location, but still make them accessible by name
42 * through this table.
44 struct NameValueTable {
45 struct Iterator {
46 explicit Iterator(const NameValueTable* tab);
47 static Iterator getLast(const NameValueTable* tab);
48 static Iterator getEnd(const NameValueTable* tab);
51 * The following two constructors are primarily for using this with
52 * the ArrayData interface (see GlobalsArray), which
53 * expects iterators to be represented by a ssize_t.
55 * The constructor taking `pos' must be given a value previously
56 * returned from toInteger().
58 * The constructor taking a const StringData* starts iteration at
59 * the key given, or returns an invalid iterator if that key does
60 * not exist.
62 explicit Iterator(const NameValueTable* tab, ssize_t pos);
63 explicit Iterator(const NameValueTable* tab, const StringData* start);
65 ssize_t toInteger() const;
66 bool valid() const;
67 const StringData* curKey() const;
68 const TypedValue* curVal() const;
69 void next();
70 void prev();
72 private:
73 explicit Iterator() {}
74 bool atEmpty() const;
76 private:
77 const NameValueTable* m_tab;
78 ssize_t m_idx;
82 * Create a global NameValueTable.
84 explicit NameValueTable();
87 * Create a NameValueTable attached to an already existing ActRec
88 * and populate the table with ActRec's locals.
90 explicit NameValueTable(ActRec* fp);
92 /**
93 * Clone NameValueTable.
95 explicit NameValueTable(const NameValueTable& nvTable, ActRec* fp);
97 ~NameValueTable();
99 NameValueTable(const NameValueTable&) = delete;
100 NameValueTable& operator=(const NameValueTable&) = delete;
103 * Suspend locals into an in-resumable ActRec.
105 void suspend(const ActRec* oldFP, ActRec* newFP);
108 * Attach to a new ActRec and populate its locals with TypedValues stored
109 * in this NameValueTable.
111 void attach(ActRec* fp);
114 * Detach from the current ActRec and steal its named locals.
116 void detach(ActRec* fp);
118 ActRec* getFP() const { return m_fp; }
121 * Explicitly request letting go of all elements in the
122 * NameValueTable without decrefing them.
124 * This is intended for use when destroying the global scope, where
125 * we shouldn't be running destructors.
127 void leak();
128 bool leaked() const { return !m_table; }
131 * Set the slot for the supplied name to `val', allocating it if
132 * necessary.
134 TypedValue* set(const StringData* name, const TypedValue* val);
137 * Bind the slot for the supplied name to `val', allocating it and
138 * boxing it first if necessary.
140 TypedValue* bind(const StringData* name, TypedValue* val);
143 * Remove an element from this table. All elements added always
144 * occupy storage, so this is done by setting the element to
145 * KindOfUninit.
147 void unset(const StringData* name);
150 * Lookup a name, returning null if it doesn't exist in this table.
152 TypedValue* lookup(const StringData* name);
155 * Insert a name to value entry with KindOfNull for the value, or
156 * return what is already there if the key already exists in the
157 * table.
159 TypedValue* lookupAdd(const StringData* name);
161 private:
162 // Dummy DT for named locals; keep out of conflict with actual DataTypes in
163 // base/datatype.h.
164 static constexpr auto kNamedLocalDataType = kExtraInvalidDataType;
166 // Element type for the name/value hashtable.
167 struct Elm {
168 TypedValue m_tv;
169 const StringData* m_name;
170 TYPE_SCAN_CUSTOM() {
171 // m_tv is only valid if m_name != null
172 if (m_name) {
173 scanner.scan(m_name);
174 scanner.scan(m_tv);
179 private:
180 void reserve(size_t desiredSize);
181 void allocate(const size_t newCapac);
182 TypedValue* derefNamedLocal(TypedValue* tv) const;
183 TypedValue* findTypedValue(const StringData* name);
184 Elm* insertImpl(const StringData* name);
185 Elm* insert(const StringData* name);
186 void rehash(Elm* const oldTab, const size_t oldMask);
187 Elm* findElm(const StringData* name) const;
189 private:
190 ActRec* m_fp{nullptr};
191 Elm* m_table{nullptr};
192 uint32_t m_tabMask{0};
193 uint32_t m_elms{0};
195 TYPE_SCAN_CUSTOM() {
196 if (leaked()) return;
197 scanner.scan(m_fp);
198 scanner.scan(m_table);
202 //////////////////////////////////////////////////////////////////////
206 #endif