2 +----------------------------------------------------------------------+
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 <gtest/gtest.h>
19 #include "folly/ScopeGuard.h"
21 #include "hphp/util/base.h"
22 #include "hphp/runtime/vm/jit/ir.h"
23 // for specialized object tests to get some real VM::Class
24 #include "hphp/system/systemlib.h"
26 namespace HPHP
{ namespace JIT
{
30 typedef hphp_hash_set
<Type
> TypeSet
;
34 # define IRT(name, ...) r.insert(Type::name);
42 TEST(Type
, Equality
) {
43 EXPECT_NE(Type::Cls
, Type::PtrToBoxedObj
);
47 EXPECT_TRUE(Type::Null
.isNull());
48 EXPECT_TRUE(Type::Uninit
.isNull());
49 EXPECT_TRUE(Type::InitNull
.isNull());
50 EXPECT_FALSE(Type::Bool
.isNull());
51 EXPECT_FALSE(Type::Null
.subtypeOf(Type::InitNull
));
52 EXPECT_NE(Type::Null
, Type::Uninit
);
53 EXPECT_NE(Type::Null
, Type::InitNull
);
56 TEST(Type
, KnownDataType
) {
58 Type::Int
, Type::BoxedCell
, Type::StaticStr
,
59 Type::Str
, // TODO(#3390819): this should return false...
70 for (auto t
: trueTypes
) {
71 EXPECT_TRUE(t
.isKnownDataType())
72 << t
.toString() << ".isKnownDataType()";
75 // Type::Null, // TODO(#3390819)
80 for (auto t
: falseTypes
) {
81 EXPECT_FALSE(t
.isKnownDataType())
82 << "!" << t
.toString() << ".isKnownDataType()";
86 TEST(Type
, ToString
) {
87 EXPECT_EQ("Int", Type::Int
.toString());
88 EXPECT_EQ("Cell", Type::Cell
.toString());
89 EXPECT_EQ("BoxedDbl", Type::BoxedDbl
.toString());
92 TEST(Type
, FromString
) {
93 EXPECT_EQ(Type::Int
, Type::fromString("Int"));
94 EXPECT_EQ(Type::None
, Type::fromString("Blah"));
95 EXPECT_EQ(Type::PtrToBoxedInt
, Type::fromString("PtrToBoxedInt"));
99 EXPECT_EQ(Type::BoxedDbl
, Type::Dbl
.box());
100 EXPECT_TRUE(Type::BoxedDbl
.isBoxed());
101 EXPECT_EQ(Type::Dbl
, Type::BoxedDbl
.unbox());
102 EXPECT_FALSE(Type::Dbl
.isBoxed());
103 EXPECT_EQ(Type::Cell
, Type::Gen
.unbox());
104 EXPECT_EQ((Type::BoxedCell
- Type::BoxedUninit
),
105 (Type::Cell
- Type::Uninit
).box());
107 EXPECT_EQ(Type::Bottom
, Type::BoxedCell
& Type::PtrToGen
);
109 EXPECT_FALSE(Type::Func
.isBoxed());
110 EXPECT_FALSE(Type::Func
.notBoxed());
112 EXPECT_EQ(Type::Int
| Type::Dbl
, (Type::Int
| Type::BoxedDbl
).unbox());
116 EXPECT_TRUE(Type::PtrToInt
.isPtr());
117 EXPECT_TRUE(Type::PtrToBoxedInt
.isPtr());
118 EXPECT_TRUE(Type::PtrToBoxedCell
.isPtr());
119 EXPECT_TRUE(Type::PtrToInt
.subtypeOf(Type::PtrToCell
));
121 EXPECT_EQ(Type::PtrToInt
, Type::Int
.ptr());
122 EXPECT_EQ(Type::PtrToCell
, Type::Cell
.ptr());
123 EXPECT_EQ(Type::Int
, Type::PtrToInt
.deref());
124 EXPECT_EQ(Type::BoxedCell
, Type::PtrToBoxedCell
.deref());
127 TEST(Type
, Subtypes
) {
128 Type numbers
= Type::Dbl
| Type::Int
;
129 EXPECT_EQ("{Int|Dbl}", numbers
.toString());
130 EXPECT_TRUE(Type::Dbl
.subtypeOf(numbers
));
131 EXPECT_TRUE(Type::Int
.subtypeOf(numbers
));
132 EXPECT_FALSE(Type::Bool
.subtypeOf(numbers
));
134 EXPECT_FALSE(Type::Func
.subtypeOf(Type::Cell
));
135 EXPECT_FALSE(Type::TCA
.subtypeOf(Type::Gen
));
137 EXPECT_TRUE(Type::PtrToCell
.strictSubtypeOf(Type::PtrToGen
));
140 TEST(Type
, RuntimeType
) {
141 auto sd
= StringData::MakeMalloced("", 0);
142 SCOPE_EXIT
{ sd
->destruct(); };
144 HPHP::JIT::RuntimeType
rt(sd
);
146 EXPECT_TRUE(t
.subtypeOf(Type::Str
));
147 EXPECT_FALSE(t
.subtypeOf(Type::Int
));
149 rt
= HPHP::JIT::RuntimeType(HphpArray::GetStaticEmptyArray());
151 EXPECT_TRUE(t
.subtypeOf(Type::Arr
));
152 EXPECT_FALSE(t
.subtypeOf(Type::Str
));
154 rt
= HPHP::JIT::RuntimeType(true);
156 EXPECT_TRUE(t
.subtypeOf(Type::Bool
));
157 EXPECT_FALSE(t
.subtypeOf(Type::Obj
));
159 rt
= HPHP::JIT::RuntimeType((int64_t) 1);
161 EXPECT_TRUE(t
.subtypeOf(Type::Int
));
162 EXPECT_FALSE(t
.subtypeOf(Type::Dbl
));
164 rt
= HPHP::JIT::RuntimeType(DataType::KindOfObject
,
165 DataType::KindOfInvalid
);
166 rt
= rt
.setKnownClass(SystemLib::s_TraversableClass
);
168 EXPECT_TRUE(t
.subtypeOf(Type::Obj
));
169 EXPECT_FALSE(Type::Obj
.subtypeOf(t
));
170 EXPECT_FALSE(Type::Int
.subtypeOf(t
));
171 HPHP::JIT::RuntimeType rt1
=
172 HPHP::JIT::RuntimeType(DataType::KindOfObject
,
173 DataType::KindOfInvalid
);
174 rt1
= rt1
.setKnownClass(SystemLib::s_IteratorClass
);
176 EXPECT_TRUE(t1
.subtypeOf(Type::Obj
));
177 EXPECT_TRUE(t1
.subtypeOf(t
));
178 EXPECT_FALSE(Type::Obj
.subtypeOf(t1
));
179 EXPECT_FALSE(t
.subtypeOf(t1
));
180 EXPECT_FALSE(t
.subtypeOf(Type::Str
));
181 EXPECT_FALSE(Type::Int
.subtypeOf(t
));
184 TEST(Type
, CanRunDtor
) {
185 TypeSet types
= allTypes();
186 auto expectTrue
= [&](Type t
) {
187 EXPECT_TRUE(t
.canRunDtor()) << t
.toString() << ".canRunDtor() == true";
190 expectTrue(Type::Arr
);
191 expectTrue(Type::CountedArr
);
192 expectTrue(Type::Obj
);
193 expectTrue(Type::Res
);
194 expectTrue(Type::Counted
);
195 expectTrue(Type::BoxedArr
);
196 expectTrue(Type::BoxedCountedArr
);
197 expectTrue(Type::BoxedObj
);
198 expectTrue(Type::BoxedRes
);
199 expectTrue(Type::BoxedInitCell
);
200 expectTrue(Type::BoxedCell
);
201 expectTrue(Type::InitCell
);
202 expectTrue(Type::Cell
);
203 expectTrue(Type::Gen
);
204 expectTrue(Type::Ctx
);
205 expectTrue(Type::Obj
| Type::Func
);
206 expectTrue(Type::Init
);
207 expectTrue(Type::Top
);
208 expectTrue(Type::StackElem
);
209 expectTrue(Type::AnyObj
);
210 expectTrue(Type::AnyRes
);
211 expectTrue(Type::AnyArr
);
212 expectTrue(Type::AnyCountedArr
);
213 expectTrue(Type::AnyInitCell
);
214 expectTrue(Type::AnyCell
);
216 for (Type t
: types
) {
217 EXPECT_FALSE(t
.canRunDtor()) << t
.toString() << ".canRunDtor == false";
221 TEST(Type
, UnionOf
) {
222 EXPECT_EQ(Type::PtrToGen
, Type::unionOf(Type::PtrToCell
, Type::PtrToGen
));
223 EXPECT_EQ(Type::UncountedInit
, Type::unionOf(Type::Int
, Type::Dbl
));
224 EXPECT_EQ(Type::Str
, Type::unionOf(Type::StaticStr
, Type::Str
));
225 EXPECT_EQ(Type::Gen
, Type::unionOf(Type::Cell
, Type::BoxedInt
));
229 for (auto t
: allTypes()) {
230 EXPECT_TRUE(t
.subtypeOf(Type::Top
));
232 for (auto t
: allTypes()) {
233 if (t
.equals(Type::Top
)) continue;
234 EXPECT_FALSE(Type::Top
.subtypeOf(t
));