PageRenderTime 27ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/runtime/base/repo-auth-type.cpp

https://gitlab.com/alvinahmadov2/hhvm
C++ | 387 lines | 301 code | 47 blank | 39 comment | 98 complexity | d481fd7e256c261af113b88f1ee0cca3 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2015 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. +----------------------------------------------------------------------+
  15. */
  16. #include "hphp/runtime/base/repo-auth-type.h"
  17. #include <vector>
  18. #include <folly/Hash.h>
  19. #include "hphp/runtime/base/array-data-defs.h"
  20. #include "hphp/runtime/base/repo-auth-type-array.h"
  21. #include "hphp/runtime/base/object-data.h"
  22. #include "hphp/runtime/base/tv-helpers.h"
  23. #include "hphp/runtime/base/typed-value.h"
  24. #include "hphp/runtime/vm/unit.h"
  25. namespace HPHP {
  26. //////////////////////////////////////////////////////////////////////
  27. static_assert(sizeof(RepoAuthType) == sizeof(CompactTaggedPtr<void>), "");
  28. //////////////////////////////////////////////////////////////////////
  29. namespace {
  30. bool tvMatchesArrayType(TypedValue tv, const RepoAuthType::Array* arrTy) {
  31. assert(isArrayType(tv.m_type));
  32. auto const ad = tv.m_data.parr;
  33. using A = RepoAuthType::Array;
  34. auto sizeMatches = [&] {
  35. switch (arrTy->emptiness()) {
  36. case A::Empty::Maybe:
  37. return ad->size() == 0 || ad->size() == arrTy->size();
  38. case A::Empty::No:
  39. return ad->size() == arrTy->size();
  40. }
  41. not_reached();
  42. };
  43. // O(N) checks are available if you want them for debugging, but
  44. // they are too slow for general use in debug builds. These type
  45. // matching functions are currently only used for assertions, so
  46. // it's ok to leave them out.
  47. auto const use_slow_checks = false;
  48. switch (arrTy->tag()) {
  49. case A::Tag::Packed:
  50. if (!sizeMatches()) return false;
  51. if (use_slow_checks) {
  52. for (auto i = uint32_t{0}; i < ad->size(); ++i) {
  53. auto const elem = ad->nvGet(i);
  54. if (!tvMatchesRepoAuthType(*elem, arrTy->packedElem(i))) {
  55. return false;
  56. }
  57. }
  58. }
  59. break;
  60. case A::Tag::PackedN:
  61. if (use_slow_checks) {
  62. for (auto i = uint32_t{0}; i < ad->size(); ++i) {
  63. auto const elem = ad->nvGet(i);
  64. if (!tvMatchesRepoAuthType(*elem, arrTy->elemType())) {
  65. return false;
  66. }
  67. }
  68. }
  69. break;
  70. }
  71. return true;
  72. }
  73. }
  74. //////////////////////////////////////////////////////////////////////
  75. bool RepoAuthType::operator==(RepoAuthType o) const {
  76. using T = Tag;
  77. if (tag() != o.tag()) return false;
  78. switch (tag()) {
  79. case T::OptBool:
  80. case T::OptInt:
  81. case T::OptSStr:
  82. case T::OptStr:
  83. case T::OptDbl:
  84. case T::OptRes:
  85. case T::OptObj:
  86. case T::Null:
  87. case T::Cell:
  88. case T::Ref:
  89. case T::InitUnc:
  90. case T::Unc:
  91. case T::InitCell:
  92. case T::InitGen:
  93. case T::Gen:
  94. case T::Uninit:
  95. case T::InitNull:
  96. case T::Bool:
  97. case T::Int:
  98. case T::Dbl:
  99. case T::Res:
  100. case T::SStr:
  101. case T::Str:
  102. case T::Obj:
  103. return true;
  104. case T::OptSArr:
  105. case T::OptArr:
  106. // Can't currently have array() info.
  107. return true;
  108. case T::SArr:
  109. case T::Arr:
  110. if (array() == nullptr && o.array() == nullptr) {
  111. return true;
  112. }
  113. if ((array() == nullptr) != (o.array() == nullptr)) {
  114. return false;
  115. }
  116. return array()->id() == o.array()->id();
  117. case T::SubObj:
  118. case T::ExactObj:
  119. case T::OptSubObj:
  120. case T::OptExactObj:
  121. return clsName() == o.clsName();
  122. }
  123. not_reached();
  124. }
  125. size_t RepoAuthType::hash() const {
  126. auto const iTag = static_cast<size_t>(tag());
  127. if (hasClassName()) {
  128. return folly::hash::hash_128_to_64(iTag, clsName()->hash());
  129. }
  130. if (mayHaveArrData() && array()) {
  131. return folly::hash::hash_128_to_64(iTag, array()->id());
  132. }
  133. return iTag;
  134. }
  135. //////////////////////////////////////////////////////////////////////
  136. folly::Optional<DataType> convertToDataType(RepoAuthType ty) {
  137. using T = RepoAuthType::Tag;
  138. switch (ty.tag()) {
  139. case T::OptBool:
  140. case T::OptInt:
  141. case T::OptSArr:
  142. case T::OptArr:
  143. case T::OptSStr:
  144. case T::OptStr:
  145. case T::OptDbl:
  146. case T::OptRes:
  147. case T::OptSubObj:
  148. case T::OptExactObj:
  149. case T::OptObj:
  150. case T::Null:
  151. return folly::none;
  152. case T::Cell:
  153. case T::Ref:
  154. case T::InitUnc:
  155. case T::Unc:
  156. case T::InitCell:
  157. case T::InitGen:
  158. case T::Gen:
  159. return folly::none;
  160. case T::Uninit: return KindOfUninit;
  161. case T::InitNull: return KindOfNull;
  162. case T::Bool: return KindOfBoolean;
  163. case T::Int: return KindOfInt64;
  164. case T::Dbl: return KindOfDouble;
  165. case T::Res: return KindOfResource;
  166. case T::SStr:
  167. case T::Str: return KindOfString;
  168. case T::SArr:
  169. case T::Arr: return KindOfArray;
  170. case T::Obj:
  171. case T::SubObj:
  172. case T::ExactObj: return KindOfObject;
  173. }
  174. not_reached();
  175. }
  176. bool tvMatchesRepoAuthType(TypedValue tv, RepoAuthType ty) {
  177. assert(tvIsPlausible(tv));
  178. bool const initNull = tv.m_type == KindOfNull;
  179. using T = RepoAuthType::Tag;
  180. switch (ty.tag()) {
  181. case T::Uninit: return tv.m_type == KindOfUninit;
  182. case T::InitNull: return initNull;
  183. case T::OptBool: if (initNull) return true;
  184. // fallthrough
  185. case T::Bool: return tv.m_type == KindOfBoolean;
  186. case T::OptInt: if (initNull) return true;
  187. // fallthrough
  188. case T::Int: return tv.m_type == KindOfInt64;
  189. case T::OptDbl: if (initNull) return true;
  190. // fallthrough
  191. case T::Dbl: return tv.m_type == KindOfDouble;
  192. case T::OptRes: if (initNull) return true;
  193. // fallthrough
  194. case T::Res: return tv.m_type == KindOfResource;
  195. case T::OptObj: if (initNull) return true;
  196. // fallthrough
  197. case T::Obj: return tv.m_type == KindOfObject;
  198. case T::OptSStr:
  199. if (initNull) return true;
  200. // fallthrough
  201. case T::SStr:
  202. return tv.m_type == KindOfStaticString ||
  203. (tv.m_type == KindOfString && tv.m_data.pstr->isStatic());
  204. case T::OptStr:
  205. if (initNull) return true;
  206. // fallthrough
  207. case T::Str:
  208. return isStringType(tv.m_type);
  209. case T::OptSArr:
  210. if (initNull) return true;
  211. // fallthrough
  212. case T::SArr:
  213. if (!isArrayType(tv.m_type) || !tv.m_data.parr->isStatic()) {
  214. return false;
  215. }
  216. if (auto const arr = ty.array()) {
  217. if (!tvMatchesArrayType(tv, arr)) return false;
  218. }
  219. return true;
  220. case T::OptArr:
  221. if (initNull) return true;
  222. // fallthrough
  223. case T::Arr:
  224. if (!isArrayType(tv.m_type)) return false;
  225. if (auto const arr = ty.array()) {
  226. if (!tvMatchesArrayType(tv, arr)) return false;
  227. }
  228. return true;
  229. case T::Null:
  230. return initNull || tv.m_type == KindOfUninit;
  231. case T::OptSubObj:
  232. if (initNull) return true;
  233. // fallthrough
  234. case T::SubObj:
  235. {
  236. auto const cls = Unit::lookupClass(ty.clsName());
  237. if (!cls) return false;
  238. return tv.m_type == KindOfObject &&
  239. tv.m_data.pobj->getVMClass()->classof(cls);
  240. }
  241. case T::OptExactObj:
  242. if (initNull) return true;
  243. // fallthrough
  244. case T::ExactObj:
  245. {
  246. auto const cls = Unit::lookupClass(ty.clsName());
  247. if (!cls) return false;
  248. return tv.m_type == KindOfObject && tv.m_data.pobj->getVMClass() == cls;
  249. }
  250. case T::InitUnc:
  251. if (tv.m_type == KindOfUninit) return false;
  252. // fallthrough
  253. case T::Unc:
  254. return !isRefcountedType(tv.m_type) ||
  255. (tv.m_type == KindOfString && tv.m_data.pstr->isStatic()) ||
  256. (tv.m_type == KindOfArray && tv.m_data.parr->isStatic());
  257. case T::InitCell:
  258. if (tv.m_type == KindOfUninit) return false;
  259. // fallthrough
  260. case T::Cell:
  261. return tv.m_type != KindOfRef;
  262. case T::Ref:
  263. return tv.m_type == KindOfRef;
  264. case T::InitGen:
  265. if (tv.m_type == KindOfUninit) return false;
  266. // fallthrough
  267. case T::Gen:
  268. return true;
  269. }
  270. not_reached();
  271. }
  272. std::string show(RepoAuthType rat) {
  273. auto const tag = rat.tag();
  274. using T = RepoAuthType::Tag;
  275. switch (tag) {
  276. case T::OptBool: return "?Bool";
  277. case T::OptInt: return "?Int";
  278. case T::OptSStr: return "?SStr";
  279. case T::OptStr: return "?Str";
  280. case T::OptDbl: return "?Dbl";
  281. case T::OptRes: return "?Res";
  282. case T::OptObj: return "?Obj";
  283. case T::Null: return "Null";
  284. case T::Cell: return "Cell";
  285. case T::Ref: return "Ref";
  286. case T::InitUnc: return "InitUnc";
  287. case T::Unc: return "Unc";
  288. case T::InitCell: return "InitCell";
  289. case T::InitGen: return "InitGen";
  290. case T::Gen: return "Gen";
  291. case T::Uninit: return "Uninit";
  292. case T::InitNull: return "InitNull";
  293. case T::Bool: return "Bool";
  294. case T::Int: return "Int";
  295. case T::Dbl: return "Dbl";
  296. case T::Res: return "Res";
  297. case T::SStr: return "SStr";
  298. case T::Str: return "Str";
  299. case T::Obj: return "Obj";
  300. case T::OptSArr:
  301. case T::OptArr:
  302. case T::SArr:
  303. case T::Arr:
  304. {
  305. auto ret = std::string{};
  306. if (tag == T::OptArr || tag == T::OptSArr) {
  307. ret += '?';
  308. }
  309. if (tag == T::SArr || tag == T::OptSArr) {
  310. ret += 'S';
  311. }
  312. ret += "Arr";
  313. if (auto const ar = rat.array()) {
  314. folly::format(&ret, "{}", show(*ar));
  315. }
  316. return ret;
  317. }
  318. break;
  319. case T::OptSubObj:
  320. case T::OptExactObj:
  321. case T::SubObj:
  322. case T::ExactObj:
  323. {
  324. auto ret = std::string{};
  325. if (tag == T::OptSubObj || tag == T::OptExactObj) {
  326. ret += '?';
  327. }
  328. ret += "Obj";
  329. if (tag == T::OptSubObj || tag == T::SubObj) {
  330. ret += "<";
  331. }
  332. ret += '=';
  333. ret += rat.clsName()->data();
  334. return ret;
  335. }
  336. }
  337. not_reached();
  338. }
  339. //////////////////////////////////////////////////////////////////////
  340. }