2 +----------------------------------------------------------------------+
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 #include "hphp/runtime/base/rds-symbol.h"
19 #include "hphp/runtime/base/string-data.h"
20 #include "hphp/runtime/vm/class.h"
21 #include "hphp/runtime/vm/func.h"
23 #include <boost/variant.hpp>
24 #include <folly/Format.h>
25 #include <folly/Hash.h>
28 #include <type_traits>
32 ///////////////////////////////////////////////////////////////////////////////
36 struct SymbolKind
: boost::static_visitor
<std::string
> {
37 std::string
operator()(LinkName k
) const { return k
.type
; }
38 std::string
operator()(LinkID k
) const { return k
.type
; }
39 std::string
operator()(ClsConstant
) const { return "ClsConstant"; }
40 std::string
operator()(StaticMethod
) const { return "StaticMethod"; }
41 std::string
operator()(StaticMethodF
) const { return "StaticMethodF"; }
42 std::string
operator()(Profile
) const { return "Profile"; }
43 std::string
operator()(SPropCache
) const { return "SPropCache"; }
44 std::string
operator()(StaticMemoValue
) const { return "StaticMemoValue"; }
45 std::string
operator()(StaticMemoCache
) const { return "StaticMemoCache"; }
46 std::string
operator()(LSBMemoValue
) const { return "LSBMemoValue"; }
47 std::string
operator()(LSBMemoCache
) const { return "LSBMemoCache"; }
48 std::string
operator()(TSCache
) const { return "TSCache"; }
49 std::string
operator()(ModuleCache
) const { return "ModuleCache"; }
50 std::string
operator()(ConstMemoCache
) const { return "ConstMemoCache"; }
53 struct SymbolRep
: boost::static_visitor
<std::string
> {
54 std::string
operator()(LinkName k
) const { return k
.name
->data(); }
55 std::string
operator()(LinkID
) const { return ""; }
57 std::string
operator()(ClsConstant k
) const {
58 return k
.clsName
->data() + std::string("::") + k
.cnsName
->data();
61 std::string
operator()(StaticMethod k
) const {
62 return folly::to
<std::string
>(
63 k
.clsName
->toCppString(), "::",
64 k
.methName
->toCppString(), ":",
65 k
.ctxName
->toCppString()
68 std::string
operator()(StaticMethodF k
) const {
69 return folly::to
<std::string
>(
70 k
.clsName
->toCppString(), "::",
71 k
.methName
->toCppString(), ":",
72 k
.ctxName
->toCppString()
76 std::string
operator()(Profile k
) const {
84 std::string
operator()(SPropCache k
) const {
85 return k
.cls
->name()->toCppString() + "::" +
86 k
.cls
->staticProperties()[k
.slot
].name
->toCppString();
89 std::string
operator()(StaticMemoValue k
) const {
90 auto const func
= Func::fromFuncId(k
.funcId
);
91 return func
->fullName()->toCppString();
93 std::string
operator()(StaticMemoCache k
) const {
94 auto const func
= Func::fromFuncId(k
.funcId
);
95 return func
->fullName()->toCppString();
98 std::string
operator()(LSBMemoValue k
) const {
99 auto const clsName
= k
.cls
->name()->toCppString();
100 auto const funcName
= Func::fromFuncId(k
.funcId
)->fullName()->toCppString();
101 return clsName
+ "::" + funcName
;
103 std::string
operator()(LSBMemoCache k
) const {
104 auto const clsName
= k
.cls
->name()->toCppString();
105 auto const funcName
= Func::fromFuncId(k
.funcId
)->fullName()->toCppString();
106 return clsName
+ "::" + funcName
;
109 std::string
operator()(TSCache k
) const {
110 auto const func
= Func::fromFuncId(k
.funcId
);
111 return func
->fullName()->toCppString();
114 std::string
operator()(ModuleCache k
) const {
115 return k
.name
->toCppString();
118 std::string
operator()(ConstMemoCache k
) const {
119 auto const func
= Func::fromFuncId(k
.funcId
);
120 auto const funcName
= func
->fullName()->toCppString();
121 auto const clsPrefix
=
122 k
.cls
? folly::format("{}::", k
.cls
->name()).str() : "";
123 return folly::format(
125 clsPrefix
, funcName
, k
.paramVals
, k
.asyncEager
).str();
129 struct SymbolEq
: boost::static_visitor
<bool> {
130 template<class T
, class U
>
131 typename
std::enable_if
<
132 !std::is_same
<T
,U
>::value
,
134 >::type
operator()(const T
&, const U
&) const { return false; }
136 bool operator()(LinkName k1
, LinkName k2
) const {
137 return strcmp(k1
.type
, k2
.type
) == 0 && k1
.name
->isame(k2
.name
);
139 bool operator()(LinkID k1
, LinkID k2
) const {
140 return strcmp(k1
.type
, k2
.type
) == 0;
143 bool operator()(ClsConstant k1
, ClsConstant k2
) const {
144 assertx(k1
.clsName
->isStatic() && k1
.cnsName
->isStatic());
145 assertx(k2
.clsName
->isStatic() && k2
.cnsName
->isStatic());
146 return k1
.clsName
->isame(k2
.clsName
) &&
147 k1
.cnsName
== k2
.cnsName
;
150 bool operator()(Profile k1
, Profile k2
) const {
151 assertx(k1
.name
->isStatic() && k2
.name
->isStatic());
152 return k1
.kind
== k2
.kind
&&
153 k1
.transId
== k2
.transId
&&
154 k1
.bcOff
== k2
.bcOff
&&
159 typename
std::enable_if
<
160 std::is_same
<T
,StaticMethod
>::value
||
161 std::is_same
<T
,StaticMethodF
>::value
,
163 >::type
operator()(const T
& t1
, const T
& t2
) const {
164 assertx(t1
.clsName
->isStatic() && t2
.clsName
->isStatic());
165 assertx(t1
.methName
->isStatic() && t2
.methName
->isStatic());
166 assertx(t1
.ctxName
->isStatic() && t2
.ctxName
->isStatic());
167 return t1
.clsName
->isame(t2
.clsName
) &&
168 t1
.methName
== t2
.methName
&&
169 t1
.ctxName
->isame(t2
.ctxName
);
172 bool operator()(SPropCache k1
, SPropCache k2
) const {
173 return k1
.cls
== k2
.cls
&& k1
.slot
== k2
.slot
;
176 bool operator()(StaticMemoValue k1
, StaticMemoValue k2
) const {
177 return k1
.funcId
== k2
.funcId
;
180 bool operator()(StaticMemoCache k1
, StaticMemoCache k2
) const {
181 return k1
.funcId
== k2
.funcId
;
184 bool operator()(LSBMemoValue k1
, LSBMemoValue k2
) const {
185 return k1
.cls
== k2
.cls
&& k1
.funcId
== k2
.funcId
;
188 bool operator()(LSBMemoCache k1
, LSBMemoCache k2
) const {
189 return k1
.cls
== k2
.cls
&& k1
.funcId
== k2
.funcId
;
192 bool operator()(TSCache k1
, TSCache k2
) const {
193 return k1
.funcId
== k2
.funcId
;
196 bool operator()(ModuleCache k1
, ModuleCache k2
) const {
197 return k1
.name
->same(k2
.name
);
200 bool operator()(ConstMemoCache k1
, ConstMemoCache k2
) const {
201 return k1
.funcId
== k2
.funcId
&&
203 k1
.paramVals
== k2
.paramVals
&&
204 k1
.asyncEager
== k2
.asyncEager
;
208 struct SymbolHash
: boost::static_visitor
<size_t> {
209 // NOTE: Any hash functions that are not stable across HHVM
210 // restarts should be overridden with an appropriate hash in
211 // SymbolStableHash below.
212 size_t operator()(LinkName k
) const {
213 return folly::hash::hash_combine(
214 std::string
{k
.type
}, k
.name
->hash());
216 size_t operator()(LinkID k
) const {
217 return folly::hash::hash_combine(std::string
{k
.type
});
220 size_t operator()(ClsConstant k
) const {
221 return folly::hash::hash_128_to_64(
227 size_t operator()(Profile k
) const {
228 return folly::hash::hash_combine(
229 static_cast<int>(k
.kind
),
236 size_t operator()(StaticMethod k
) const {
237 return folly::hash::hash_combine(
238 k
.clsName
->hash(), k
.methName
->hash(), k
.ctxName
->hash()
241 size_t operator()(StaticMethodF k
) const {
242 return folly::hash::hash_combine(
243 k
.clsName
->hash(), k
.methName
->hash(), k
.ctxName
->hash()
247 size_t operator()(SPropCache k
) const {
248 return folly::hash::hash_combine(
253 size_t operator()(StaticMemoValue k
) const {
254 return std::hash
<FuncId
>()(k
.funcId
);
256 size_t operator()(StaticMemoCache k
) const {
257 return std::hash
<FuncId
>()(k
.funcId
);
260 size_t operator()(LSBMemoValue k
) const {
261 return folly::hash::hash_combine(
262 k
.cls
.get(), std::hash
<FuncId
>()(k
.funcId
)
265 size_t operator()(LSBMemoCache k
) const {
266 return folly::hash::hash_combine(
267 k
.cls
.get(), std::hash
<FuncId
>()(k
.funcId
)
271 size_t operator()(TSCache k
) const {
272 return std::hash
<FuncId
>()(k
.funcId
);
275 size_t operator()(ModuleCache k
) const {
276 return k
.name
->hash();
279 size_t operator()(ConstMemoCache k
) const {
280 auto const clsHash
= k
.cls
? k
.cls
->stableHash() : 0;
281 return folly::hash::hash_combine(
282 std::hash
<FuncId
>()(k
.funcId
),
284 std::hash
<const ArrayData
*>()(k
.paramVals
),
285 std::hash
<bool>()(k
.asyncEager
)
290 struct SymbolStableHash
: SymbolHash
{
291 using SymbolHash::operator();
292 size_t operator()(SPropCache k
) const {
293 return folly::hash::hash_combine(
294 k
.cls
->stableHash(), k
.slot
297 size_t operator()(StaticMemoValue k
) const {
298 return Func::fromFuncId(k
.funcId
)->stableHash();
300 size_t operator()(StaticMemoCache k
) const {
301 return Func::fromFuncId(k
.funcId
)->stableHash();
303 size_t operator()(LSBMemoValue k
) const {
304 return folly::hash::hash_combine(
305 k
.cls
->stableHash(), Func::fromFuncId(k
.funcId
)->stableHash()
308 size_t operator()(LSBMemoCache k
) const {
309 return folly::hash::hash_combine(
310 k
.cls
->stableHash(), Func::fromFuncId(k
.funcId
)->stableHash()
313 size_t operator()(TSCache k
) const {
314 return Func::fromFuncId(k
.funcId
)->stableHash();
320 std::string
symbol_kind(const Symbol
& sym
) {
321 return boost::apply_visitor(SymbolKind(), sym
);
323 std::string
symbol_rep(const Symbol
& sym
) {
324 return boost::apply_visitor(SymbolRep(), sym
);
326 bool symbol_eq(const Symbol
& sym1
, const Symbol
& sym2
) {
327 return boost::apply_visitor(SymbolEq(), sym1
, sym2
);
329 size_t symbol_hash(const Symbol
& sym
) {
330 return boost::apply_visitor(SymbolHash(), sym
);
332 size_t symbol_stable_hash(const Symbol
& sym
) {
333 return boost::apply_visitor(SymbolStableHash(), sym
);
336 ///////////////////////////////////////////////////////////////////////////////