Flutter Engine
The Flutter Engine
compile_type.h
Go to the documentation of this file.
1// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_BACKEND_COMPILE_TYPE_H_
6#define RUNTIME_VM_COMPILER_BACKEND_COMPILE_TYPE_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
12#include "vm/allocation.h"
13#include "vm/class_id.h"
16
17namespace dart {
18
19class AbstractType;
20class BaseTextBuffer;
21class Definition;
22class FlowGraphDeserializer;
23class FlowGraphSerializer;
24class JSONWriter;
25
26template <typename T>
27class GrowableArray;
28
29// CompileType describes type of a value produced by a definition.
30//
31// It captures the following properties:
32// - whether the value can potentially be null or if it is definitely not
33// null;
34// - whether the value can potentially be sentinel or if it is definitely
35// not sentinel;
36// - concrete class id of the value or kDynamicCid if unknown statically;
37// - abstract super type of the value, where the concrete type of the value
38// in runtime is guaranteed to be sub type of this type.
39//
40// Values of CompileType form a lattice with a None type as a bottom and a
41// nullable Dynamic type as a top element. Method Union provides a join
42// operation for the lattice.
43class CompileType : public ZoneAllocated {
44 public:
45 static constexpr bool kCanBeNull = true;
46 static constexpr bool kCannotBeNull = false;
47
48 static constexpr bool kCanBeSentinel = true;
49 static constexpr bool kCannotBeSentinel = false;
50
51 CompileType(bool can_be_null,
52 bool can_be_sentinel,
53 intptr_t cid,
54 const AbstractType* type)
55 : can_be_null_(can_be_null),
56 can_be_sentinel_(can_be_sentinel),
57 cid_(cid),
58 type_(type) {}
59
61 : ZoneAllocated(),
62 can_be_null_(other.can_be_null_),
63 can_be_sentinel_(other.can_be_sentinel_),
64 cid_(other.cid_),
65 type_(other.type_) {}
66
68 // This intentionally does not change the owner of this type.
69 can_be_null_ = other.can_be_null_;
70 can_be_sentinel_ = other.can_be_sentinel_;
71 cid_ = other.cid_;
72 type_ = other.type_;
73 return *this;
74 }
75
76 bool is_nullable() const { return can_be_null_; }
77
78 // Return true if value of this type can be Object::sentinel().
79 // Such values cannot be unboxed.
80 bool can_be_sentinel() const { return can_be_sentinel_; }
81
82 // Return type such that concrete value's type in runtime is guaranteed to
83 // be subtype of it.
85
86 // Return class id such that it is either kDynamicCid or in runtime
87 // value is guaranteed to have an equal class id.
88 intptr_t ToCid();
89
90 // Return class id such that it is either kDynamicCid or in runtime
91 // value is guaranteed to be either null or have an equal class id.
92 intptr_t ToNullableCid();
93
94 // Return true if the value is guaranteed to be not-null or is known to be
95 // always null.
97
98 // Return true if the value is known to be always null.
99 bool IsNull();
100
101 // Return true if this type is a subtype of the given type.
102 bool IsSubtypeOf(const AbstractType& other);
103
104 // Return true if value of this type is assignable to a location of the
105 // given type.
106 bool IsAssignableTo(const AbstractType& other);
107
108 // Return true if value of this type always passes 'is' test
109 // against given type.
110 bool IsInstanceOf(const AbstractType& other);
111
112 // Return the non-nullable version of this type.
114 if (IsNull()) {
115 // Represent a non-nullable null type (typically arising for
116 // unreachable values) as None.
117 return None();
118 }
119
120 return CompileType(kCannotBeNull, can_be_sentinel_, cid_, type_);
121 }
122
123 // Return the non-sentinel version of this type.
125 return CompileType(can_be_null_, kCannotBeSentinel, cid_, type_);
126 }
127
128 // Create a new CompileType representing given abstract type.
129 // By default nullability of values is determined by type.
130 // CompileType can be further constrained to non-nullable values by
131 // passing kCannotBeNull as |can_be_null| parameter.
133 bool can_be_null,
134 bool can_be_sentinel);
135
136 // Create a new CompileType representing a value with the given class id.
137 // Resulting CompileType can be null only if cid is kDynamicCid or kNullCid.
138 // Resulting CompileType can be sentinel only if cid is kDynamicCid or
139 // kSentinelCid.
140 static CompileType FromCid(intptr_t cid);
141
142 // Create a new CompileType representing an unboxed value
143 // with given unboxed representation.
144 // Resulting CompileType cannot be null and cannot be sentinel.
146
147 // Create a new CompileType representing an value where the only information
148 // known is its representation.
149 // The resulting CompileType can only be null if the representation is
150 // tagged and cannot be sentinel.
152
153 // Create None CompileType. It is the bottom of the lattice and is used to
154 // represent type of the phi that was not yet inferred.
155 static CompileType None() {
157 }
158
159 // Create Dynamic CompileType. It is the top of the lattice and is used to
160 // represent unknown type.
161 static CompileType Dynamic();
162
164
165 static CompileType Null();
166
167 // Create non-nullable Bool type.
168 static CompileType Bool();
169
170 // Create non-nullable Int type.
171 static CompileType Int();
172
173 // Create non-nullable 32-bit Int type (arch dependent).
174 static CompileType Int32();
175
176 // Create nullable Int type.
177 static CompileType NullableInt();
178
179 // Create non-nullable Smi type.
180 static CompileType Smi();
181
182 // Create nullable Smi type.
184 return CompileType(kCanBeNull, kCannotBeSentinel, kSmiCid, nullptr);
185 }
186
187 // Create nullable Mint type.
189 return CompileType(kCanBeNull, kCannotBeSentinel, kMintCid, nullptr);
190 }
191
192 // Create non-nullable Double type.
193 static CompileType Double();
194
195 // Create nullable Double type.
197
198 // Create non-nullable String type.
199 static CompileType String();
200
201 // Create non-nullable Object type.
202 static CompileType Object();
203
204 // Perform a join operation over the type lattice.
205 void Union(CompileType* other);
206
207 // Refine old type with newly inferred type (it could be more or less
208 // specific, or even unrelated to an old type in case of unreachable code).
209 // May return 'old_type', 'new_type' or create a new CompileType instance.
211 CompileType* new_type);
212
213 // Return true if this and other types are the same.
214 bool IsEqualTo(CompileType* other) {
215 return (can_be_null_ == other->can_be_null_) &&
216 (can_be_sentinel_ == other->can_be_sentinel_) &&
217 (ToNullableCid() == other->ToNullableCid()) &&
219 }
220
221 bool IsNone() const { return (cid_ == kIllegalCid) && (type_ == nullptr); }
222
223 // Return true if value of this type is a non-nullable Object.
224 bool IsObject() const;
225
226 // Return true if value of this type is a non-nullable int.
227 bool IsInt() { return !is_nullable() && IsNullableInt(); }
228
229 // Return true if value of this type is a non-nullable double.
230 bool IsDouble() { return !is_nullable() && IsNullableDouble(); }
231
232 // Return true if value of this type is a non-nullable double.
233 bool IsBool() { return !is_nullable() && IsNullableBool(); }
234
235 // Return true if value of this type is either int or null.
237 if (cid_ == kSmiCid || cid_ == kMintCid) {
238 return true;
239 }
240 if (cid_ == kIllegalCid || cid_ == kDynamicCid) {
241 return type_ != nullptr && compiler::IsSubtypeOfInt(*type_);
242 }
243 return false;
244 }
245
246 // Returns true if value of this type is either Smi or null.
248 if (cid_ == kSmiCid) {
249 return true;
250 }
251 if (cid_ == kIllegalCid || cid_ == kDynamicCid) {
252 return type_ != nullptr && compiler::IsSmiType(*type_);
253 }
254 return false;
255 }
256
257 // Return true if value of this type is either double or null.
259 if (cid_ == kDoubleCid) {
260 return true;
261 }
262 if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
263 return type_ != nullptr && compiler::IsDoubleType(*type_);
264 }
265 return false;
266 }
267
268 // Return true if value of this type is either double or null.
270 if (cid_ == kBoolCid) {
271 return true;
272 }
273 if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
274 return type_ != nullptr && compiler::IsBoolType(*type_);
275 }
276 return false;
277 }
278
279 // Returns true if a value of this CompileType can contain a Smi.
280 // Note that this is not the same as calling
281 // CompileType::Smi().IsAssignableTo(this) - because this compile type
282 // can be uninstantiated.
283 bool CanBeSmi();
284
285 // Returns true if a value of this CompileType can contain a Future
286 // instance.
287 bool CanBeFuture();
288
289 bool Specialize(GrowableArray<intptr_t>* class_ids);
290
291 void PrintTo(BaseTextBuffer* f) const;
292 void PrintTo(JSONWriter* writer) const;
293
294 const char* ToCString() const;
295
296 // CompileType object might be unowned or owned by a definition.
297 // Owned CompileType objects can change during type propagation when
298 // [RecomputeType] is called on the owner. We keep track of which
299 // definition owns [CompileType] to prevent situations where
300 // owned [CompileType] is cached as a reaching type in a [Value] which
301 // is no longer connected to the original owning definition.
302 // See [Value::SetReachingType].
303 void set_owner(Definition* owner) { owner_ = owner; }
304 Definition* owner() const { return owner_; }
305
306 void Write(FlowGraphSerializer* s) const;
308
309 private:
310 bool can_be_null_;
311 bool can_be_sentinel_;
312 classid_t cid_;
313 const AbstractType* type_;
314 Definition* owner_ = nullptr;
315};
316
317} // namespace dart
318
319#endif // RUNTIME_VM_COMPILER_BACKEND_COMPILE_TYPE_H_
GLenum type
static CompileType * ComputeRefinedType(CompileType *old_type, CompileType *new_type)
void Union(CompileType *other)
Definition * owner() const
Definition: compile_type.h:304
bool IsAssignableTo(const AbstractType &other)
static constexpr bool kCanBeSentinel
Definition: compile_type.h:48
CompileType CopyNonNullable()
Definition: compile_type.h:113
static CompileType FromCid(intptr_t cid)
static constexpr bool kCannotBeSentinel
Definition: compile_type.h:49
bool can_be_sentinel() const
Definition: compile_type.h:80
bool IsInstanceOf(const AbstractType &other)
static CompileType NullableMint()
Definition: compile_type.h:188
bool IsObject() const
CompileType(bool can_be_null, bool can_be_sentinel, intptr_t cid, const AbstractType *type)
Definition: compile_type.h:51
static CompileType DynamicOrSentinel()
static constexpr bool kCannotBeNull
Definition: compile_type.h:46
static CompileType Int()
static constexpr bool kCanBeNull
Definition: compile_type.h:45
bool IsSubtypeOf(const AbstractType &other)
static CompileType Dynamic()
bool Specialize(GrowableArray< intptr_t > *class_ids)
static CompileType String()
bool IsEqualTo(CompileType *other)
Definition: compile_type.h:214
CompileType(const CompileType &other)
Definition: compile_type.h:60
CompileType & operator=(const CompileType &other)
Definition: compile_type.h:67
bool IsNone() const
Definition: compile_type.h:221
static CompileType Null()
intptr_t ToNullableCid()
static CompileType NullableSmi()
Definition: compile_type.h:183
static CompileType NullableDouble()
bool is_nullable() const
Definition: compile_type.h:76
void set_owner(Definition *owner)
Definition: compile_type.h:303
static CompileType Object()
static CompileType FromRepresentation(Representation rep)
static CompileType Smi()
static CompileType Int32()
CompileType CopyNonSentinel()
Definition: compile_type.h:124
static CompileType FromAbstractType(const AbstractType &type, bool can_be_null, bool can_be_sentinel)
static CompileType NullableInt()
const char * ToCString() const
void PrintTo(BaseTextBuffer *f) const
static CompileType Bool()
void Write(FlowGraphSerializer *s) const
static CompileType None()
Definition: compile_type.h:155
const AbstractType * ToAbstractType()
static CompileType FromUnboxedRepresentation(Representation rep)
static CompileType Double()
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
struct MyStruct s
bool IsBoolType(const AbstractType &type)
Definition: runtime_api.cc:75
bool IsDoubleType(const AbstractType &type)
Definition: runtime_api.cc:71
bool IsEqualType(const AbstractType &a, const AbstractType &b)
Definition: runtime_api.cc:67
bool IsSubtypeOfInt(const AbstractType &type)
Definition: runtime_api.cc:79
bool IsSmiType(const AbstractType &type)
Definition: runtime_api.cc:84
Definition: dart_vm.cc:33
int32_t classid_t
Definition: globals.h:524
@ kIllegalCid
Definition: class_id.h:214
@ kDynamicCid
Definition: class_id.h:253
Representation
Definition: locations.h:66
const intptr_t cid