PageRenderTime 24ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/hphp/runtime/vm/class-inl.h

https://gitlab.com/0072016/0072016-PHP.LLC
C Header | 522 lines | 338 code | 117 blank | 67 comment | 13 complexity | e3b1a863519ee70b27adc9614c318099 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. #ifndef incl_HPHP_VM_CLASS_INL_H_
  17. #error "class-inl.h should only be included by class.h"
  18. #endif
  19. #include "hphp/runtime/base/runtime-error.h"
  20. #include "hphp/runtime/base/strings.h"
  21. namespace HPHP {
  22. ///////////////////////////////////////////////////////////////////////////////
  23. inline bool Class::isZombie() const {
  24. return !m_cachedClass.bound();
  25. }
  26. ///////////////////////////////////////////////////////////////////////////////
  27. // Class::PropInitVec.
  28. inline Class::PropInitVec::iterator Class::PropInitVec::begin() {
  29. return m_data;
  30. }
  31. inline Class::PropInitVec::iterator Class::PropInitVec::end() {
  32. return m_data + m_size;
  33. }
  34. inline size_t Class::PropInitVec::size() const {
  35. return m_size;
  36. }
  37. inline TypedValueAux& Class::PropInitVec::operator[](size_t i) {
  38. assert(i < m_size);
  39. return m_data[i];
  40. }
  41. inline const TypedValueAux& Class::PropInitVec::operator[](size_t i) const {
  42. assert(i < m_size);
  43. return m_data[i];
  44. }
  45. ///////////////////////////////////////////////////////////////////////////////
  46. // Pre- and post-allocations.
  47. inline const LowPtr<Class>* Class::classVec() const {
  48. return m_classVec;
  49. }
  50. inline Class::veclen_t Class::classVecLen() const {
  51. return m_classVecLen;
  52. }
  53. ///////////////////////////////////////////////////////////////////////////////
  54. // Ancestry.
  55. inline bool Class::classofNonIFace(const Class* cls) const {
  56. assert(!(cls->attrs() & AttrInterface));
  57. if (m_classVecLen >= cls->m_classVecLen) {
  58. return (m_classVec[cls->m_classVecLen-1] == cls);
  59. }
  60. return false;
  61. }
  62. inline bool Class::classof(const Class* cls) const {
  63. // If `cls' is an interface, we can simply check to see if cls is in
  64. // this->m_interfaces. Otherwise, if `this' is not an interface, the
  65. // classVec check will determine whether it's an instance of cls (including
  66. // the case where this and cls are the same trait). Otherwise, `this' is an
  67. // interface, and `cls' is not, so we need to return false. But the classVec
  68. // check can never return true in that case (cls's classVec contains only
  69. // non-interfaces, while this->classVec is either empty, or contains
  70. // interfaces).
  71. if (UNLIKELY(cls->attrs() & AttrInterface)) {
  72. return this == cls ||
  73. m_interfaces.lookupDefault(cls->m_preClass->name(), nullptr) == cls;
  74. }
  75. return classofNonIFace(cls);
  76. }
  77. inline bool Class::ifaceofDirect(const StringData* name) const {
  78. return m_interfaces.contains(name);
  79. }
  80. ///////////////////////////////////////////////////////////////////////////////
  81. // Basic info.
  82. inline const StringData* Class::name() const {
  83. return m_preClass->name();
  84. }
  85. inline const PreClass* Class::preClass() const {
  86. return m_preClass.get();
  87. }
  88. inline Class* Class::parent() const {
  89. return m_parent.get();
  90. }
  91. inline StrNR Class::nameStr() const {
  92. return m_preClass->nameStr();
  93. }
  94. inline StrNR Class::parentStr() const {
  95. return m_preClass->parentStr();
  96. }
  97. inline Attr Class::attrs() const {
  98. assert(Attr(m_attrCopy) == m_preClass->attrs());
  99. return Attr(m_attrCopy);
  100. }
  101. inline int Class::getODAttrs() const {
  102. return m_ODAttrs;
  103. }
  104. inline bool Class::isPersistent() const {
  105. return attrs() & AttrPersistent;
  106. }
  107. ///////////////////////////////////////////////////////////////////////////////
  108. // Magic methods.
  109. inline const Func* Class::getCtor() const {
  110. return m_ctor;
  111. }
  112. inline const Func* Class::getDtor() const {
  113. return m_dtor;
  114. }
  115. inline const Func* Class::getToString() const {
  116. return m_toString;
  117. }
  118. ///////////////////////////////////////////////////////////////////////////////
  119. // Builtin classes.
  120. inline bool Class::isBuiltin() const {
  121. return attrs() & AttrBuiltin;
  122. }
  123. inline const ClassInfo* Class::clsInfo() const {
  124. return m_extra->m_clsInfo;
  125. }
  126. inline BuiltinCtorFunction Class::instanceCtor() const {
  127. return m_extra->m_instanceCtor;
  128. }
  129. inline BuiltinDtorFunction Class::instanceDtor() const {
  130. return m_extra->m_instanceDtor;
  131. }
  132. inline int32_t Class::builtinODTailSize() const {
  133. return m_extra->m_builtinODTailSize;
  134. }
  135. ///////////////////////////////////////////////////////////////////////////////
  136. // Methods.
  137. inline size_t Class::numMethods() const {
  138. return m_methods.size();
  139. }
  140. inline Func* Class::getMethod(Slot idx) const {
  141. auto funcVec = (LowPtr<Func>*)this;
  142. return funcVec[-((int32_t)idx + 1)];
  143. }
  144. inline void Class::setMethod(Slot idx, Func* func) {
  145. auto funcVec = (LowPtr<Func>*)this;
  146. funcVec[-((int32_t)idx + 1)] = func;
  147. }
  148. inline Func* Class::lookupMethod(const StringData* methName) const {
  149. Slot* idx = m_methods.find(methName);
  150. if (!idx) return nullptr;
  151. return getMethod(*idx);
  152. }
  153. ///////////////////////////////////////////////////////////////////////////////
  154. // Property metadata.
  155. inline size_t Class::numDeclProperties() const {
  156. return m_declProperties.size();
  157. }
  158. inline size_t Class::numStaticProperties() const {
  159. return m_staticProperties.size();
  160. }
  161. inline uint32_t Class::declPropNumAccessible() const {
  162. return m_declPropNumAccessible;
  163. }
  164. inline const Class::Prop* Class::declProperties() const {
  165. return m_declProperties.accessList();
  166. }
  167. inline const Class::SProp* Class::staticProperties() const {
  168. return m_staticProperties.accessList();
  169. }
  170. inline Slot Class::lookupDeclProp(const StringData* propName) const {
  171. return m_declProperties.findIndex(propName);
  172. }
  173. inline Slot Class::lookupSProp(const StringData* sPropName) const {
  174. return m_staticProperties.findIndex(sPropName);
  175. }
  176. inline RepoAuthType Class::declPropRepoAuthType(Slot index) const {
  177. return m_declProperties[index].m_repoAuthType;
  178. }
  179. inline RepoAuthType Class::staticPropRepoAuthType(Slot index) const {
  180. return m_staticProperties[index].m_repoAuthType;
  181. }
  182. inline bool Class::hasDeepInitProps() const {
  183. return m_hasDeepInitProps;
  184. }
  185. ///////////////////////////////////////////////////////////////////////////////
  186. // Property initialization.
  187. inline bool Class::needInitialization() const {
  188. return m_needInitialization;
  189. }
  190. inline const Class::PropInitVec& Class::declPropInit() const {
  191. return m_declPropInit;
  192. }
  193. inline const FixedVector<const Func*>& Class::pinitVec() const {
  194. return m_pinitVec;
  195. }
  196. ///////////////////////////////////////////////////////////////////////////////
  197. // Property storage.
  198. inline void Class::initPropHandle() const {
  199. m_propDataCache.bind();
  200. }
  201. inline rds::Handle Class::propHandle() const {
  202. return m_propDataCache.handle();
  203. }
  204. inline rds::Handle Class::sPropInitHandle() const {
  205. return m_sPropCacheInit.handle();
  206. }
  207. inline rds::Handle Class::sPropHandle(Slot index) const {
  208. assert(m_sPropCacheInit.bound());
  209. assert(numStaticProperties() > index);
  210. return m_sPropCache[index].handle();
  211. }
  212. ///////////////////////////////////////////////////////////////////////////////
  213. // Constants.
  214. inline size_t Class::numConstants() const {
  215. return m_constants.size();
  216. }
  217. inline const Class::Const* Class::constants() const {
  218. return m_constants.accessList();
  219. }
  220. inline bool Class::hasConstant(const StringData* clsCnsName) const {
  221. // m_constants.contains(clsCnsName) returns abstract constants
  222. auto clsCnsInd = m_constants.findIndex(clsCnsName);
  223. return (clsCnsInd != kInvalidSlot) &&
  224. !m_constants[clsCnsInd].isAbstract() &&
  225. !m_constants[clsCnsInd].isType();
  226. }
  227. inline bool Class::hasTypeConstant(const StringData* typeConstName,
  228. bool includeAbs) const {
  229. auto typeConstInd = m_constants.findIndex(typeConstName);
  230. return (typeConstInd != kInvalidSlot) &&
  231. (!m_constants[typeConstInd].isAbstract() || includeAbs) &&
  232. m_constants[typeConstInd].isType();
  233. }
  234. ///////////////////////////////////////////////////////////////////////////////
  235. // Interfaces and traits.
  236. inline folly::Range<const ClassPtr*> Class::declInterfaces() const {
  237. return folly::range(
  238. m_declInterfaces.get(),
  239. m_declInterfaces.get() + m_numDeclInterfaces
  240. );
  241. }
  242. inline const Class::InterfaceMap& Class::allInterfaces() const {
  243. return m_interfaces;
  244. }
  245. inline Slot Class::traitsBeginIdx() const {
  246. return m_extra->m_traitsBeginIdx;
  247. }
  248. inline Slot Class::traitsEndIdx() const {
  249. return m_extra->m_traitsEndIdx;
  250. }
  251. inline const std::vector<ClassPtr>& Class::usedTraitClasses() const {
  252. return m_extra->m_usedTraits;
  253. }
  254. inline const Class::TraitAliasVec& Class::traitAliases() const {
  255. return m_extra->m_traitAliases;
  256. }
  257. inline const Class::RequirementMap& Class::allRequirements() const {
  258. return m_requirements;
  259. }
  260. ///////////////////////////////////////////////////////////////////////////////
  261. // Objects.
  262. inline bool Class::callsCustomInstanceInit() const {
  263. return m_callsCustomInstanceInit;
  264. }
  265. ///////////////////////////////////////////////////////////////////////////////
  266. // JIT data.
  267. inline rds::Handle Class::classHandle() const {
  268. return m_cachedClass.handle();
  269. }
  270. inline void Class::setClassHandle(rds::Link<Class*> link) const {
  271. assert(!m_cachedClass.bound());
  272. m_cachedClass = link;
  273. }
  274. inline Class* Class::getCached() const {
  275. return *m_cachedClass;
  276. }
  277. inline void Class::setCached() {
  278. *m_cachedClass = this;
  279. }
  280. ///////////////////////////////////////////////////////////////////////////////
  281. // Native data.
  282. inline const Native::NativeDataInfo* Class::getNativeDataInfo() const {
  283. return m_extra->m_nativeDataInfo;
  284. }
  285. ///////////////////////////////////////////////////////////////////////////////
  286. // Closure subclasses.
  287. inline bool Class::isScopedClosure() const {
  288. return m_scoped;
  289. }
  290. inline const Class::ScopedClonesMap& Class::scopedClones() const {
  291. return m_extra->m_scopedClones;
  292. }
  293. ///////////////////////////////////////////////////////////////////////////////
  294. // Other methods.
  295. inline MaybeDataType Class::enumBaseTy() const {
  296. return m_enumBaseTy;
  297. }
  298. ///////////////////////////////////////////////////////////////////////////////
  299. // ExtraData.
  300. inline void Class::allocExtraData() {
  301. if (!m_extra) {
  302. m_extra = new ExtraData();
  303. }
  304. }
  305. ///////////////////////////////////////////////////////////////////////////////
  306. // Trait method import.
  307. inline bool Class::TMIOps::strEmpty(const StringData* str) {
  308. return str->empty();
  309. }
  310. inline const StringData* Class::TMIOps::clsName(const Class* traitCls) {
  311. return traitCls->name();
  312. }
  313. inline bool Class::TMIOps::isTrait(const Class* traitCls) {
  314. return traitCls->attrs() & AttrTrait;
  315. }
  316. inline bool Class::TMIOps::isAbstract(Attr modifiers) {
  317. return modifiers & AttrAbstract;
  318. }
  319. inline Class::TraitMethod
  320. Class::TMIOps::traitMethod(const Class* traitCls,
  321. const Func* traitMeth,
  322. Class::TMIOps::alias_type rule) {
  323. return TraitMethod { traitCls, traitMeth, rule.modifiers() };
  324. }
  325. inline const StringData*
  326. Class::TMIOps::precMethodName(Class::TMIOps::prec_type rule) {
  327. return rule.methodName();
  328. }
  329. inline const StringData*
  330. Class::TMIOps::precSelectedTraitName(Class::TMIOps::prec_type rule) {
  331. return rule.selectedTraitName();
  332. }
  333. inline TraitNameSet
  334. Class::TMIOps::precOtherTraitNames(Class::TMIOps::prec_type rule) {
  335. return rule.otherTraitNames();
  336. }
  337. inline const StringData*
  338. Class::TMIOps::aliasTraitName(Class::TMIOps::alias_type rule) {
  339. return rule.traitName();
  340. }
  341. inline const StringData*
  342. Class::TMIOps::aliasOrigMethodName(Class::TMIOps::alias_type rule) {
  343. return rule.origMethodName();
  344. }
  345. inline const StringData*
  346. Class::TMIOps::aliasNewMethodName(Class::TMIOps::alias_type rule) {
  347. return rule.newMethodName();
  348. }
  349. inline Attr
  350. Class::TMIOps::aliasModifiers(Class::TMIOps::alias_type rule) {
  351. return rule.modifiers();
  352. }
  353. inline const Func*
  354. Class::TMIOps::findTraitMethod(const Class* cls,
  355. const Class* traitCls,
  356. const StringData* origMethName) {
  357. return traitCls->lookupMethod(origMethName);
  358. }
  359. inline void
  360. Class::TMIOps::errorUnknownMethod(Class::TMIOps::prec_type rule) {
  361. raise_error("unknown method '%s'", rule.methodName()->data());
  362. }
  363. inline void
  364. Class::TMIOps::errorUnknownMethod(Class::TMIOps::alias_type rule,
  365. const StringData* methName) {
  366. raise_error(Strings::TRAITS_UNKNOWN_TRAIT_METHOD, methName->data());
  367. }
  368. template <class Rule>
  369. inline void
  370. Class::TMIOps::errorUnknownTrait(const Rule& rule,
  371. const StringData* traitName) {
  372. raise_error(Strings::TRAITS_UNKNOWN_TRAIT, traitName->data());
  373. }
  374. inline void
  375. Class::TMIOps::errorDuplicateMethod(const Class* cls,
  376. const StringData* methName) {
  377. // No error if the class will override the method.
  378. if (cls->preClass()->hasMethod(methName)) return;
  379. raise_error(Strings::METHOD_IN_MULTIPLE_TRAITS, methName->data());
  380. }
  381. ///////////////////////////////////////////////////////////////////////////////
  382. // Non-member functions.
  383. inline Attr classKindAsAttr(ClassKind kind) {
  384. return static_cast<Attr>(kind);
  385. }
  386. inline bool isTrait(const Class* cls) {
  387. return cls->attrs() & AttrTrait;
  388. }
  389. inline bool isEnum(const Class* cls) {
  390. return cls->attrs() & AttrEnum;
  391. }
  392. inline bool isInterface(const Class* cls) {
  393. return cls->attrs() & AttrInterface;
  394. }
  395. inline bool isNormalClass(const Class* cls) {
  396. return !(cls->attrs() & (AttrTrait | AttrInterface | AttrEnum));
  397. }
  398. inline bool isAbstract(const Class* cls) {
  399. return cls->attrs() & AttrAbstract;
  400. }
  401. inline bool classHasPersistentRDS(const Class* cls) {
  402. return cls && rds::isPersistentHandle(cls->classHandle());
  403. }
  404. ///////////////////////////////////////////////////////////////////////////////
  405. }