Delete StructArray and Shape
[hiphop-php.git] / hphp / runtime / vm / jit / type-constraint.cpp
blob5504231fe28dc6537b5ad6f45a0ee2783d181b1d
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2016 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/jit/type-constraint.h"
19 #include "hphp/runtime/base/datatype.h"
21 #include <folly/Format.h>
23 namespace HPHP { namespace jit {
25 TRACE_SET_MOD(hhir);
27 ///////////////////////////////////////////////////////////////////////////////
29 std::string TypeConstraint::toString() const {
30 std::string ret = "<" + typeCategoryName(category);
32 if (category == DataTypeSpecialized) {
33 if (wantArrayKind()) ret += ",ArrayKind";
34 if (wantClass()) {
35 folly::toAppend("Cls:", desiredClass()->name()->data(), &ret);
39 if (weak) ret += ",weak";
41 return ret + '>';
44 ///////////////////////////////////////////////////////////////////////////////
46 bool typeFitsConstraint(Type t, TypeConstraint tc) {
47 switch (tc.category) {
48 case DataTypeGeneric:
49 return true;
51 case DataTypeCountness:
52 // Consumers using this constraint expect the type to be relaxed to
53 // Uncounted or left alone, so something like Arr|Obj isn't specific
54 // enough.
55 return !t.maybe(TCounted) ||
56 t.subtypeOfAny(TStr, TArr, TObj,
57 TRes, TBoxedCell);
59 case DataTypeCountnessInit:
60 return typeFitsConstraint(t, DataTypeCountness) &&
61 (t <= TUninit || !t.maybe(TUninit));
63 case DataTypeSpecific:
64 return t.isKnownDataType();
66 case DataTypeSpecialized:
67 // Type::isSpecialized() returns true for types like {Arr<Packed>|Int}
68 // and Arr has non-specialized subtypes, so we require that t is
69 // specialized, a strict subtype of Obj or Arr, and that it fits the
70 // specific requirements of tc.
72 assertx(tc.wantClass() ^ tc.wantArrayKind());
74 if (t < TObj && t.clsSpec()) {
75 return tc.wantClass() &&
76 t.clsSpec().cls()->classof(tc.desiredClass());
78 if (t < TArr && t.arrSpec()) {
79 auto arrSpec = t.arrSpec();
80 if (tc.wantArrayKind() && !arrSpec.kind()) return false;
81 return true;
84 return false;
87 not_reached();
90 static void incCategory(DataTypeCategory& c) {
91 always_assert(c != DataTypeSpecialized);
92 c = static_cast<DataTypeCategory>(static_cast<uint8_t>(c) + 1);
95 TypeConstraint relaxConstraint(const TypeConstraint origTc,
96 const Type knownType, const Type toRelax) {
97 ITRACE(4, "relaxConstraint({}, knownType = {}, toRelax = {})\n",
98 origTc, knownType, toRelax);
99 Trace::Indent _i;
101 auto const dstType = knownType & toRelax;
102 always_assert_flog(typeFitsConstraint(dstType, origTc),
103 "refine({}, {}) doesn't fit {}",
104 knownType, toRelax, origTc);
106 // Preserve origTc's weak property.
107 TypeConstraint newTc{DataTypeGeneric};
108 newTc.weak = origTc.weak;
110 while (true) {
111 if (newTc.isSpecialized()) {
112 // We need to ask for the right kind of specialization, so grab it from
113 // origTc.
114 if (origTc.wantArrayKind()) newTc.setWantArrayKind();
115 if (origTc.wantClass()) newTc.setDesiredClass(origTc.desiredClass());
118 auto const relaxed = relaxType(toRelax, newTc.category);
119 auto const newDstType = relaxed & knownType;
120 if (typeFitsConstraint(newDstType, origTc)) break;
122 ITRACE(5, "newDstType = {}, newTc = {}; incrementing constraint\n",
123 newDstType, newTc);
124 incCategory(newTc.category);
127 ITRACE(4, "Returning {}\n", newTc);
128 // newTc shouldn't be any more specific than origTc.
129 always_assert(newTc.category <= origTc.category);
130 return newTc;
133 TypeConstraint applyConstraint(TypeConstraint tc, const TypeConstraint newTc) {
134 tc.category = std::max(newTc.category, tc.category);
136 if (newTc.wantArrayKind()) tc.setWantArrayKind();
138 if (newTc.wantClass()) {
139 if (tc.wantClass()) {
140 // It only makes sense to constrain tc with a class that's related to its
141 // existing class, and we want to preserve the more derived of the two.
142 auto cls1 = tc.desiredClass();
143 auto cls2 = newTc.desiredClass();
144 tc.setDesiredClass(cls1->classof(cls2) ? cls1 : cls2);
145 } else {
146 tc.setDesiredClass(newTc.desiredClass());
150 return tc;
153 ///////////////////////////////////////////////////////////////////////////////