Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include <iomanip>
6 :
7 : #include "src/compiler/types.h"
8 :
9 : #include "src/handles-inl.h"
10 : #include "src/objects-inl.h"
11 : #include "src/ostreams.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 : namespace compiler {
16 :
17 : // -----------------------------------------------------------------------------
18 : // Range-related helper functions.
19 :
20 3032330 : bool RangeType::Limits::IsEmpty() { return this->min > this->max; }
21 :
22 0 : RangeType::Limits RangeType::Limits::Intersect(Limits lhs, Limits rhs) {
23 : DisallowHeapAllocation no_allocation;
24 : Limits result(lhs);
25 1873455 : if (lhs.min < rhs.min) result.min = rhs.min;
26 1873455 : if (lhs.max > rhs.max) result.max = rhs.max;
27 0 : return result;
28 : }
29 :
30 0 : RangeType::Limits RangeType::Limits::Union(Limits lhs, Limits rhs) {
31 : DisallowHeapAllocation no_allocation;
32 3758895 : if (lhs.IsEmpty()) return rhs;
33 3758893 : if (rhs.IsEmpty()) return lhs;
34 : Limits result(lhs);
35 3122962 : if (lhs.min > rhs.min) result.min = rhs.min;
36 3122962 : if (lhs.max < rhs.max) result.max = rhs.max;
37 0 : return result;
38 : }
39 :
40 0 : bool Type::Overlap(const RangeType* lhs, const RangeType* rhs) {
41 : DisallowHeapAllocation no_allocation;
42 : return !RangeType::Limits::Intersect(RangeType::Limits(lhs),
43 : RangeType::Limits(rhs))
44 1237430 : .IsEmpty();
45 : }
46 :
47 42379900 : bool Type::Contains(const RangeType* lhs, const RangeType* rhs) {
48 : DisallowHeapAllocation no_allocation;
49 42379900 : return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max();
50 : }
51 :
52 : // -----------------------------------------------------------------------------
53 : // Min and Max computation.
54 :
55 13164483 : double Type::Min() const {
56 : DCHECK(this->Is(Number()));
57 : DCHECK(!this->Is(NaN()));
58 13826593 : if (this->IsBitset()) return BitsetType::Min(this->AsBitset());
59 12502373 : if (this->IsUnion()) {
60 49958 : double min = +V8_INFINITY;
61 129241 : for (int i = 1, n = AsUnion()->Length(); i < n; ++i) {
62 237833 : min = std::min(min, AsUnion()->Get(i).Min());
63 : }
64 99932 : Type bitset = AsUnion()->Get(0);
65 69155 : if (!bitset.Is(NaN())) min = std::min(min, bitset.Min());
66 49965 : return min;
67 : }
68 24861455 : if (this->IsRange()) return this->AsRange()->Min();
69 : DCHECK(this->IsOtherNumberConstant());
70 43375 : return this->AsOtherNumberConstant()->Value();
71 : }
72 :
73 13430385 : double Type::Max() const {
74 : DCHECK(this->Is(Number()));
75 : DCHECK(!this->Is(NaN()));
76 14276349 : if (this->IsBitset()) return BitsetType::Max(this->AsBitset());
77 12584421 : if (this->IsUnion()) {
78 45452 : double max = -V8_INFINITY;
79 120223 : for (int i = 1, n = this->AsUnion()->Length(); i < n; ++i) {
80 224313 : max = std::max(max, this->AsUnion()->Get(i).Max());
81 : }
82 90904 : Type bitset = this->AsUnion()->Get(0);
83 60115 : if (!bitset.Is(NaN())) max = std::max(max, bitset.Max());
84 45451 : return max;
85 : }
86 25039313 : if (this->IsRange()) return this->AsRange()->Max();
87 : DCHECK(this->IsOtherNumberConstant());
88 38625 : return this->AsOtherNumberConstant()->Value();
89 : }
90 :
91 : // -----------------------------------------------------------------------------
92 : // Glb and lub computation.
93 :
94 : // The largest bitset subsumed by this type.
95 130352561 : Type::bitset Type::BitsetGlb() const {
96 : DisallowHeapAllocation no_allocation;
97 : // Fast case.
98 130352561 : if (IsBitset()) {
99 38916978 : return AsBitset();
100 91435583 : } else if (IsUnion()) {
101 : SLOW_DCHECK(AsUnion()->Wellformed());
102 82880451 : return AsUnion()->Get(0).BitsetGlb() |
103 55253428 : AsUnion()->Get(1).BitsetGlb(); // Shortcut.
104 63809041 : } else if (IsRange()) {
105 39385435 : bitset glb = BitsetType::Glb(AsRange()->Min(), AsRange()->Max());
106 39385576 : return glb;
107 : } else {
108 : return BitsetType::kNone;
109 : }
110 : }
111 :
112 : // The smallest bitset subsuming this type, possibly not a proper one.
113 376084085 : Type::bitset Type::BitsetLub() const {
114 : DisallowHeapAllocation no_allocation;
115 620893890 : if (IsBitset()) return AsBitset();
116 131274280 : if (IsUnion()) {
117 : // Take the representation from the first element, which is always
118 : // a bitset.
119 22663120 : int bitset = AsUnion()->Get(0).BitsetLub();
120 42154890 : for (int i = 0, n = AsUnion()->Length(); i < n; ++i) {
121 : // Other elements only contribute their semantic part.
122 61650538 : bitset |= AsUnion()->Get(i).BitsetLub();
123 : }
124 11329621 : return bitset;
125 : }
126 159345234 : if (IsHeapConstant()) return AsHeapConstant()->Lub();
127 80540206 : if (IsOtherNumberConstant()) {
128 : return AsOtherNumberConstant()->Lub();
129 : }
130 137122260 : if (IsRange()) return AsRange()->Lub();
131 4152 : if (IsTuple()) return BitsetType::kOtherInternal;
132 0 : UNREACHABLE();
133 : }
134 :
135 : // TODO(neis): Once the broker mode kDisabled is gone, change the input type to
136 : // MapRef and get rid of the HeapObjectType class.
137 : template <typename MapRefLike>
138 18616781 : Type::bitset BitsetType::Lub(const MapRefLike& map) {
139 18616781 : switch (map.instance_type()) {
140 : case CONS_STRING_TYPE:
141 : case CONS_ONE_BYTE_STRING_TYPE:
142 : case THIN_STRING_TYPE:
143 : case THIN_ONE_BYTE_STRING_TYPE:
144 : case SLICED_STRING_TYPE:
145 : case SLICED_ONE_BYTE_STRING_TYPE:
146 : case EXTERNAL_STRING_TYPE:
147 : case EXTERNAL_ONE_BYTE_STRING_TYPE:
148 : case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
149 : case UNCACHED_EXTERNAL_STRING_TYPE:
150 : case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE:
151 : case UNCACHED_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
152 : case STRING_TYPE:
153 : case ONE_BYTE_STRING_TYPE:
154 : return kString;
155 : case EXTERNAL_INTERNALIZED_STRING_TYPE:
156 : case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
157 : case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
158 : case UNCACHED_EXTERNAL_INTERNALIZED_STRING_TYPE:
159 : case UNCACHED_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
160 : case UNCACHED_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
161 : case INTERNALIZED_STRING_TYPE:
162 : case ONE_BYTE_INTERNALIZED_STRING_TYPE:
163 4949362 : return kInternalizedString;
164 : case SYMBOL_TYPE:
165 759 : return kSymbol;
166 : case BIGINT_TYPE:
167 2383 : return kBigInt;
168 : case ODDBALL_TYPE:
169 10513652 : switch (map.oddball_type()) {
170 : case OddballType::kNone:
171 : break;
172 : case OddballType::kHole:
173 : return kHole;
174 : case OddballType::kBoolean:
175 6520440 : return kBoolean;
176 : case OddballType::kNull:
177 32161 : return kNull;
178 : case OddballType::kUndefined:
179 950716 : return kUndefined;
180 : case OddballType::kUninitialized:
181 : case OddballType::kOther:
182 : // TODO(neis): We should add a kOtherOddball type.
183 1446762 : return kOtherInternal;
184 : }
185 0 : UNREACHABLE();
186 : case HEAP_NUMBER_TYPE:
187 0 : return kNumber;
188 : case JS_OBJECT_TYPE:
189 : case JS_ARGUMENTS_TYPE:
190 : case JS_ERROR_TYPE:
191 : case JS_GLOBAL_OBJECT_TYPE:
192 : case JS_GLOBAL_PROXY_TYPE:
193 : case JS_API_OBJECT_TYPE:
194 : case JS_SPECIAL_API_OBJECT_TYPE:
195 1149084 : if (map.is_undetectable()) {
196 : // Currently we assume that every undetectable receiver is also
197 : // callable, which is what we need to support document.all. We
198 : // could add another Type bit to support other use cases in the
199 : // future if necessary.
200 : DCHECK(map.is_callable());
201 : return kOtherUndetectable;
202 : }
203 1149018 : if (map.is_callable()) {
204 : return kOtherCallable;
205 : }
206 1149018 : return kOtherObject;
207 : case JS_ARRAY_TYPE:
208 540939 : return kArray;
209 : case JS_VALUE_TYPE:
210 : case JS_MESSAGE_OBJECT_TYPE:
211 : case JS_DATE_TYPE:
212 : #ifdef V8_INTL_SUPPORT
213 : case JS_INTL_V8_BREAK_ITERATOR_TYPE:
214 : case JS_INTL_COLLATOR_TYPE:
215 : case JS_INTL_DATE_TIME_FORMAT_TYPE:
216 : case JS_INTL_LIST_FORMAT_TYPE:
217 : case JS_INTL_LOCALE_TYPE:
218 : case JS_INTL_NUMBER_FORMAT_TYPE:
219 : case JS_INTL_PLURAL_RULES_TYPE:
220 : case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
221 : case JS_INTL_SEGMENT_ITERATOR_TYPE:
222 : case JS_INTL_SEGMENTER_TYPE:
223 : #endif // V8_INTL_SUPPORT
224 : case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
225 : case JS_GENERATOR_OBJECT_TYPE:
226 : case JS_ASYNC_FUNCTION_OBJECT_TYPE:
227 : case JS_ASYNC_GENERATOR_OBJECT_TYPE:
228 : case JS_MODULE_NAMESPACE_TYPE:
229 : case JS_ARRAY_BUFFER_TYPE:
230 : case JS_ARRAY_ITERATOR_TYPE:
231 : case JS_REGEXP_TYPE: // TODO(rossberg): there should be a RegExp type.
232 : case JS_REGEXP_STRING_ITERATOR_TYPE:
233 : case JS_TYPED_ARRAY_TYPE:
234 : case JS_DATA_VIEW_TYPE:
235 : case JS_SET_TYPE:
236 : case JS_MAP_TYPE:
237 : case JS_SET_KEY_VALUE_ITERATOR_TYPE:
238 : case JS_SET_VALUE_ITERATOR_TYPE:
239 : case JS_MAP_KEY_ITERATOR_TYPE:
240 : case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
241 : case JS_MAP_VALUE_ITERATOR_TYPE:
242 : case JS_STRING_ITERATOR_TYPE:
243 : case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
244 : case JS_FINALIZATION_GROUP_TYPE:
245 : case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
246 : case JS_WEAK_MAP_TYPE:
247 : case JS_WEAK_REF_TYPE:
248 : case JS_WEAK_SET_TYPE:
249 : case JS_PROMISE_TYPE:
250 : case WASM_EXCEPTION_TYPE:
251 : case WASM_GLOBAL_TYPE:
252 : case WASM_INSTANCE_TYPE:
253 : case WASM_MEMORY_TYPE:
254 : case WASM_MODULE_TYPE:
255 : case WASM_TABLE_TYPE:
256 : case WEAK_CELL_TYPE:
257 : DCHECK(!map.is_callable());
258 : DCHECK(!map.is_undetectable());
259 5180 : return kOtherObject;
260 : case JS_BOUND_FUNCTION_TYPE:
261 : DCHECK(!map.is_undetectable());
262 163 : return kBoundFunction;
263 : case JS_FUNCTION_TYPE:
264 : DCHECK(!map.is_undetectable());
265 539733 : return kFunction;
266 : case JS_PROXY_TYPE:
267 : DCHECK(!map.is_undetectable());
268 372 : if (map.is_callable()) return kCallableProxy;
269 169 : return kOtherProxy;
270 : case MAP_TYPE:
271 : case ALLOCATION_SITE_TYPE:
272 : case ACCESSOR_INFO_TYPE:
273 : case SHARED_FUNCTION_INFO_TYPE:
274 : case FUNCTION_TEMPLATE_INFO_TYPE:
275 : case FUNCTION_TEMPLATE_RARE_DATA_TYPE:
276 : case ACCESSOR_PAIR_TYPE:
277 : case EMBEDDER_DATA_ARRAY_TYPE:
278 : case FIXED_ARRAY_TYPE:
279 : case HASH_TABLE_TYPE:
280 : case ORDERED_HASH_MAP_TYPE:
281 : case ORDERED_HASH_SET_TYPE:
282 : case ORDERED_NAME_DICTIONARY_TYPE:
283 : case NAME_DICTIONARY_TYPE:
284 : case GLOBAL_DICTIONARY_TYPE:
285 : case NUMBER_DICTIONARY_TYPE:
286 : case SIMPLE_NUMBER_DICTIONARY_TYPE:
287 : case STRING_TABLE_TYPE:
288 : case EPHEMERON_HASH_TABLE_TYPE:
289 : case WEAK_FIXED_ARRAY_TYPE:
290 : case WEAK_ARRAY_LIST_TYPE:
291 : case FIXED_DOUBLE_ARRAY_TYPE:
292 : case FEEDBACK_METADATA_TYPE:
293 : case BYTE_ARRAY_TYPE:
294 : case BYTECODE_ARRAY_TYPE:
295 : case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
296 : case ARRAY_BOILERPLATE_DESCRIPTION_TYPE:
297 : case DESCRIPTOR_ARRAY_TYPE:
298 : case TRANSITION_ARRAY_TYPE:
299 : case FEEDBACK_CELL_TYPE:
300 : case FEEDBACK_VECTOR_TYPE:
301 : case PROPERTY_ARRAY_TYPE:
302 : case FOREIGN_TYPE:
303 : case SCOPE_INFO_TYPE:
304 : case SCRIPT_CONTEXT_TABLE_TYPE:
305 : case AWAIT_CONTEXT_TYPE:
306 : case BLOCK_CONTEXT_TYPE:
307 : case CATCH_CONTEXT_TYPE:
308 : case DEBUG_EVALUATE_CONTEXT_TYPE:
309 : case EVAL_CONTEXT_TYPE:
310 : case FUNCTION_CONTEXT_TYPE:
311 : case MODULE_CONTEXT_TYPE:
312 : case NATIVE_CONTEXT_TYPE:
313 : case SCRIPT_CONTEXT_TYPE:
314 : case WITH_CONTEXT_TYPE:
315 : case SCRIPT_TYPE:
316 : case CODE_TYPE:
317 : case PROPERTY_CELL_TYPE:
318 : case MODULE_TYPE:
319 : case MODULE_INFO_ENTRY_TYPE:
320 : case CELL_TYPE:
321 : case PREPARSE_DATA_TYPE:
322 : case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE:
323 : case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE:
324 914535 : return kOtherInternal;
325 :
326 : // Remaining instance types are unsupported for now. If any of them do
327 : // require bit set types, they should get kOtherInternal.
328 : case MUTABLE_HEAP_NUMBER_TYPE:
329 : case FREE_SPACE_TYPE:
330 : #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
331 : case FIXED_##TYPE##_ARRAY_TYPE:
332 :
333 : TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE)
334 : #undef FIXED_TYPED_ARRAY_CASE
335 : case FILLER_TYPE:
336 : case ACCESS_CHECK_INFO_TYPE:
337 : case ASM_WASM_DATA_TYPE:
338 : case CALL_HANDLER_INFO_TYPE:
339 : case INTERCEPTOR_INFO_TYPE:
340 : case OBJECT_TEMPLATE_INFO_TYPE:
341 : case ALLOCATION_MEMENTO_TYPE:
342 : case ALIASED_ARGUMENTS_ENTRY_TYPE:
343 : case PROMISE_CAPABILITY_TYPE:
344 : case PROMISE_REACTION_TYPE:
345 : case CLASS_POSITIONS_TYPE:
346 : case DEBUG_INFO_TYPE:
347 : case STACK_FRAME_INFO_TYPE:
348 : case STACK_TRACE_FRAME_TYPE:
349 : case SMALL_ORDERED_HASH_MAP_TYPE:
350 : case SMALL_ORDERED_HASH_SET_TYPE:
351 : case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
352 : case PROTOTYPE_INFO_TYPE:
353 : case INTERPRETER_DATA_TYPE:
354 : case TUPLE2_TYPE:
355 : case TUPLE3_TYPE:
356 : case WASM_DEBUG_INFO_TYPE:
357 : case WASM_EXCEPTION_TAG_TYPE:
358 : case WASM_EXPORTED_FUNCTION_DATA_TYPE:
359 : case LOAD_HANDLER_TYPE:
360 : case STORE_HANDLER_TYPE:
361 : case ASYNC_GENERATOR_REQUEST_TYPE:
362 : case CODE_DATA_CONTAINER_TYPE:
363 : case CALLBACK_TASK_TYPE:
364 : case CALLABLE_TASK_TYPE:
365 : case PROMISE_FULFILL_REACTION_JOB_TASK_TYPE:
366 : case PROMISE_REJECT_REACTION_JOB_TASK_TYPE:
367 : case PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE:
368 : case FINALIZATION_GROUP_CLEANUP_JOB_TASK_TYPE:
369 0 : UNREACHABLE();
370 : }
371 0 : UNREACHABLE();
372 : }
373 :
374 : // Explicit instantiation.
375 : template Type::bitset BitsetType::Lub<MapRef>(const MapRef& map);
376 :
377 0 : Type::bitset BitsetType::Lub(double value) {
378 : DisallowHeapAllocation no_allocation;
379 0 : if (IsMinusZero(value)) return kMinusZero;
380 0 : if (std::isnan(value)) return kNaN;
381 0 : if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value);
382 : return kOtherNumber;
383 : }
384 :
385 : // Minimum values of plain numeric bitsets.
386 : const BitsetType::Boundary BitsetType::BoundariesArray[] = {
387 : {kOtherNumber, kPlainNumber, -V8_INFINITY},
388 : {kOtherSigned32, kNegative32, kMinInt},
389 : {kNegative31, kNegative31, -0x40000000},
390 : {kUnsigned30, kUnsigned30, 0},
391 : {kOtherUnsigned31, kUnsigned31, 0x40000000},
392 : {kOtherUnsigned32, kUnsigned32, 0x80000000},
393 : {kOtherNumber, kPlainNumber, static_cast<double>(kMaxUInt32) + 1}};
394 :
395 : const BitsetType::Boundary* BitsetType::Boundaries() { return BoundariesArray; }
396 :
397 : size_t BitsetType::BoundariesSize() {
398 : // Windows doesn't like arraysize here.
399 : // return arraysize(BoundariesArray);
400 : return 7;
401 : }
402 :
403 10935 : Type::bitset BitsetType::ExpandInternals(Type::bitset bits) {
404 : DCHECK_IMPLIES(bits & kOtherString, (bits & kString) == kString);
405 : DisallowHeapAllocation no_allocation;
406 10935 : if (!(bits & kPlainNumber)) return bits; // Shortcut.
407 : const Boundary* boundaries = Boundaries();
408 0 : for (size_t i = 0; i < BoundariesSize(); ++i) {
409 : DCHECK(BitsetType::Is(boundaries[i].internal, boundaries[i].external));
410 0 : if (bits & boundaries[i].internal) bits |= boundaries[i].external;
411 : }
412 : return bits;
413 : }
414 :
415 0 : Type::bitset BitsetType::Lub(double min, double max) {
416 : DisallowHeapAllocation no_allocation;
417 : int lub = kNone;
418 : const Boundary* mins = Boundaries();
419 :
420 84321710 : for (size_t i = 1; i < BoundariesSize(); ++i) {
421 96764291 : if (min < mins[i].min) {
422 56336340 : lub |= mins[i - 1].internal;
423 56336340 : if (max < mins[i].min) return lub;
424 : }
425 : }
426 8744280 : return lub | mins[BoundariesSize() - 1].internal;
427 : }
428 :
429 14994367 : Type::bitset BitsetType::NumberBits(bitset bits) { return bits & kPlainNumber; }
430 :
431 39384923 : Type::bitset BitsetType::Glb(double min, double max) {
432 : DisallowHeapAllocation no_allocation;
433 : int glb = kNone;
434 : const Boundary* mins = Boundaries();
435 :
436 : // If the range does not touch 0, the bound is empty.
437 39384923 : if (max < -1 || min > 0) return glb;
438 :
439 130738050 : for (size_t i = 1; i + 1 < BoundariesSize(); ++i) {
440 117003640 : if (min <= mins[i].min) {
441 89206036 : if (max + 1 < mins[i + 1].min) break;
442 74226156 : glb |= mins[i].external;
443 : }
444 : }
445 : // OtherNumber also contains float numbers, so it can never be
446 : // in the greatest lower bound.
447 28714290 : return glb & ~(kOtherNumber);
448 : }
449 :
450 6993358 : double BitsetType::Min(bitset bits) {
451 : DisallowHeapAllocation no_allocation;
452 : DCHECK(Is(bits, kNumber));
453 : DCHECK(!Is(bits, kNaN));
454 : const Boundary* mins = Boundaries();
455 6993358 : bool mz = bits & kMinusZero;
456 14860791 : for (size_t i = 0; i < BoundariesSize(); ++i) {
457 29680064 : if (Is(mins[i].internal, bits)) {
458 7026568 : return mz ? std::min(0.0, mins[i].min) : mins[i].min;
459 : }
460 : }
461 : DCHECK(mz);
462 : return 0;
463 : }
464 :
465 7176857 : double BitsetType::Max(bitset bits) {
466 : DisallowHeapAllocation no_allocation;
467 : DCHECK(Is(bits, kNumber));
468 : DCHECK(!Is(bits, kNaN));
469 : const Boundary* mins = Boundaries();
470 7176857 : bool mz = bits & kMinusZero;
471 7176857 : if (BitsetType::Is(mins[BoundariesSize() - 1].internal, bits)) {
472 : return +V8_INFINITY;
473 : }
474 10962321 : for (size_t i = BoundariesSize() - 1; i-- > 0;) {
475 21892642 : if (Is(mins[i].internal, bits)) {
476 5999785 : return mz ? std::max(0.0, mins[i + 1].min - 1) : mins[i + 1].min - 1;
477 : }
478 : }
479 : DCHECK(mz);
480 : return 0;
481 : }
482 :
483 : // static
484 1632369 : bool OtherNumberConstantType::IsOtherNumberConstant(double value) {
485 : // Not an integer, not NaN, and not -0.
486 4897107 : return !std::isnan(value) && !RangeType::IsInteger(value) &&
487 1632369 : !IsMinusZero(value);
488 : }
489 :
490 0 : HeapConstantType::HeapConstantType(BitsetType::bitset bitset,
491 : const HeapObjectRef& heap_ref)
492 18605802 : : TypeBase(kHeapConstant), bitset_(bitset), heap_ref_(heap_ref) {}
493 :
494 1993102 : Handle<HeapObject> HeapConstantType::Value() const {
495 22997484 : return heap_ref_.object();
496 : }
497 :
498 : // -----------------------------------------------------------------------------
499 : // Predicates.
500 :
501 14918036 : bool Type::SimplyEquals(Type that) const {
502 : DisallowHeapAllocation no_allocation;
503 14918036 : if (this->IsHeapConstant()) {
504 22517865 : return that.IsHeapConstant() &&
505 10502154 : this->AsHeapConstant()->Value().address() ==
506 22517869 : that.AsHeapConstant()->Value().address();
507 : }
508 2902327 : if (this->IsOtherNumberConstant()) {
509 3646364 : return that.IsOtherNumberConstant() &&
510 1080773 : this->AsOtherNumberConstant()->Value() ==
511 3646364 : that.AsOtherNumberConstant()->Value();
512 : }
513 336736 : if (this->IsRange()) {
514 673470 : if (that.IsHeapConstant() || that.IsOtherNumberConstant()) return false;
515 : }
516 0 : if (this->IsTuple()) {
517 0 : if (!that.IsTuple()) return false;
518 : const TupleType* this_tuple = this->AsTuple();
519 : const TupleType* that_tuple = that.AsTuple();
520 0 : if (this_tuple->Arity() != that_tuple->Arity()) {
521 : return false;
522 : }
523 0 : for (int i = 0, n = this_tuple->Arity(); i < n; ++i) {
524 0 : if (!this_tuple->Element(i).Equals(that_tuple->Element(i))) return false;
525 : }
526 : return true;
527 : }
528 0 : UNREACHABLE();
529 : }
530 :
531 : // Check if [this] <= [that].
532 400004409 : bool Type::SlowIs(Type that) const {
533 : DisallowHeapAllocation no_allocation;
534 :
535 : // Fast bitset cases
536 400004409 : if (that.IsBitset()) {
537 560509510 : return BitsetType::Is(this->BitsetLub(), that.AsBitset());
538 : }
539 :
540 119745036 : if (this->IsBitset()) {
541 68234836 : return BitsetType::Is(this->AsBitset(), that.BitsetGlb());
542 : }
543 :
544 : // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T)
545 85628033 : if (this->IsUnion()) {
546 18935532 : for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
547 36435442 : if (!this->AsUnion()->Get(i).Is(that)) return false;
548 : }
549 : return true;
550 : }
551 :
552 : // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn)
553 71863755 : if (that.IsUnion()) {
554 31183408 : for (int i = 0, n = that.AsUnion()->Length(); i < n; ++i) {
555 53874508 : if (this->Is(that.AsUnion()->Get(i))) return true;
556 23446354 : if (i > 1 && this->IsRange()) return false; // Shortcut.
557 : }
558 : return false;
559 : }
560 :
561 59610255 : if (that.IsRange()) {
562 64903305 : return (this->IsRange() && Contains(that.AsRange(), this->AsRange()));
563 : }
564 17987922 : if (this->IsRange()) return false;
565 :
566 14541810 : return this->SimplyEquals(that);
567 : }
568 :
569 : // Check if [this] and [that] overlap.
570 21169419 : bool Type::Maybe(Type that) const {
571 : DisallowHeapAllocation no_allocation;
572 :
573 21169419 : if (BitsetType::IsNone(this->BitsetLub() & that.BitsetLub())) return false;
574 :
575 : // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T)
576 9955128 : if (this->IsUnion()) {
577 777898 : for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
578 1397682 : if (this->AsUnion()->Get(i).Maybe(that)) return true;
579 : }
580 : return false;
581 : }
582 :
583 : // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn)
584 9521814 : if (that.IsUnion()) {
585 519610 : for (int i = 0, n = that.AsUnion()->Length(); i < n; ++i) {
586 846910 : if (this->Maybe(that.AsUnion()->Get(i))) return true;
587 : }
588 : return false;
589 : }
590 :
591 9297147 : if (this->IsBitset() && that.IsBitset()) return true;
592 :
593 4958190 : if (this->IsRange()) {
594 2379964 : if (that.IsRange()) {
595 1237430 : return Overlap(this->AsRange(), that.AsRange());
596 : }
597 1142534 : if (that.IsBitset()) {
598 : bitset number_bits = BitsetType::NumberBits(that.AsBitset());
599 806072 : if (number_bits == BitsetType::kNone) {
600 : return false;
601 : }
602 1612189 : double min = std::max(BitsetType::Min(number_bits), this->Min());
603 1612197 : double max = std::min(BitsetType::Max(number_bits), this->Max());
604 806083 : return min <= max;
605 : }
606 : }
607 2914688 : if (that.IsRange()) {
608 1097158 : return that.Maybe(*this); // This case is handled above.
609 : }
610 :
611 1817530 : if (this->IsBitset() || that.IsBitset()) return true;
612 :
613 374887 : return this->SimplyEquals(that);
614 : }
615 :
616 : // Return the range in [this], or [nullptr].
617 37748598 : Type Type::GetRange() const {
618 : DisallowHeapAllocation no_allocation;
619 37748598 : if (this->IsRange()) return *this;
620 57914178 : if (this->IsUnion() && this->AsUnion()->Get(1).IsRange()) {
621 9933518 : return this->AsUnion()->Get(1);
622 : }
623 21000836 : return nullptr;
624 : }
625 :
626 0 : bool UnionType::Wellformed() const {
627 : DisallowHeapAllocation no_allocation;
628 : // This checks the invariants of the union representation:
629 : // 1. There are at least two elements.
630 : // 2. The first element is a bitset, no other element is a bitset.
631 : // 3. At most one element is a range, and it must be the second one.
632 : // 4. No element is itself a union.
633 : // 5. No element (except the bitset) is a subtype of any other.
634 : // 6. If there is a range, then the bitset type does not contain
635 : // plain number bits.
636 : DCHECK_LE(2, this->Length()); // (1)
637 : DCHECK(this->Get(0).IsBitset()); // (2a)
638 :
639 : for (int i = 0; i < this->Length(); ++i) {
640 : if (i != 0) DCHECK(!this->Get(i).IsBitset()); // (2b)
641 : if (i != 1) DCHECK(!this->Get(i).IsRange()); // (3)
642 : DCHECK(!this->Get(i).IsUnion()); // (4)
643 : for (int j = 0; j < this->Length(); ++j) {
644 : if (i != j && i != 0) DCHECK(!this->Get(i).Is(this->Get(j))); // (5)
645 : }
646 : }
647 : DCHECK(!this->Get(1).IsRange() ||
648 : (BitsetType::NumberBits(this->Get(0).AsBitset()) ==
649 : BitsetType::kNone)); // (6)
650 0 : return true;
651 : }
652 :
653 : // -----------------------------------------------------------------------------
654 : // Union and intersection
655 :
656 26770748 : Type Type::Intersect(Type type1, Type type2, Zone* zone) {
657 : // Fast case: bit sets.
658 42731214 : if (type1.IsBitset() && type2.IsBitset()) {
659 15238063 : return NewBitset(type1.AsBitset() & type2.AsBitset());
660 : }
661 :
662 : // Fast case: top or bottom types.
663 23051623 : if (type1.IsNone() || type2.IsAny()) return type1; // Shortcut.
664 11294670 : if (type2.IsNone() || type1.IsAny()) return type2; // Shortcut.
665 :
666 : // Semi-fast case.
667 11200898 : if (type1.Is(type2)) return type1;
668 3510363 : if (type2.Is(type1)) return type2;
669 :
670 : // Slow case: create union.
671 :
672 : // Semantic subtyping check - this is needed for consistency with the
673 : // semi-fast case above.
674 1794924 : if (type1.Is(type2)) {
675 0 : type2 = Any();
676 1794943 : } else if (type2.Is(type1)) {
677 0 : type1 = Any();
678 : }
679 :
680 1794943 : bitset bits = type1.BitsetGlb() & type2.BitsetGlb();
681 2178433 : int size1 = type1.IsUnion() ? type1.AsUnion()->Length() : 1;
682 1891658 : int size2 = type2.IsUnion() ? type2.AsUnion()->Length() : 1;
683 : int size;
684 1794936 : if (base::bits::SignedAddOverflow32(size1, size2, &size)) return Any();
685 1794936 : if (base::bits::SignedAddOverflow32(size, 2, &size)) return Any();
686 1794936 : UnionType* result = UnionType::New(size, zone);
687 : size = 0;
688 :
689 : // Deal with bitsets.
690 2430748 : result->Set(size++, NewBitset(bits));
691 :
692 1794893 : RangeType::Limits lims = RangeType::Limits::Empty();
693 1794893 : size = IntersectAux(type1, type2, result, size, &lims, zone);
694 :
695 : // If the range is not empty, then insert it into the union and
696 : // remove the number bits from the bitset.
697 1794900 : if (!lims.IsEmpty()) {
698 635850 : size = UpdateRange(Type::Range(lims, zone), result, size, zone);
699 :
700 : // Remove the number bits.
701 : bitset number_bits = BitsetType::NumberBits(bits);
702 635855 : bits &= ~number_bits;
703 : result->Set(0, NewBitset(bits));
704 : }
705 1794890 : return NormalizeUnion(result, size, zone);
706 : }
707 :
708 635854 : int Type::UpdateRange(Type range, UnionType* result, int size, Zone* zone) {
709 635854 : if (size == 1) {
710 656332 : result->Set(size++, range);
711 : } else {
712 : // Make space for the range.
713 7426 : result->Set(size++, result->Get(1));
714 : result->Set(1, range);
715 : }
716 :
717 : // Remove any components that just got subsumed.
718 648906 : for (int i = 2; i < size;) {
719 26104 : if (result->Get(i).Is(range)) {
720 0 : result->Set(i, result->Get(--size));
721 : } else {
722 13052 : ++i;
723 : }
724 : }
725 635854 : return size;
726 : }
727 :
728 315804 : RangeType::Limits Type::ToLimits(bitset bits, Zone* zone) {
729 : bitset number_bits = BitsetType::NumberBits(bits);
730 :
731 315804 : if (number_bits == BitsetType::kNone) {
732 : return RangeType::Limits::Empty();
733 : }
734 :
735 : return RangeType::Limits(BitsetType::Min(number_bits),
736 315804 : BitsetType::Max(number_bits));
737 : }
738 :
739 315805 : RangeType::Limits Type::IntersectRangeAndBitset(Type range, Type bitset,
740 : Zone* zone) {
741 : RangeType::Limits range_lims(range.AsRange());
742 315805 : RangeType::Limits bitset_lims = ToLimits(bitset.AsBitset(), zone);
743 315804 : return RangeType::Limits::Intersect(range_lims, bitset_lims);
744 : }
745 :
746 3142014 : int Type::IntersectAux(Type lhs, Type rhs, UnionType* result, int size,
747 : RangeType::Limits* lims, Zone* zone) {
748 3142014 : if (lhs.IsUnion()) {
749 1335218 : for (int i = 0, n = lhs.AsUnion()->Length(); i < n; ++i) {
750 1903448 : size = IntersectAux(lhs.AsUnion()->Get(i), rhs, result, size, lims, zone);
751 : }
752 : return size;
753 : }
754 2758521 : if (rhs.IsUnion()) {
755 305353 : for (int i = 0, n = rhs.AsUnion()->Length(); i < n; ++i) {
756 411466 : size = IntersectAux(lhs, rhs.AsUnion()->Get(i), result, size, lims, zone);
757 : }
758 : return size;
759 : }
760 :
761 2658902 : if (BitsetType::IsNone(lhs.BitsetLub() & rhs.BitsetLub())) return size;
762 :
763 1029117 : if (lhs.IsRange()) {
764 794490 : if (rhs.IsBitset()) {
765 315807 : RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone);
766 :
767 315805 : if (!lim.IsEmpty()) {
768 315806 : *lims = RangeType::Limits::Union(lim, *lims);
769 : }
770 : return size;
771 : }
772 478683 : if (rhs.IsRange()) {
773 : RangeType::Limits lim = RangeType::Limits::Intersect(
774 : RangeType::Limits(lhs.AsRange()), RangeType::Limits(rhs.AsRange()));
775 320221 : if (!lim.IsEmpty()) {
776 320127 : *lims = RangeType::Limits::Union(lim, *lims);
777 : }
778 : }
779 478683 : return size;
780 : }
781 234627 : if (rhs.IsRange()) {
782 : // This case is handled symmetrically above.
783 189777 : return IntersectAux(rhs, lhs, result, size, lims, zone);
784 : }
785 44850 : if (lhs.IsBitset() || rhs.IsBitset()) {
786 43522 : return AddToUnion(lhs.IsBitset() ? rhs : lhs, result, size, zone);
787 : }
788 1328 : if (lhs.SimplyEquals(rhs)) {
789 320 : return AddToUnion(lhs, result, size, zone);
790 : }
791 : return size;
792 : }
793 :
794 : // Make sure that we produce a well-formed range and bitset:
795 : // If the range is non-empty, the number bits in the bitset should be
796 : // clear. Moreover, if we have a canonical range (such as Signed32),
797 : // we want to produce a bitset rather than a range.
798 13236636 : Type Type::NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone) {
799 : // Fast path: If the bitset does not mention numbers, we can just keep the
800 : // range.
801 13236636 : bitset number_bits = BitsetType::NumberBits(*bits);
802 13236636 : if (number_bits == 0) {
803 7135411 : return range;
804 : }
805 :
806 : // If the range is semantically contained within the bitset, return None and
807 : // leave the bitset untouched.
808 6101225 : bitset range_lub = range.BitsetLub();
809 12202450 : if (BitsetType::Is(range_lub, *bits)) {
810 : return None();
811 : }
812 :
813 : // Slow path: reconcile the bitset range and the range.
814 5209823 : double bitset_min = BitsetType::Min(number_bits);
815 5209823 : double bitset_max = BitsetType::Max(number_bits);
816 :
817 5209823 : double range_min = range.Min();
818 5209823 : double range_max = range.Max();
819 :
820 : // Remove the number bits from the bitset, they would just confuse us now.
821 : // NOTE: bits contains OtherNumber iff bits contains PlainNumber, in which
822 : // case we already returned after the subtype check above.
823 5209823 : *bits &= ~number_bits;
824 :
825 5209823 : if (range_min <= bitset_min && range_max >= bitset_max) {
826 : // Bitset is contained within the range, just return the range.
827 4795727 : return range;
828 : }
829 :
830 414096 : if (bitset_min < range_min) {
831 : range_min = bitset_min;
832 : }
833 414096 : if (bitset_max > range_max) {
834 : range_max = bitset_max;
835 : }
836 : return Type::Range(range_min, range_max, zone);
837 : }
838 :
839 8054355 : Type Type::NewConstant(double value, Zone* zone) {
840 8054355 : if (RangeType::IsInteger(value)) {
841 : return Range(value, value, zone);
842 1650412 : } else if (IsMinusZero(value)) {
843 : return Type::MinusZero();
844 1636968 : } else if (std::isnan(value)) {
845 : return Type::NaN();
846 : }
847 :
848 : DCHECK(OtherNumberConstantType::IsOtherNumberConstant(value));
849 : return OtherNumberConstant(value, zone);
850 : }
851 :
852 11392866 : Type Type::NewConstant(JSHeapBroker* broker, Handle<i::Object> value,
853 : Zone* zone) {
854 11392866 : ObjectRef ref(broker, value);
855 11392862 : if (ref.IsSmi()) {
856 626968 : return NewConstant(static_cast<double>(ref.AsSmi()), zone);
857 : }
858 10765893 : if (ref.IsHeapNumber()) {
859 2685642 : return NewConstant(ref.AsHeapNumber().value(), zone);
860 : }
861 8080250 : if (ref.IsString() && !ref.IsInternalizedString()) {
862 : return Type::String();
863 : }
864 16159830 : return HeapConstant(ref.AsHeapObject(), zone);
865 : }
866 :
867 47112763 : Type Type::Union(Type type1, Type type2, Zone* zone) {
868 : // Fast case: bit sets.
869 71920466 : if (type1.IsBitset() && type2.IsBitset()) {
870 14699733 : return NewBitset(type1.AsBitset() | type2.AsBitset());
871 : }
872 :
873 : // Fast case: top or bottom types.
874 64635135 : if (type1.IsAny() || type2.IsNone()) return type1;
875 30972899 : if (type2.IsAny() || type1.IsNone()) return type2;
876 :
877 : // Semi-fast case.
878 28024237 : if (type1.Is(type2)) return type2;
879 25976503 : if (type2.Is(type1)) return type1;
880 :
881 : // Slow case: create union.
882 26236461 : int size1 = type1.IsUnion() ? type1.AsUnion()->Length() : 1;
883 24605162 : int size2 = type2.IsUnion() ? type2.AsUnion()->Length() : 1;
884 : int size;
885 18675855 : if (base::bits::SignedAddOverflow32(size1, size2, &size)) return Any();
886 18675855 : if (base::bits::SignedAddOverflow32(size, 2, &size)) return Any();
887 18675855 : UnionType* result = UnionType::New(size, zone);
888 : size = 0;
889 :
890 : // Compute the new bitset.
891 18675837 : bitset new_bitset = type1.BitsetGlb() | type2.BitsetGlb();
892 :
893 : // Deal with ranges.
894 : Type range = None();
895 18675840 : Type range1 = type1.GetRange();
896 18675844 : Type range2 = type2.GetRange();
897 18675857 : if (range1 != nullptr && range2 != nullptr) {
898 : RangeType::Limits lims =
899 : RangeType::Limits::Union(RangeType::Limits(range1.AsRange()),
900 : RangeType::Limits(range2.AsRange()));
901 3122961 : Type union_range = Type::Range(lims, zone);
902 3122961 : range = NormalizeRangeAndBitset(union_range, &new_bitset, zone);
903 15552895 : } else if (range1 != nullptr) {
904 5630141 : range = NormalizeRangeAndBitset(range1, &new_bitset, zone);
905 9922754 : } else if (range2 != nullptr) {
906 4483541 : range = NormalizeRangeAndBitset(range2, &new_bitset, zone);
907 : }
908 18675856 : Type bits = NewBitset(new_bitset);
909 31021083 : result->Set(size++, bits);
910 18675856 : if (!range.IsNone()) result->Set(size++, range);
911 :
912 18675856 : size = AddToUnion(type1, result, size, zone);
913 18675840 : size = AddToUnion(type2, result, size, zone);
914 18675848 : return NormalizeUnion(result, size, zone);
915 : }
916 :
917 : // Add [type] to [result] unless [type] is bitset, range, or already subsumed.
918 : // Return new size of [result].
919 75073889 : int Type::AddToUnion(Type type, UnionType* result, int size, Zone* zone) {
920 126830730 : if (type.IsBitset() || type.IsRange()) return size;
921 35397288 : if (type.IsUnion()) {
922 51168369 : for (int i = 0, n = type.AsUnion()->Length(); i < n; ++i) {
923 75356932 : size = AddToUnion(type.AsUnion()->Get(i), result, size, zone);
924 : }
925 : return size;
926 : }
927 41126954 : for (int i = 0; i < size; ++i) {
928 105842760 : if (type.Is(result->Get(i))) return size;
929 : }
930 20225915 : result->Set(size++, type);
931 20225915 : return size;
932 : }
933 :
934 20470733 : Type Type::NormalizeUnion(UnionType* unioned, int size, Zone* zone) {
935 : DCHECK_LE(1, size);
936 : DCHECK(unioned->Get(0).IsBitset());
937 : // If the union has just one element, return it.
938 20470733 : if (size == 1) {
939 20470733 : return unioned->Get(0);
940 : }
941 : bitset bits = unioned->Get(0).AsBitset();
942 : // If the union only consists of a range, we can get rid of the union.
943 18798492 : if (size == 2 && bits == BitsetType::kNone) {
944 1847395 : if (unioned->Get(1).IsRange()) {
945 : return Type::Range(unioned->Get(1).AsRange()->Min(),
946 1846162 : unioned->Get(1).AsRange()->Max(), zone);
947 : }
948 : }
949 : unioned->Shrink(size);
950 : SLOW_DCHECK(unioned->Wellformed());
951 16952330 : return Type(unioned);
952 : }
953 :
954 79006 : int Type::NumConstants() const {
955 : DisallowHeapAllocation no_allocation;
956 156596 : if (this->IsHeapConstant() || this->IsOtherNumberConstant()) {
957 : return 1;
958 76678 : } else if (this->IsUnion()) {
959 : int result = 0;
960 18010 : for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
961 25132 : if (this->AsUnion()->Get(i).IsHeapConstant()) ++result;
962 : }
963 : return result;
964 : } else {
965 : return 0;
966 : }
967 : }
968 :
969 : // -----------------------------------------------------------------------------
970 : // Printing.
971 :
972 140027 : const char* BitsetType::Name(bitset bits) {
973 140027 : switch (bits) {
974 : #define RETURN_NAMED_TYPE(type, value) \
975 : case k##type: \
976 : return #type;
977 0 : PROPER_BITSET_TYPE_LIST(RETURN_NAMED_TYPE)
978 0 : INTERNAL_BITSET_TYPE_LIST(RETURN_NAMED_TYPE)
979 : #undef RETURN_NAMED_TYPE
980 :
981 : default:
982 0 : return nullptr;
983 : }
984 : }
985 :
986 140027 : void BitsetType::Print(std::ostream& os, // NOLINT
987 : bitset bits) {
988 : DisallowHeapAllocation no_allocation;
989 140027 : const char* name = Name(bits);
990 140027 : if (name != nullptr) {
991 140027 : os << name;
992 140027 : return;
993 : }
994 :
995 : // clang-format off
996 : static const bitset named_bitsets[] = {
997 : #define BITSET_CONSTANT(type, value) k##type,
998 : INTERNAL_BITSET_TYPE_LIST(BITSET_CONSTANT)
999 : PROPER_BITSET_TYPE_LIST(BITSET_CONSTANT)
1000 : #undef BITSET_CONSTANT
1001 : };
1002 : // clang-format on
1003 :
1004 : bool is_first = true;
1005 0 : os << "(";
1006 0 : for (int i(arraysize(named_bitsets) - 1); bits != 0 && i >= 0; --i) {
1007 0 : bitset subset = named_bitsets[i];
1008 0 : if ((bits & subset) == subset) {
1009 0 : if (!is_first) os << " | ";
1010 : is_first = false;
1011 0 : os << Name(subset);
1012 0 : bits -= subset;
1013 : }
1014 : }
1015 : DCHECK_EQ(0, bits);
1016 0 : os << ")";
1017 : }
1018 :
1019 140151 : void Type::PrintTo(std::ostream& os) const {
1020 : DisallowHeapAllocation no_allocation;
1021 140151 : if (this->IsBitset()) {
1022 140027 : BitsetType::Print(os, this->AsBitset());
1023 124 : } else if (this->IsHeapConstant()) {
1024 76 : os << "HeapConstant(" << Brief(*this->AsHeapConstant()->Value()) << ")";
1025 48 : } else if (this->IsOtherNumberConstant()) {
1026 0 : os << "OtherNumberConstant(" << this->AsOtherNumberConstant()->Value()
1027 0 : << ")";
1028 48 : } else if (this->IsRange()) {
1029 29 : std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed);
1030 29 : std::streamsize saved_precision = os.precision(0);
1031 58 : os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max()
1032 29 : << ")";
1033 29 : os.flags(saved_flags);
1034 29 : os.precision(saved_precision);
1035 19 : } else if (this->IsUnion()) {
1036 19 : os << "(";
1037 57 : for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
1038 76 : Type type_i = this->AsUnion()->Get(i);
1039 38 : if (i > 0) os << " | ";
1040 38 : os << type_i;
1041 : }
1042 19 : os << ")";
1043 0 : } else if (this->IsTuple()) {
1044 0 : os << "<";
1045 0 : for (int i = 0, n = this->AsTuple()->Arity(); i < n; ++i) {
1046 0 : Type type_i = this->AsTuple()->Element(i);
1047 0 : if (i > 0) os << ", ";
1048 0 : os << type_i;
1049 : }
1050 0 : os << ">";
1051 : } else {
1052 0 : UNREACHABLE();
1053 : }
1054 140151 : }
1055 :
1056 : #ifdef DEBUG
1057 : void Type::Print() const {
1058 : StdoutStream os;
1059 : PrintTo(os);
1060 : os << std::endl;
1061 : }
1062 : void BitsetType::Print(bitset bits) {
1063 : StdoutStream os;
1064 : Print(os, bits);
1065 : os << std::endl;
1066 : }
1067 : #endif
1068 :
1069 6759531 : BitsetType::bitset BitsetType::SignedSmall() {
1070 6759531 : return SmiValuesAre31Bits() ? kSigned31 : kSigned32;
1071 : }
1072 :
1073 232619 : BitsetType::bitset BitsetType::UnsignedSmall() {
1074 232619 : return SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31;
1075 : }
1076 :
1077 : // static
1078 1384 : Type Type::Tuple(Type first, Type second, Type third, Zone* zone) {
1079 1384 : TupleType* tuple = TupleType::New(3, zone);
1080 : tuple->InitElement(0, first);
1081 : tuple->InitElement(1, second);
1082 : tuple->InitElement(2, third);
1083 1384 : return FromTypeBase(tuple);
1084 : }
1085 :
1086 : // static
1087 0 : Type Type::OtherNumberConstant(double value, Zone* zone) {
1088 1632369 : return FromTypeBase(OtherNumberConstantType::New(value, zone));
1089 : }
1090 :
1091 : // static
1092 10524897 : Type Type::HeapConstant(JSHeapBroker* broker, Handle<i::Object> value,
1093 : Zone* zone) {
1094 : return FromTypeBase(
1095 21049831 : HeapConstantType::New(HeapObjectRef(broker, value), zone));
1096 : }
1097 :
1098 : // static
1099 1005 : Type Type::HeapConstant(const HeapObjectRef& value, Zone* zone) {
1100 8081927 : return HeapConstantType::New(value, zone);
1101 : }
1102 :
1103 : // static
1104 8764415 : Type Type::Range(double min, double max, Zone* zone) {
1105 8764401 : return FromTypeBase(RangeType::New(min, max, zone));
1106 : }
1107 :
1108 : // static
1109 0 : Type Type::Range(RangeType::Limits lims, Zone* zone) {
1110 3758827 : return FromTypeBase(RangeType::New(lims, zone));
1111 : }
1112 :
1113 : // static
1114 0 : Type Type::Union(int length, Zone* zone) {
1115 0 : return FromTypeBase(UnionType::New(length, zone));
1116 : }
1117 :
1118 2340071 : const HeapConstantType* Type::AsHeapConstant() const {
1119 : DCHECK(IsKind(TypeBase::kHeapConstant));
1120 2340071 : return static_cast<const HeapConstantType*>(ToTypeBase());
1121 : }
1122 :
1123 57 : const OtherNumberConstantType* Type::AsOtherNumberConstant() const {
1124 : DCHECK(IsKind(TypeBase::kOtherNumberConstant));
1125 57 : return static_cast<const OtherNumberConstantType*>(ToTypeBase());
1126 : }
1127 :
1128 45247 : const RangeType* Type::AsRange() const {
1129 : DCHECK(IsKind(TypeBase::kRange));
1130 45247 : return static_cast<const RangeType*>(ToTypeBase());
1131 : }
1132 :
1133 8304 : const TupleType* Type::AsTuple() const {
1134 : DCHECK(IsKind(TypeBase::kTuple));
1135 8304 : return static_cast<const TupleType*>(ToTypeBase());
1136 : }
1137 :
1138 5444 : const UnionType* Type::AsUnion() const {
1139 : DCHECK(IsKind(TypeBase::kUnion));
1140 5444 : return static_cast<const UnionType*>(ToTypeBase());
1141 : }
1142 :
1143 139989 : std::ostream& operator<<(std::ostream& os, Type type) {
1144 139989 : type.PrintTo(os);
1145 139989 : return os;
1146 : }
1147 :
1148 : } // namespace compiler
1149 : } // namespace internal
1150 178779 : } // namespace v8
|