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/vm/reified-generics.h"
19 #include "hphp/runtime/base/array-iterator.h"
20 #include "hphp/runtime/base/type-structure-helpers-defs.h"
22 #include "hphp/runtime/vm/act-rec.h"
23 #include "hphp/runtime/vm/named-entity.h"
24 #include "hphp/runtime/vm/reified-generics-info.h"
28 ///////////////////////////////////////////////////////////////////////////////
30 ArrayData
* addToTypeReifiedGenericsTable(
31 const StringData
* name
,
34 auto const ne
= NamedType::getOrCreate(name
);
35 auto const generics
= ne
->getCachedReifiedGenerics();
37 // We have created a new entry on the named entity table
38 // TODO(T31677864): If the type structures only contain persistent data,
39 // mark it as persistent
40 ne
->m_cachedReifiedGenerics
.bind(
42 rds::LinkName
{"ReifiedGenerics", name
}
44 ArrayData::GetScalarArray(&tsList
);
45 ne
->setCachedReifiedGenerics(tsList
);
48 // Same key should never result in different values.
49 // If this assertion fires, there's a high chance that two different type
50 // structure mangle to the same name and they should not.
51 assert_flog(tsList
->same(generics
),
52 "reified ts mismatch\nname: {}\ntsList: {}\ngenerics: {}\n",
54 staticArrayStreamer(tsList
),
55 staticArrayStreamer(generics
));
60 ArrayData
* getClsReifiedGenericsProp(Class
* cls
, ObjectData
* obj
) {
61 if (!cls
->hasReifiedGenerics()) {
62 raise_error("Cannot get reified generics property of a non reified class");
64 auto const slot
= cls
->lookupReifiedInitProp();
65 assertx(slot
!= kInvalidSlot
);
66 auto index
= cls
->propSlotToIndex(slot
);
67 auto tv
= obj
->props()->at(index
).tv();
69 return tv
.m_data
.parr
;
73 extractSizeAndPosFromReifiedAttribute(const ArrayData
* arr
) {
74 size_t len
= 0, cur
= 0, numReified
= 0;
75 bool isReified
= false, isSoft
= false, hasAnySoft
= false;
77 std::vector
<TypeParamInfo
> tpList
;
80 [&](TypedValue k
, TypedValue v
) {
81 assertx(isIntType(k
.m_type
));
82 assertx(isIntType(v
.m_type
));
83 if (k
.m_data
.num
== 0) {
84 len
= (size_t) v
.m_data
.num
;
86 if (k
.m_data
.num
% 3 == 1) {
87 // This is the reified generic index
88 // Insert the non reified ones
89 auto const numErased
= v
.m_data
.num
- cur
;
90 tpList
.insert(tpList
.end(), numErased
, {});
91 bitmap
= (bitmap
<< (numErased
+ 1)) | 1;
94 } else if (k
.m_data
.num
% 3 == 2) {
95 isSoft
= (bool) v
.m_data
.num
;
98 // k.m_data.num % 3 == 0
101 tpList
.push_back({isReified
, isSoft
, (bool) v
.m_data
.num
});
106 // Insert the non reified ones at the end
107 tpList
.insert(tpList
.end(), len
- cur
, {});
108 bitmap
= bitmap
<< (len
- cur
);
109 return {numReified
, hasAnySoft
, bitmap
, tpList
};
112 // Raises a runtime error if the location of reified generics of f does not
113 // match the location of reified_generics
115 void checkReifiedGenericMismatchHelper(
116 const ReifiedGenericsInfo
& info
,
117 const StringData
* name
,
118 const ArrayData
* reified_generics
120 auto const& generics
= info
.m_typeParamInfo
;
121 auto const len
= generics
.size();
122 if (len
!= reified_generics
->size()) {
123 if (reified_generics
->size() == 0) {
124 if (areAllGenericsSoft(info
)) {
125 raise_warning_for_soft_reified(0, fun
, name
);
129 SystemLib::throwBadMethodCallExceptionObject(
130 folly::sformat("{} {} requires {} generics but {} given",
131 fun
? "Function" : "Class",
134 reified_generics
->size()));
136 auto it
= generics
.begin();
139 [&](TypedValue k
, TypedValue v
) {
140 assertx(isIntType(k
.m_type
));
141 assertx(isArrayLikeType(v
.m_type
));
142 auto const i
= k
.m_data
.num
;
143 if (isWildCard(v
.m_data
.parr
) && it
->m_isReified
) {
145 SystemLib::throwBadMethodCallExceptionObject(
146 folly::sformat("{} {} expects a reified generic at index {}",
147 fun
? "Function" : "Class",
151 raise_warning_for_soft_reified(i
, fun
, name
);
158 void checkFunReifiedGenericMismatch(
160 const ArrayData
* reified_generics
162 checkReifiedGenericMismatchHelper
<true>(
163 f
->getReifiedGenericsInfo(),
169 void checkClassReifiedGenericMismatch(
171 const ArrayData
* reified_generics
173 checkReifiedGenericMismatchHelper
<false>(
174 c
->getReifiedGenericsInfo(),
180 uint16_t getGenericsBitmap(const ArrayData
* generics
) {
182 if (generics
->size() > 15) return 0;
187 assertx(isArrayLikeType(v
.m_type
));
188 bitmap
= (bitmap
<< 1) | !isWildCard(v
.m_data
.parr
);
194 uint16_t getGenericsBitmap(const Func
* f
) {
196 if (!f
->hasReifiedGenerics()) return 0;
197 auto const& info
= f
->getReifiedGenericsInfo();
198 if (info
.m_typeParamInfo
.size() > 15) return 0;
200 for (auto const& tinfo
: info
.m_typeParamInfo
) {
201 bitmap
= (bitmap
<< 1) | (tinfo
.m_isReified
&& !tinfo
.m_isSoft
);
206 bool areAllGenericsSoft(const ReifiedGenericsInfo
& info
) {
207 for (auto const& tp
: info
.m_typeParamInfo
) {
208 if (!tp
.m_isSoft
) return false;
213 void raise_warning_for_soft_reified(size_t i
, bool fun
,
214 const StringData
*name
) {
215 raise_warning("Generic at index %zu to %s %s must be reified,"
218 fun
? "Function" : "Class",
222 void checkClassReifiedGenericsSoft(const Class
* cls
) {
223 assertx(cls
->hasReifiedGenerics());
224 if (areAllGenericsSoft(cls
->getReifiedGenericsInfo())) {
225 raise_warning_for_soft_reified(0, false, cls
->name());
227 raise_error("Cannot create a new instance of a reified class without "
228 "the reified generics");
232 ///////////////////////////////////////////////////////////////////////////////