Split fields of rds::StaticMethod so method names are compared correctly
[hiphop-php.git] / hphp / runtime / base / rds-symbol.cpp
blob0011edf26012a8d9d1ede1a2c9f924337a8b3c5f
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 #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>
27 #include <string>
28 #include <type_traits>
30 namespace HPHP::rds {
32 ///////////////////////////////////////////////////////////////////////////////
34 namespace {
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 {
77 return folly::format(
78 "{}:t{}:{}",
79 k.name,
80 k.transId,
81 k.bcOff
82 ).str();
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(
124 "{}{}::{}::{}",
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,
133 bool
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 &&
155 k1.name == k2.name;
158 template<class T>
159 typename std::enable_if<
160 std::is_same<T,StaticMethod>::value ||
161 std::is_same<T,StaticMethodF>::value,
162 bool
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 &&
202 k1.cls == k2.cls &&
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(
222 k.clsName->hash(),
223 k.cnsName->hash()
227 size_t operator()(Profile k) const {
228 return folly::hash::hash_combine(
229 static_cast<int>(k.kind),
230 k.transId,
231 k.bcOff,
232 k.name->hash()
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(
249 k.cls.get(), k.slot
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),
283 clsHash,
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 ///////////////////////////////////////////////////////////////////////////////