make PHP_SAPI dynamic based on execution mode
[hiphop-php.git] / hphp / runtime / base / class_info.cpp
blob2914191e0122aa4952e4e3dd8e6dd95a42b3e6fa
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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/array/array_util.h"
18 #include "hphp/runtime/base/class_info.h"
19 #include "hphp/runtime/base/complex_types.h"
20 #include "hphp/runtime/base/externals.h"
21 #include "hphp/runtime/base/hphp_system.h"
22 #include "hphp/runtime/base/variable_serializer.h"
23 #include "hphp/runtime/base/variable_unserializer.h"
24 #include "hphp/util/util.h"
25 #include "hphp/util/lock.h"
26 #include "hphp/util/logger.h"
28 namespace HPHP {
29 ///////////////////////////////////////////////////////////////////////////////
30 // statics
32 bool ClassInfo::s_loaded = false;
33 ClassInfo *ClassInfo::s_systemFuncs = nullptr;
34 ClassInfo::ClassMap ClassInfo::s_class_like;
35 ClassInfoHook *ClassInfo::s_hook = nullptr;
37 Array ClassInfo::GetSystemFunctions() {
38 assert(s_loaded);
40 Array ret = Array::Create();
41 if (s_systemFuncs) {
42 const MethodVec &methods = s_systemFuncs->getMethodsVec();
43 for (unsigned i = 0; i < methods.size(); i++) {
44 ret.append(methods[i]->name);
47 return ret;
50 Array ClassInfo::GetUserFunctions() {
51 assert(s_loaded);
53 Array ret = Array::Create();
54 if (s_hook) {
55 Array dyn = s_hook->getUserFunctions();
56 if (!dyn.isNull()) {
57 ret.merge(dyn);
58 // De-dup values, then renumber (for aesthetics).
59 ret = ArrayUtil::StringUnique(ret).toArrRef();
60 ret->renumber();
63 return ret;
66 const ClassInfo::MethodInfo *ClassInfo::FindSystemFunction(CStrRef name) {
67 assert(!name.isNull());
68 assert(s_loaded);
70 return s_systemFuncs->getMethodInfo(name);
73 const ClassInfo::MethodInfo *ClassInfo::FindFunction(CStrRef name) {
74 assert(!name.isNull());
75 assert(s_loaded);
77 const MethodInfo *ret = s_systemFuncs->getMethodInfo(name);
78 if (ret == nullptr && s_hook) {
79 ret = s_hook->findFunction(name);
81 return ret;
84 const ClassInfo *ClassInfo::FindClassInterfaceOrTrait(CStrRef name) {
85 assert(!name.isNull());
86 assert(s_loaded);
88 if (s_hook) {
89 const ClassInfo *r = s_hook->findClassLike(name);
90 if (r) return r;
93 ClassMap::const_iterator iter = s_class_like.find(name);
94 if (iter != s_class_like.end()) {
95 return iter->second->getDeclared();
98 return 0;
101 const ClassInfo *ClassInfo::FindClass(CStrRef name) {
102 if (const ClassInfo *r = FindClassInterfaceOrTrait(name)) {
103 return r->getAttribute() & (IsTrait|IsInterface) ? 0 : r;
105 return 0;
108 const ClassInfo *ClassInfo::FindInterface(CStrRef name) {
109 if (const ClassInfo *r = FindClassInterfaceOrTrait(name)) {
110 return r->getAttribute() & IsInterface ? r : 0;
112 return 0;
115 const ClassInfo *ClassInfo::FindTrait(CStrRef name) {
116 if (const ClassInfo *r = FindClassInterfaceOrTrait(name)) {
117 return r->getAttribute() & IsTrait ? r : 0;
119 return 0;
122 const ClassInfo *ClassInfo::FindSystemClassInterfaceOrTrait(CStrRef name) {
123 assert(!name.isNull());
124 assert(s_loaded);
126 ClassMap::const_iterator iter = s_class_like.find(name);
127 if (iter != s_class_like.end()) {
128 const ClassInfo *ci = iter->second;
129 if (ci->m_attribute & IsSystem) return ci;
132 return 0;
135 const ClassInfo *ClassInfo::FindSystemClass(CStrRef name) {
136 if (const ClassInfo *r = FindSystemClassInterfaceOrTrait(name)) {
137 return r->getAttribute() & (IsTrait|IsInterface) ? 0 : r;
139 return 0;
142 const ClassInfo *ClassInfo::FindSystemInterface(CStrRef name) {
143 if (const ClassInfo *r = FindSystemClassInterfaceOrTrait(name)) {
144 return r->getAttribute() & IsInterface ? r : 0;
146 return 0;
149 const ClassInfo *ClassInfo::FindSystemTrait(CStrRef name) {
150 if (const ClassInfo *r = FindSystemClassInterfaceOrTrait(name)) {
151 return r->getAttribute() & IsTrait ? r : 0;
153 return 0;
156 Array ClassInfo::GetClassLike(unsigned mask, unsigned value) {
157 assert(s_loaded);
159 Array ret = Array::Create();
160 for (ClassMap::const_iterator iter = s_class_like.begin();
161 iter != s_class_like.end(); ++iter) {
162 const ClassInfo *info = iter->second->getDeclared();
163 if (!info || (info->m_attribute & mask) != value) continue;
164 ret.append(info->m_name);
166 if (s_hook) {
167 if (value & IsInterface) {
168 Array dyn = s_hook->getInterfaces();
169 if (!dyn.isNull()) {
170 ret.merge(dyn);
171 // De-dup values, then renumber (for aesthetics).
172 ret = ArrayUtil::StringUnique(ret).toArrRef();
173 ret->renumber();
175 } else if (value & IsTrait) {
176 Array dyn = s_hook->getTraits();
177 if (!dyn.isNull()) {
178 ret.merge(dyn);
179 // De-dup values, then renumber (for aesthetics).
180 ret = ArrayUtil::StringUnique(ret).toArrRef();
181 ret->renumber();
183 } else {
184 Array dyn = s_hook->getClasses();
185 if (!dyn.isNull()) {
186 ret.merge(dyn);
187 // De-dup values, then renumber (for aesthetics).
188 ret = ArrayUtil::StringUnique(ret).toArrRef();
189 ret->renumber();
193 return ret;
196 ClassInfo::ConstantInfo::ConstantInfo() :
197 valueLen(0), callback(nullptr), deferred(true) {
200 CVarRef ClassInfo::ConstantInfo::getDeferredValue() const {
201 assert(deferred);
202 if (callback) {
203 CVarRef (*f)()=(CVarRef(*)())callback;
204 return (*f)();
206 SystemGlobals* g = get_global_variables();
207 return g->stgv_Variant[valueLen];
210 Variant ClassInfo::ConstantInfo::getValue() const {
211 if (deferred) {
212 return getDeferredValue();
214 if (!svalue.empty()) {
215 try {
216 VariableUnserializer vu(svalue.data(), svalue.size(),
217 VariableUnserializer::Serialize);
218 return vu.unserialize();
219 } catch (Exception &e) {
220 assert(false);
223 return value;
226 void ClassInfo::ConstantInfo::setValue(CVarRef value) {
227 VariableSerializer vs(VariableSerializer::Serialize);
228 String s = vs.serialize(value, true);
229 svalue = string(s.data(), s.size());
230 deferred = false;
233 void ClassInfo::ConstantInfo::setStaticValue(CVarRef v) {
234 value = v;
235 value.setEvalScalar();
236 deferred = false;
239 void ClassInfo::InitializeSystemConstants() {
240 assert(s_loaded);
241 const ConstantMap &scm = s_systemFuncs->getConstants();
242 for (ConstantMap::const_iterator it = scm.begin(); it != scm.end(); ++it) {
243 ConstantInfo* ci = it->second;
244 if (ci->isDynamic()) {
245 Unit::defDynamicSystemConstant(ci->name.get(), ci);
246 } else {
247 Variant v = ci->getValue();
248 bool DEBUG_ONLY res = Unit::defCns(ci->name.get(),
249 v.asTypedValue(), true);
250 assert(res);
255 Array ClassInfo::GetSystemConstants() {
256 assert(s_loaded);
257 Array res;
258 const ConstantMap &scm = s_systemFuncs->getConstants();
259 for (ConstantMap::const_iterator it = scm.begin(); it != scm.end(); ++it) {
260 if (!it->second->isDynamic()) {
261 res.set(it->second->name, it->second->getValue());
264 return res;
267 Array ClassInfo::GetConstants() {
268 assert(s_loaded);
269 Array res;
270 Array dyn;
272 const ConstantMap &scm = s_systemFuncs->getConstants();
273 for (ConstantMap::const_iterator it = scm.begin(); it != scm.end(); ++it) {
274 res.set(it->second->name, it->second->getValue());
277 if (s_hook) {
278 dyn = s_hook->getConstants();
279 if (!dyn.isNull()) {
280 res.merge(dyn);
283 return res;
286 ClassInfo::UserAttributeInfo::UserAttributeInfo() {
289 Variant ClassInfo::UserAttributeInfo::getValue() const {
290 return value;
293 void ClassInfo::UserAttributeInfo::setStaticValue(CVarRef v) {
294 value = v;
295 value.setEvalScalar();
298 bool ClassInfo::GetClassMethods(MethodVec &ret, CStrRef classname,
299 int type /* = 0 */) {
300 if (classname.empty()) return false;
302 const ClassInfo *classInfo = nullptr;
303 switch (type) {
304 case 0:
305 classInfo = FindClassInterfaceOrTrait(classname);
306 break;
307 case 1:
308 classInfo = FindClass(classname);
309 break;
310 case 2:
311 classInfo = FindInterface(classname);
312 break;
313 case 3:
314 classInfo = FindTrait(classname);
315 break;
316 default:
317 assert(false);
320 if (!classInfo) return false;
321 return GetClassMethods(ret, classInfo);
324 bool ClassInfo::GetClassMethods(MethodVec &ret, const ClassInfo *classInfo) {
325 const ClassInfo::MethodVec &methods = classInfo->getMethodsVec();
326 ret.insert(ret.end(), methods.begin(), methods.end());
328 if (!(classInfo->getAttribute() & (IsInterface|IsTrait))) {
329 CStrRef parentClass = classInfo->getParentClass();
330 if (!parentClass.empty()) {
331 if (!GetClassMethods(ret, parentClass, 1)) return false;
335 const ClassInfo::InterfaceVec &interfaces =
336 classInfo->getInterfacesVec();
337 for (unsigned int i = 0; i < interfaces.size(); i++) {
338 if (!GetClassMethods(ret, interfaces[i], 2)) return false;
341 return true;
344 void ClassInfo::GetClassSymbolNames(CArrRef names, bool interface, bool trait,
345 std::vector<String> &classes,
346 std::vector<String> *clsMethods,
347 std::vector<String> *clsProperties,
348 std::vector<String> *clsConstants) {
349 if (clsMethods || clsProperties || clsConstants) {
350 for (ArrayIter iter(names); iter; ++iter) {
351 String clsname = iter.second().toString();
352 classes.push_back(clsname);
354 const ClassInfo *cls;
355 if (interface) {
356 cls = FindInterface(clsname.data());
357 } else if (trait) {
358 cls = FindTrait(clsname.data());
359 } else {
360 try {
361 cls = FindClass(clsname.data());
362 } catch (Exception &e) {
363 Logger::Error("Caught exception %s", e.getMessage().c_str());
364 continue;
365 } catch(...) {
366 Logger::Error("Caught unknown exception");
367 continue;
370 assert(cls);
371 if (clsMethods) {
372 const ClassInfo::MethodVec &methods = cls->getMethodsVec();
373 for (unsigned int i = 0; i < methods.size(); i++) {
374 clsMethods->push_back(clsname + "::" + methods[i]->name);
377 if (clsProperties) {
378 const ClassInfo::PropertyVec &properties = cls->getPropertiesVec();
379 for (ClassInfo::PropertyVec::const_iterator iter = properties.begin();
380 iter != properties.end(); ++iter) {
381 clsProperties->push_back(clsname + "::$" + (*iter)->name);
384 if (clsConstants) {
385 const ClassInfo::ConstantVec &constants = cls->getConstantsVec();
386 for (ClassInfo::ConstantVec::const_iterator iter = constants.begin();
387 iter != constants.end(); ++iter) {
388 clsConstants->push_back(clsname + "::" + (*iter)->name);
392 } else {
393 for (ArrayIter iter(names); iter; ++iter) {
394 classes.push_back(iter.second().toString());
399 void ClassInfo::GetSymbolNames(std::vector<String> &classes,
400 std::vector<String> &functions,
401 std::vector<String> &constants,
402 std::vector<String> *clsMethods,
403 std::vector<String> *clsProperties,
404 std::vector<String> *clsConstants) {
405 static unsigned int methodSize = 128;
406 static unsigned int propSize = 128;
407 static unsigned int constSize = 128;
409 if (clsMethods) {
410 clsMethods->reserve(methodSize);
412 if (clsProperties) {
413 clsProperties->reserve(propSize);
415 if (clsConstants) {
416 clsConstants->reserve(constSize);
419 GetClassSymbolNames(GetClasses(), false, false, classes,
420 clsMethods, clsProperties, clsConstants);
421 GetClassSymbolNames(GetInterfaces(), true, false, classes,
422 clsMethods, clsProperties, clsConstants);
424 if (clsMethods && methodSize < clsMethods->size()) {
425 methodSize = clsMethods->size();
427 if (clsProperties && propSize < clsProperties->size()) {
428 propSize = clsProperties->size();
430 if (constSize && constSize < clsConstants->size()) {
431 constSize = clsConstants->size();
434 Array funcs1 = ClassInfo::GetSystemFunctions();
435 Array funcs2 = ClassInfo::GetUserFunctions();
436 functions.reserve(funcs1.size() + funcs2.size());
437 for (ArrayIter iter(funcs1); iter; ++iter) {
438 functions.push_back(iter.second().toString());
440 for (ArrayIter iter(funcs2); iter; ++iter) {
441 functions.push_back(iter.second().toString());
443 Array consts = GetConstants();
444 constants.reserve(consts.size());
445 for (ArrayIter iter(consts); iter; ++iter) {
446 constants.push_back(iter.first().toString());
450 ///////////////////////////////////////////////////////////////////////////////
451 // ClassInfo
453 const ClassInfo *ClassInfo::getDeclared() const {
454 if (m_attribute & IsRedeclared) {
455 return getCurrentOrNull();
456 } else if (m_attribute & IsVolatile) {
457 return *(bool*)((char*)get_global_variables() + m_cdec_offset) ? this : 0;
458 } else {
459 return this;
463 const ClassInfo *ClassInfo::getParentClassInfo() const {
464 CStrRef parentName = getParentClass();
465 if (parentName.empty()) return nullptr;
466 return FindClass(parentName);
469 ClassInfo::MethodInfo *ClassInfo::getMethodInfo(CStrRef name) const {
470 assert(!name.isNull());
472 const MethodMap &methods = getMethods();
473 MethodMap::const_iterator iter = methods.find(name);
474 if (iter != methods.end()) {
475 ClassInfo::MethodInfo *m = iter->second;
476 if (m->attribute & (IsVolatile|IsRedeclared)) {
477 return m->getDeclared();
479 return m;
481 return nullptr;
484 ClassInfo::MethodInfo *ClassInfo::hasMethod(CStrRef name,
485 ClassInfo* &classInfo,
486 bool interfaces /* = false */)
487 const {
488 assert(!name.isNull());
489 classInfo = (ClassInfo *)this;
490 const MethodMap &methods = getMethods();
491 MethodMap::const_iterator it = methods.find(name);
492 if (it != methods.end()) {
493 assert(!(it->second->attribute & (IsVolatile|IsRedeclared)));
494 return it->second;
496 ClassInfo::MethodInfo *result = nullptr;
497 const ClassInfo *parent = getParentClassInfo();
498 if (parent) result = parent->hasMethod(name, classInfo);
499 if (result || !interfaces || !(m_attribute & IsAbstract)) return result;
500 // TODO: consider caching the iface lookups
501 const InterfaceVec &ifaces = getInterfacesVec();
502 for (InterfaceVec::const_iterator it = ifaces.begin();
503 it != ifaces.end(); ++it) {
504 const ClassInfo *iface = FindInterface(*it);
505 if (iface) result = iface->hasMethod(name, classInfo, true);
506 if (result) return result;
508 return nullptr;
511 ///////////////////////////////////////////////////////////////////////////////
512 // load functions
514 static String makeStaticString(const char *s) {
515 if (!s) {
516 return null_string;
518 return StringData::GetStaticString(s);
521 void ClassInfo::ReadUserAttributes(const char **&p,
522 std::vector<const UserAttributeInfo*> &userAttrVec) {
523 while (*p) {
524 UserAttributeInfo *userAttr = new UserAttributeInfo();
525 userAttr->name = makeStaticString(*p++);
527 const char *len = *p++;
528 const char *valueText = *p++;
529 int64_t valueLen = (int64_t)len;
530 VariableUnserializer vu(valueText,
531 valueLen,
532 VariableUnserializer::Serialize);
533 userAttr->setStaticValue(vu.unserialize());
535 userAttrVec.push_back(userAttr);
539 ClassInfo::MethodInfo *ClassInfo::MethodInfo::getDeclared() {
540 assert(!(attribute & ClassInfo::IsRedeclared));
541 assert(!(attribute & ClassInfo::IsVolatile));
542 return this;
545 ClassInfo::MethodInfo::MethodInfo(const char **&p) {
546 attribute = (Attribute)(int64_t)(*p++);
547 name = makeStaticString(*p++);
548 docComment = 0;
549 if (attribute & ClassInfo::IsRedeclared) {
550 volatile_redec_offset = (int)(int64_t)(*p++);
551 while (*p) {
552 MethodInfo *m = new MethodInfo(p);
553 parameters.push_back((ParameterInfo*)(void*)m);
555 } else {
556 file = *p++;
557 line1 = (int)(int64_t)(*p++);
558 line2 = (int)(int64_t)(*p++);
559 if (attribute & IsVolatile) {
560 volatile_redec_offset = (int)(int64_t)(*p++);
563 if (attribute & HasDocComment) {
564 docComment = *p++;
567 if (attribute & IsSystem) {
568 returnType = (DataType)(int64_t)(*p++);
570 while (*p) {
571 ParameterInfo *parameter = new ParameterInfo();
572 parameter->attribute = (Attribute)(int64_t)(*p++);
573 parameter->name = *p++;
574 parameter->type = *p++;
575 if (attribute & IsSystem) {
576 parameter->argType = (DataType)(int64_t)(*p++);
578 parameter->value = *p++;
579 parameter->valueLen = (int64_t)*p++;
580 parameter->valueText = *p++;
581 parameter->valueTextLen = (int64_t)*p++;
583 ClassInfo::ReadUserAttributes(p, parameter->userAttrs);
584 p++;
586 parameters.push_back(parameter);
588 p++;
590 while (*p) {
591 ConstantInfo *staticVariable = new ConstantInfo();
592 staticVariable->name = makeStaticString(*p++);
593 staticVariable->valueLen = (int64_t)(*p++);
594 staticVariable->valueText = *p++;
595 VariableUnserializer vu(staticVariable->valueText,
596 staticVariable->valueLen,
597 VariableUnserializer::Serialize);
598 try {
599 staticVariable->setStaticValue(vu.unserialize());
600 } catch (Exception &e) {
601 assert(false);
603 staticVariables.push_back(staticVariable);
605 p++;
607 ClassInfo::ReadUserAttributes(p, userAttrs);
610 p++;
613 ClassInfoUnique::ClassInfoUnique(const char **&p) {
614 m_attribute = (Attribute)(int64_t)(*p++);
615 assert(!(m_attribute & IsRedeclared));
617 // ClassInfoUnique is only created by ClassInfo::Load(), which is called
618 // from hphp_process_init() in the thread-neutral initialization phase.
619 // It is OK to create StaticStrings here, and throw the smart ptrs away,
620 // because the underlying static StringData will not be released.
621 m_name = makeStaticString(*p++);
622 m_parent = makeStaticString(*p++);
623 m_parentInfo = 0;
625 m_file = *p++;
626 m_line1 = (int)(int64_t)(*p++);
627 m_line2 = (int)(int64_t)(*p++);
629 if (m_attribute & IsVolatile) {
630 m_cdec_offset = (int)(int64_t)(*p++);
633 if (m_attribute & HasDocComment) {
634 m_docComment = *p++;
637 while (*p) {
638 String iface_name = makeStaticString(*p++);
639 assert(m_interfaces.find(iface_name) == m_interfaces.end());
640 m_interfaces.insert(iface_name);
641 m_interfacesVec.push_back(iface_name);
643 p++;
645 if (m_attribute & ClassInfo::UsesTraits) {
646 while (*p) {
647 String trait_name = makeStaticString(*p++);
648 assert(m_traits.find(trait_name) == m_traits.end());
649 m_traits.insert(trait_name);
650 m_traitsVec.push_back(trait_name);
652 p++;
655 if (m_attribute & ClassInfo::HasAliasedMethods) {
656 while (*p) {
657 String new_name = makeStaticString(*p++);
658 String old_name = makeStaticString(*p++);
659 m_traitAliasesVec.push_back(std::pair<String, String>(
660 new_name, old_name));
662 p++;
665 while (*p) {
666 MethodInfo *method = new MethodInfo(p);
668 assert(m_methods.find(method->name) == m_methods.end());
669 m_methods[method->name] = method;
670 m_methodsVec.push_back(method);
672 p++;
674 while (*p) {
675 PropertyInfo *property = new PropertyInfo();
676 property->attribute = (Attribute)(int64_t)(*p++);
677 property->name = makeStaticString(*p++);
678 property->type = DataType((int)uintptr_t(*p++));
679 property->owner = this;
680 assert(m_properties.find(property->name) == m_properties.end());
681 m_properties[property->name] = property;
682 m_propertiesVec.push_back(property);
684 p++;
686 while (*p) {
687 ConstantInfo *constant = new ConstantInfo();
688 constant->name = makeStaticString(*p++);
689 const char *len_or_cw = *p++;
690 constant->valueText = *p++;
692 if (uintptr_t(constant->valueText) > 0x100) {
693 constant->valueLen = (int64_t)len_or_cw;
694 VariableUnserializer vu(constant->valueText,
695 constant->valueLen,
696 VariableUnserializer::Serialize);
697 try {
698 constant->setStaticValue(vu.unserialize());
699 } catch (Exception &e) {
700 assert(false);
702 } else if (constant->valueText) {
703 DataType dt = DataType((int)uintptr_t(constant->valueText) - 2);
704 constant->valueLen = 0;
705 constant->valueText = nullptr;
706 Variant v;
707 if (dt == KindOfUnknown) {
708 constant->valueLen = intptr_t(len_or_cw);
709 } else {
710 v = ClassInfo::GetVariant(dt, len_or_cw);
711 constant->setStaticValue(v);
713 } else {
714 constant->callback = (void*)len_or_cw;
717 assert(m_constants.find(constant->name) == m_constants.end());
718 m_constants[constant->name] = constant;
719 m_constantsVec.push_back(constant);
721 p++;
723 while (*p) {
724 UserAttributeInfo *userAttr = new UserAttributeInfo();
725 userAttr->name = makeStaticString(*p++);
727 const char *len = *p++;
728 const char *valueText = *p++;
729 int64_t valueLen = (int64_t)len;
730 VariableUnserializer vu(valueText,
731 valueLen,
732 VariableUnserializer::Serialize);
733 userAttr->setStaticValue(vu.unserialize());
735 m_userAttrVec.push_back(userAttr);
737 p++;
740 ClassInfoUnique::~ClassInfoUnique() {
741 for (auto it = m_userAttrVec.begin(); it != m_userAttrVec.end(); ++it) {
742 delete *it;
746 const ClassInfo *ClassInfoUnique::getParentClassInfo() const {
747 if (m_parentInfo) return m_parentInfo;
748 if (m_parent.empty()) return nullptr;
749 return FindClass(m_parent);
752 void ClassInfoUnique::postInit() {
753 if (m_parent.empty()) return;
754 const ClassInfo *ci = FindClassInterfaceOrTrait(m_parent);
755 if (!ci) return;
756 if ((m_attribute & IsInterface) !=
757 (ci->getAttribute() & (IsInterface|IsTrait|IsRedeclared))) {
758 return;
760 m_parentInfo = ci;
763 void ClassInfo::Load() {
764 if (s_loaded) return;
765 const char **p = g_class_map;
766 while (*p) {
767 Attribute attribute = (Attribute)(int64_t)*p;
768 always_assert(!(attribute & IsRedeclared));
769 ClassInfo *info = new ClassInfoUnique(p);
771 if (info->m_name.empty()) {
772 if (attribute & IsSystem) {
773 assert(s_systemFuncs == nullptr);
774 s_systemFuncs = info;
775 } else {
776 always_assert(false);
778 } else {
779 ClassInfo *&i = s_class_like[info->m_name];
780 assert(!i);
781 i = info;
785 assert(s_systemFuncs);
786 s_loaded = true;
788 for (ClassMap::iterator it = s_class_like.begin(), end = s_class_like.end();
789 it != end; ++it) {
790 it->second->postInit();
794 void ClassInfo::postInit() {}
796 ClassInfo::ParameterInfo::~ParameterInfo() {
797 for (auto it = userAttrs.begin(); it != userAttrs.end(); ++it) {
798 delete *it;
802 ClassInfo::MethodInfo::~MethodInfo() {
803 if (attribute & ClassInfo::IsRedeclared) {
804 for (vector<const ParameterInfo *>::iterator it = parameters.begin();
805 it != parameters.end(); ++it) {
806 delete (MethodInfo*)(void*)*it;
808 } else {
809 for (vector<const ParameterInfo *>::iterator it = parameters.begin();
810 it != parameters.end(); ++it) {
811 delete *it;
813 for (vector<const ConstantInfo *>::iterator it = staticVariables.begin();
814 it != staticVariables.end(); ++it) {
815 delete *it;
818 for (auto it = userAttrs.begin(); it != userAttrs.end(); ++it) {
819 delete *it;
823 ///////////////////////////////////////////////////////////////////////////////