Replace usage of ThreadLocalProxy with RDS locals
[hiphop-php.git] / hphp / runtime / vm / globals-array.cpp
blob3d03aecfb7027b5ed7c2b01c5f29382e93bb3ff4
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 +----------------------------------------------------------------------+
16 #include "hphp/runtime/vm/globals-array.h"
18 #include "hphp/runtime/base/array-init.h"
19 #include "hphp/runtime/base/array-iterator.h"
20 #include "hphp/runtime/base/rds-local.h"
21 #include "hphp/runtime/base/tv-val.h"
22 #include "hphp/runtime/base/mixed-array-defs.h"
23 #include "hphp/runtime/base/runtime-error.h"
25 namespace HPHP {
27 //////////////////////////////////////////////////////////////////////
29 static RDS_LOCAL_NO_CHECK(GlobalsArray*, g_variables)(nullptr);
31 GlobalsArray* get_global_variables() {
32 assertx(*g_variables != nullptr);
33 return *g_variables;
36 GlobalsArray::GlobalsArray(NameValueTable* tab)
37 : ArrayData(kGlobalsKind)
38 , m_tab(tab)
40 Variant arr(staticEmptyArray());
41 #define X(s,v) tab->set(makeStaticString(#s), v.asTypedValue());
43 X(argc, init_null_variant);
44 X(argv, init_null_variant);
45 X(_SERVER, arr);
46 X(_GET, arr);
47 X(_POST, arr);
48 X(_COOKIE, arr);
49 X(_FILES, arr);
50 X(_ENV, arr);
51 X(_REQUEST, arr);
52 X(_SESSION, arr);
53 X(HTTP_RAW_POST_DATA, init_null_variant);
54 #undef X
56 *g_variables = this;
57 assertx(hasExactlyOneRef());
60 inline GlobalsArray* GlobalsArray::asGlobals(ArrayData* ad) {
61 assertx(ad->kind() == kGlobalsKind);
62 return static_cast<GlobalsArray*>(ad);
65 inline const GlobalsArray*
66 GlobalsArray::asGlobals(const ArrayData* ad) {
67 assertx(ad->kind() == kGlobalsKind);
68 return static_cast<const GlobalsArray*>(ad);
71 size_t GlobalsArray::Vsize(const ArrayData* ad) {
72 // We need to iterate to find out the actual size, since kNamedLocalDataType
73 // elements in the array may have been set to KindOfUninit.
74 auto a = asGlobals(ad);
75 if (a->m_tab->leaked()) return 0;
76 size_t count = 0;
77 auto iter_limit = IterEnd(a);
78 for (auto iter = IterBegin(a);
79 iter != iter_limit;
80 iter = IterAdvance(a, iter)) {
81 ++count;
83 return count;
86 Cell GlobalsArray::NvGetKey(const ArrayData* ad, ssize_t pos) {
87 auto a = asGlobals(ad);
88 NameValueTable::Iterator iter(a->m_tab, pos);
89 if (iter.valid()) {
90 auto k = iter.curKey();
91 if (k->isRefCounted()) {
92 k->rawIncRefCount();
93 return make_tv<KindOfString>(const_cast<StringData*>(k));
95 return make_tv<KindOfPersistentString>(k);
97 return make_tv<KindOfUninit>();
100 tv_rval GlobalsArray::GetValueRef(const ArrayData* ad, ssize_t pos) {
101 auto a = asGlobals(ad);
102 NameValueTable::Iterator iter(a->m_tab, pos);
103 return iter.valid() ? iter.curVal() : uninit_variant.asTypedValue();
106 bool
107 GlobalsArray::ExistsInt(const ArrayData* ad, int64_t k) {
108 return ExistsStr(ad, String(k).get());
111 bool
112 GlobalsArray::ExistsStr(const ArrayData* ad, const StringData* k) {
113 return asGlobals(ad)->m_tab->lookup(k) != nullptr;
116 tv_rval GlobalsArray::NvGetStr(const ArrayData* ad, const StringData* k) {
117 return asGlobals(ad)->m_tab->lookup(k);
120 tv_rval GlobalsArray::NvGetInt(const ArrayData* ad, int64_t k) {
121 return asGlobals(ad)->m_tab->lookup(String(k).get());
124 arr_lval GlobalsArray::LvalInt(ArrayData* ad, int64_t k, bool copy) {
125 return LvalStr(ad, String(k).get(), copy);
128 arr_lval GlobalsArray::LvalStr(ArrayData* ad, StringData* k, bool /*copy*/) {
129 auto a = asGlobals(ad);
130 TypedValue* tv = a->m_tab->lookup(k);
131 if (!tv) {
132 TypedValue nulVal;
133 tvWriteNull(nulVal);
134 tv = a->m_tab->set(k, &nulVal);
136 return arr_lval { ad, tv };
139 arr_lval GlobalsArray::LvalNew(ArrayData* ad, bool /*copy*/) {
140 return arr_lval { ad, lvalBlackHole().asTypedValue() };
143 ArrayData* GlobalsArray::SetIntInPlace(ArrayData* ad, int64_t k, Cell v) {
144 return SetStrInPlace(ad, String(k).get(), v);
147 ArrayData*
148 GlobalsArray::SetStrInPlace(ArrayData* ad, StringData* k, Cell v) {
149 auto a = asGlobals(ad);
150 cellSet(v, *tvToCell(a->m_tab->lookupAdd(k)));
151 return a;
154 ArrayData*
155 GlobalsArray::SetWithRefIntInPlace(ArrayData* ad, int64_t k, TypedValue v) {
156 return SetWithRefStrInPlace(ad, String(k).get(), v);
159 ArrayData*
160 GlobalsArray::SetWithRefStrInPlace(ArrayData* ad, StringData* k, TypedValue v) {
161 auto a = asGlobals(ad);
162 tvSetWithRef(v, *a->m_tab->lookupAdd(k));
163 return a;
166 ArrayData*
167 GlobalsArray::SetRefIntInPlace(ArrayData* ad, int64_t k, tv_lval v) {
168 return SetRefStrInPlace(ad, String(k).get(), v);
171 ArrayData*
172 GlobalsArray::SetRefStrInPlace(ArrayData* ad, StringData* k, tv_lval v) {
173 auto a = asGlobals(ad);
174 tvAsVariant(a->m_tab->lookupAdd(k)).assignRef(v);
175 return a;
178 ArrayData*
179 GlobalsArray::RemoveIntInPlace(ArrayData* ad, int64_t k) {
180 return RemoveStrInPlace(ad, String(k).get());
183 ArrayData*
184 GlobalsArray::RemoveStrInPlace(ArrayData* ad, const StringData* k) {
185 auto a = asGlobals(ad);
186 a->m_tab->unset(k);
187 return a;
191 * The messages in the user-visible exceptions below claim we are
192 * $GLOBALS, because the only user-visible GlobalsArray array
193 * is currently $GLOBALS.
196 ArrayData* GlobalsArray::AppendInPlace(ArrayData*, Cell /*v*/) {
197 throw_not_implemented("append on $GLOBALS");
200 ArrayData* GlobalsArray::AppendRefInPlace(ArrayData*, tv_lval) {
201 throw_not_implemented("appendRef on $GLOBALS");
204 ArrayData* GlobalsArray::AppendWithRefInPlace(ArrayData*, TypedValue) {
205 throw_not_implemented("appendWithRef on $GLOBALS");
208 ArrayData* GlobalsArray::PlusEq(ArrayData*, const ArrayData*) {
209 throw_not_implemented("plus on $GLOBALS");
212 ArrayData* GlobalsArray::Merge(ArrayData*, const ArrayData*) {
213 throw_not_implemented("merge on $GLOBALS");
216 ArrayData* GlobalsArray::Prepend(ArrayData*, Cell) {
217 throw_not_implemented("prepend on $GLOBALS");
220 ssize_t GlobalsArray::IterBegin(const ArrayData* ad) {
221 auto a = asGlobals(ad);
222 NameValueTable::Iterator iter(a->m_tab);
223 return iter.toInteger();
226 ssize_t GlobalsArray::IterLast(const ArrayData* ad) {
227 auto a = asGlobals(ad);
228 return NameValueTable::Iterator::getLast(a->m_tab).toInteger();
231 ssize_t GlobalsArray::IterEnd(const ArrayData* ad) {
232 auto a = asGlobals(ad);
233 return NameValueTable::Iterator::getEnd(a->m_tab).toInteger();
236 ssize_t GlobalsArray::IterAdvance(const ArrayData* ad, ssize_t prev) {
237 auto a = asGlobals(ad);
238 NameValueTable::Iterator iter(a->m_tab, prev);
239 iter.next();
240 return iter.toInteger();
243 ssize_t GlobalsArray::IterRewind(const ArrayData* ad, ssize_t prev) {
244 auto a = asGlobals(ad);
245 NameValueTable::Iterator iter(a->m_tab, prev);
246 iter.prev();
247 return iter.toInteger();
250 bool
251 GlobalsArray::ValidMArrayIter(const ArrayData* ad,
252 const MArrayIter & fp) {
253 assertx(fp.getContainer() == ad);
254 auto a = asGlobals(ad);
255 if (fp.getResetFlag()) return false;
256 if (fp.m_pos == IterEnd(a)) return false;
257 NameValueTable::Iterator iter(a->m_tab, fp.m_pos);
258 return iter.valid();
261 bool GlobalsArray::AdvanceMArrayIter(ArrayData* ad, MArrayIter& fp) {
262 auto a = asGlobals(ad);
263 bool reset = fp.getResetFlag();
264 NameValueTable::Iterator iter = reset ?
265 NameValueTable::Iterator(a->m_tab) :
266 NameValueTable::Iterator(a->m_tab, fp.m_pos);
267 if (reset) {
268 fp.setResetFlag(false);
269 } else {
270 if (!iter.valid()) {
271 return false;
273 iter.next();
275 fp.m_pos = iter.toInteger();
276 if (!iter.valid()) return false;
277 // To conform to PHP behavior, we need to set the internal
278 // cursor to point to the next element.
279 iter.next();
280 a->m_pos = iter.toInteger();
281 return true;
284 ArrayData* GlobalsArray::EscalateForSort(ArrayData* ad, SortFunction /*sf*/) {
285 raise_warning("Sorting the $GLOBALS array is not supported");
286 return ad;
288 void GlobalsArray::Ksort(ArrayData*, int /*sort_flags*/, bool /*ascending*/) {}
289 void GlobalsArray::Sort(ArrayData*, int /*sort_flags*/, bool /*ascending*/) {}
290 void GlobalsArray::Asort(ArrayData*, int /*sort_flags*/, bool /*ascending*/) {}
291 bool GlobalsArray::Uksort(ArrayData*, const Variant& /*cmp_function*/) {
292 return false;
294 bool GlobalsArray::Usort(ArrayData*, const Variant& /*cmp_function*/) {
295 return false;
297 bool GlobalsArray::Uasort(ArrayData*, const Variant& /*cmp_function*/) {
298 return false;
301 bool GlobalsArray::IsVectorData(const ArrayData*) {
302 return false;
305 ArrayData* GlobalsArray::CopyStatic(const ArrayData*) {
306 raise_fatal_error("GlobalsArray::copyStatic "
307 "not implemented.");
310 void GlobalsArray::Renumber(ArrayData*) {}
312 void GlobalsArray::OnSetEvalScalar(ArrayData*) {
313 not_reached();
316 //////////////////////////////////////////////////////////////////////