Fix a bug in preOptimizeStLoc
[hiphop-php.git] / hphp / runtime / vm / jit / test / type.cpp
blobddbe7a5455fec875b969a9b67da4764fcaf165a1
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 <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 {
28 namespace {
30 typedef hphp_hash_set<Type> TypeSet;
32 TypeSet allTypes() {
33 TypeSet r;
34 # define IRT(name, ...) r.insert(Type::name);
35 IR_TYPES
36 # undef IRT
37 return r;
42 TEST(Type, Equality) {
43 EXPECT_NE(Type::Cls, Type::PtrToBoxedObj);
46 TEST(Type, Null) {
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) {
57 auto trueTypes = {
58 Type::Int, Type::BoxedCell, Type::StaticStr,
59 Type::Str, // TODO(#3390819): this should return false...
60 Type::Obj,
61 Type::Dbl,
62 Type::Arr,
63 Type::StaticArr,
64 Type::CountedArr,
65 Type::Res,
66 Type::Bool,
67 Type::Uninit,
68 Type::InitNull
70 for (auto t : trueTypes) {
71 EXPECT_TRUE(t.isKnownDataType())
72 << t.toString() << ".isKnownDataType()";
74 auto falseTypes = {
75 // Type::Null, // TODO(#3390819)
76 Type::Cell,
77 Type::Gen,
78 Type::Int | Type::Dbl
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"));
98 TEST(Type, Boxes) {
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());
115 TEST(Type, Ptr) {
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);
145 Type t = Type(rt);
146 EXPECT_TRUE(t.subtypeOf(Type::Str));
147 EXPECT_FALSE(t.subtypeOf(Type::Int));
149 rt = HPHP::JIT::RuntimeType(HphpArray::GetStaticEmptyArray());
150 t = Type(rt);
151 EXPECT_TRUE(t.subtypeOf(Type::Arr));
152 EXPECT_FALSE(t.subtypeOf(Type::Str));
154 rt = HPHP::JIT::RuntimeType(true);
155 t = Type(rt);
156 EXPECT_TRUE(t.subtypeOf(Type::Bool));
157 EXPECT_FALSE(t.subtypeOf(Type::Obj));
159 rt = HPHP::JIT::RuntimeType((int64_t) 1);
160 t = Type(rt);
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);
167 t = Type(rt);
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);
175 Type t1 = Type(rt1);
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";
188 types.erase(t);
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));
228 TEST(Type, Top) {
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));