OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_TYPES_H_ | 5 #ifndef V8_TYPES_H_ |
6 #define V8_TYPES_H_ | 6 #define V8_TYPES_H_ |
7 | 7 |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/handles.h" | 9 #include "src/handles.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 #define PROPER_BITSET_TYPE_LIST(V) \ | 252 #define PROPER_BITSET_TYPE_LIST(V) \ |
253 REPRESENTATION_BITSET_TYPE_LIST(V) \ | 253 REPRESENTATION_BITSET_TYPE_LIST(V) \ |
254 SEMANTIC_BITSET_TYPE_LIST(V) | 254 SEMANTIC_BITSET_TYPE_LIST(V) |
255 | 255 |
256 #define BITSET_TYPE_LIST(V) \ | 256 #define BITSET_TYPE_LIST(V) \ |
257 MASK_BITSET_TYPE_LIST(V) \ | 257 MASK_BITSET_TYPE_LIST(V) \ |
258 REPRESENTATION_BITSET_TYPE_LIST(V) \ | 258 REPRESENTATION_BITSET_TYPE_LIST(V) \ |
259 INTERNAL_BITSET_TYPE_LIST(V) \ | 259 INTERNAL_BITSET_TYPE_LIST(V) \ |
260 SEMANTIC_BITSET_TYPE_LIST(V) | 260 SEMANTIC_BITSET_TYPE_LIST(V) |
261 | 261 |
| 262 class Type; |
262 | 263 |
263 // ----------------------------------------------------------------------------- | 264 // ----------------------------------------------------------------------------- |
264 // The abstract Type class, parameterized over the low-level representation. | 265 // Bitset types (internal). |
265 | 266 |
266 // struct Config { | 267 class BitsetType { |
267 // typedef TypeImpl<Config> Type; | |
268 // typedef Base; | |
269 // typedef Struct; | |
270 // typedef Range; | |
271 // typedef Region; | |
272 // template<class> struct Handle { typedef type; } // No template typedefs... | |
273 // | |
274 // template<class T> static Handle<T>::type null_handle(); | |
275 // template<class T> static Handle<T>::type handle(T* t); // !is_bitset(t) | |
276 // template<class T> static Handle<T>::type cast(Handle<Type>::type); | |
277 // | |
278 // static bool is_bitset(Type*); | |
279 // static bool is_class(Type*); | |
280 // static bool is_struct(Type*, int tag); | |
281 // static bool is_range(Type*); | |
282 // | |
283 // static bitset as_bitset(Type*); | |
284 // static i::Handle<i::Map> as_class(Type*); | |
285 // static Handle<Struct>::type as_struct(Type*); | |
286 // static Handle<Range>::type as_range(Type*); | |
287 // | |
288 // static Type* from_bitset(bitset); | |
289 // static Handle<Type>::type from_bitset(bitset, Region*); | |
290 // static Handle<Type>::type from_class(i::Handle<Map>, Region*); | |
291 // static Handle<Type>::type from_struct(Handle<Struct>::type, int tag); | |
292 // static Handle<Type>::type from_range(Handle<Range>::type); | |
293 // | |
294 // static Handle<Struct>::type struct_create(int tag, int length, Region*); | |
295 // static void struct_shrink(Handle<Struct>::type, int length); | |
296 // static int struct_tag(Handle<Struct>::type); | |
297 // static int struct_length(Handle<Struct>::type); | |
298 // static Handle<Type>::type struct_get(Handle<Struct>::type, int); | |
299 // static void struct_set(Handle<Struct>::type, int, Handle<Type>::type); | |
300 // template<class V> | |
301 // static i::Handle<V> struct_get_value(Handle<Struct>::type, int); | |
302 // template<class V> | |
303 // static void struct_set_value(Handle<Struct>::type, int, i::Handle<V>); | |
304 // | |
305 // static Handle<Range>::type range_create(Region*); | |
306 // static int range_get_bitset(Handle<Range>::type); | |
307 // static void range_set_bitset(Handle<Range>::type, int); | |
308 // static double range_get_double(Handle<Range>::type, int); | |
309 // static void range_set_double(Handle<Range>::type, int, double, Region*); | |
310 // } | |
311 template<class Config> | |
312 class TypeImpl : public Config::Base { | |
313 public: | 268 public: |
314 // Auxiliary types. | 269 typedef uint32_t bitset; // Internal |
315 | 270 |
316 typedef uint32_t bitset; // Internal | 271 enum : uint32_t { |
317 class BitsetType; // Internal | 272 #define DECLARE_TYPE(type, value) k##type = (value), |
318 class StructuralType; // Internal | 273 BITSET_TYPE_LIST(DECLARE_TYPE) |
319 class UnionType; // Internal | 274 #undef DECLARE_TYPE |
| 275 kUnusedEOL = 0 |
| 276 }; |
320 | 277 |
321 class ClassType; | 278 static bitset SignedSmall(); |
322 class ConstantType; | 279 static bitset UnsignedSmall(); |
323 class RangeType; | |
324 class ContextType; | |
325 class ArrayType; | |
326 class FunctionType; | |
327 class TupleType; | |
328 | 280 |
329 typedef typename Config::template Handle<TypeImpl>::type TypeHandle; | 281 bitset Bitset() { |
330 typedef typename Config::template Handle<ClassType>::type ClassHandle; | 282 return static_cast<bitset>(reinterpret_cast<uintptr_t>(this) ^ 1u); |
331 typedef typename Config::template Handle<ConstantType>::type ConstantHandle; | |
332 typedef typename Config::template Handle<RangeType>::type RangeHandle; | |
333 typedef typename Config::template Handle<ContextType>::type ContextHandle; | |
334 typedef typename Config::template Handle<ArrayType>::type ArrayHandle; | |
335 typedef typename Config::template Handle<FunctionType>::type FunctionHandle; | |
336 typedef typename Config::template Handle<UnionType>::type UnionHandle; | |
337 typedef typename Config::template Handle<TupleType>::type TupleHandle; | |
338 typedef typename Config::Region Region; | |
339 | |
340 // Constructors. | |
341 | |
342 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ | |
343 static TypeImpl* type() { \ | |
344 return BitsetType::New(BitsetType::k##type); \ | |
345 } \ | |
346 static TypeHandle type(Region* region) { \ | |
347 return BitsetType::New(BitsetType::k##type, region); \ | |
348 } | |
349 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) | |
350 #undef DEFINE_TYPE_CONSTRUCTOR | |
351 | |
352 static TypeImpl* SignedSmall() { | |
353 return BitsetType::New(BitsetType::SignedSmall()); | |
354 } | |
355 static TypeHandle SignedSmall(Region* region) { | |
356 return BitsetType::New(BitsetType::SignedSmall(), region); | |
357 } | |
358 static TypeImpl* UnsignedSmall() { | |
359 return BitsetType::New(BitsetType::UnsignedSmall()); | |
360 } | |
361 static TypeHandle UnsignedSmall(Region* region) { | |
362 return BitsetType::New(BitsetType::UnsignedSmall(), region); | |
363 } | 283 } |
364 | 284 |
365 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { | 285 static bool IsInhabited(bitset bits) { |
366 return ClassType::New(map, region); | 286 return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone; |
367 } | |
368 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { | |
369 return ConstantType::New(value, region); | |
370 } | |
371 static TypeHandle Range(double min, double max, Region* region) { | |
372 return RangeType::New( | |
373 min, max, BitsetType::New(REPRESENTATION(BitsetType::kTagged | | |
374 BitsetType::kUntaggedNumber), | |
375 region), | |
376 region); | |
377 } | |
378 static TypeHandle Context(TypeHandle outer, Region* region) { | |
379 return ContextType::New(outer, region); | |
380 } | |
381 static TypeHandle Array(TypeHandle element, Region* region) { | |
382 return ArrayType::New(element, region); | |
383 } | |
384 static FunctionHandle Function( | |
385 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | |
386 return FunctionType::New(result, receiver, arity, region); | |
387 } | |
388 static TypeHandle Function(TypeHandle result, Region* region) { | |
389 return Function(result, Any(region), 0, region); | |
390 } | |
391 static TypeHandle Function( | |
392 TypeHandle result, TypeHandle param0, Region* region) { | |
393 FunctionHandle function = Function(result, Any(region), 1, region); | |
394 function->InitParameter(0, param0); | |
395 return function; | |
396 } | |
397 static TypeHandle Function( | |
398 TypeHandle result, TypeHandle param0, TypeHandle param1, Region* region) { | |
399 FunctionHandle function = Function(result, Any(region), 2, region); | |
400 function->InitParameter(0, param0); | |
401 function->InitParameter(1, param1); | |
402 return function; | |
403 } | |
404 static TypeHandle Function( | |
405 TypeHandle result, TypeHandle param0, TypeHandle param1, | |
406 TypeHandle param2, Region* region) { | |
407 FunctionHandle function = Function(result, Any(region), 3, region); | |
408 function->InitParameter(0, param0); | |
409 function->InitParameter(1, param1); | |
410 function->InitParameter(2, param2); | |
411 return function; | |
412 } | |
413 static TypeHandle Function(TypeHandle result, int arity, TypeHandle* params, | |
414 Region* region) { | |
415 FunctionHandle function = Function(result, Any(region), arity, region); | |
416 for (int i = 0; i < arity; ++i) { | |
417 function->InitParameter(i, params[i]); | |
418 } | |
419 return function; | |
420 } | |
421 static TypeHandle Tuple(TypeHandle first, TypeHandle second, TypeHandle third, | |
422 Region* region) { | |
423 TupleHandle tuple = TupleType::New(3, region); | |
424 tuple->InitElement(0, first); | |
425 tuple->InitElement(1, second); | |
426 tuple->InitElement(2, third); | |
427 return tuple; | |
428 } | 287 } |
429 | 288 |
430 #define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \ | 289 static bool SemanticIsInhabited(bitset bits) { |
431 static TypeHandle Name(Isolate* isolate, Region* region); | 290 return SEMANTIC(bits) != kNone; |
432 SIMD128_TYPES(CONSTRUCT_SIMD_TYPE) | |
433 #undef CONSTRUCT_SIMD_TYPE | |
434 | |
435 static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg); | |
436 static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg); | |
437 | |
438 static TypeHandle Of(double value, Region* region) { | |
439 return Config::from_bitset(BitsetType::ExpandInternals( | |
440 BitsetType::Lub(value)), region); | |
441 } | |
442 static TypeHandle Of(i::Object* value, Region* region) { | |
443 return Config::from_bitset(BitsetType::ExpandInternals( | |
444 BitsetType::Lub(value)), region); | |
445 } | |
446 static TypeHandle Of(i::Handle<i::Object> value, Region* region) { | |
447 return Of(*value, region); | |
448 } | 291 } |
449 | 292 |
450 // Extraction of components. | 293 static bool Is(bitset bits1, bitset bits2) { |
451 static TypeHandle Representation(TypeHandle t, Region* region); | 294 return (bits1 | bits2) == bits2; |
452 static TypeHandle Semantic(TypeHandle t, Region* region); | |
453 | |
454 // Predicates. | |
455 bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); } | |
456 | |
457 bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); } | |
458 template<class TypeHandle> | |
459 bool Is(TypeHandle that) { return this->Is(*that); } | |
460 | |
461 bool Maybe(TypeImpl* that); | |
462 template<class TypeHandle> | |
463 bool Maybe(TypeHandle that) { return this->Maybe(*that); } | |
464 | |
465 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } | |
466 template<class TypeHandle> | |
467 bool Equals(TypeHandle that) { return this->Equals(*that); } | |
468 | |
469 // Equivalent to Constant(val)->Is(this), but avoiding allocation. | |
470 bool Contains(i::Object* val); | |
471 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } | |
472 | |
473 // State-dependent versions of the above that consider subtyping between | |
474 // a constant and its map class. | |
475 inline static TypeHandle NowOf(i::Object* value, Region* region); | |
476 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { | |
477 return NowOf(*value, region); | |
478 } | |
479 bool NowIs(TypeImpl* that); | |
480 template<class TypeHandle> | |
481 bool NowIs(TypeHandle that) { return this->NowIs(*that); } | |
482 inline bool NowContains(i::Object* val); | |
483 bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); } | |
484 | |
485 bool NowStable(); | |
486 | |
487 // Inspection. | |
488 | |
489 bool IsRange() { return Config::is_range(this); } | |
490 bool IsClass() { | |
491 return Config::is_class(this) | |
492 || Config::is_struct(this, StructuralType::kClassTag); | |
493 } | |
494 bool IsConstant() { | |
495 return Config::is_struct(this, StructuralType::kConstantTag); | |
496 } | |
497 bool IsContext() { | |
498 return Config::is_struct(this, StructuralType::kContextTag); | |
499 } | |
500 bool IsArray() { | |
501 return Config::is_struct(this, StructuralType::kArrayTag); | |
502 } | |
503 bool IsFunction() { | |
504 return Config::is_struct(this, StructuralType::kFunctionTag); | |
505 } | |
506 bool IsTuple() { return Config::is_struct(this, StructuralType::kTupleTag); } | |
507 | |
508 ClassType* AsClass() { return ClassType::cast(this); } | |
509 ConstantType* AsConstant() { return ConstantType::cast(this); } | |
510 RangeType* AsRange() { return RangeType::cast(this); } | |
511 ContextType* AsContext() { return ContextType::cast(this); } | |
512 ArrayType* AsArray() { return ArrayType::cast(this); } | |
513 FunctionType* AsFunction() { return FunctionType::cast(this); } | |
514 TupleType* AsTuple() { return TupleType::cast(this); } | |
515 | |
516 // Minimum and maximum of a numeric type. | |
517 // These functions do not distinguish between -0 and +0. If the type equals | |
518 // kNaN, they return NaN; otherwise kNaN is ignored. Only call these | |
519 // functions on subtypes of Number. | |
520 double Min(); | |
521 double Max(); | |
522 | |
523 // Extracts a range from the type: if the type is a range or a union | |
524 // containing a range, that range is returned; otherwise, NULL is returned. | |
525 RangeType* GetRange(); | |
526 | |
527 static bool IsInteger(double x) { | |
528 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. | |
529 } | |
530 static bool IsInteger(i::Object* x) { | |
531 return x->IsNumber() && IsInteger(x->Number()); | |
532 } | 295 } |
533 | 296 |
534 int NumClasses(); | 297 static double Min(bitset); |
535 int NumConstants(); | 298 static double Max(bitset); |
536 | 299 |
537 template<class T> class Iterator; | 300 static bitset Glb(Type* type); // greatest lower bound that's a bitset |
538 Iterator<i::Map> Classes() { | 301 static bitset Glb(double min, double max); |
539 if (this->IsBitset()) return Iterator<i::Map>(); | 302 static bitset Lub(Type* type); // least upper bound that's a bitset |
540 return Iterator<i::Map>(Config::handle(this)); | 303 static bitset Lub(i::Map* map); |
541 } | 304 static bitset Lub(i::Object* value); |
542 Iterator<i::Object> Constants() { | 305 static bitset Lub(double value); |
543 if (this->IsBitset()) return Iterator<i::Object>(); | 306 static bitset Lub(double min, double max); |
544 return Iterator<i::Object>(Config::handle(this)); | 307 static bitset ExpandInternals(bitset bits); |
| 308 |
| 309 static const char* Name(bitset); |
| 310 static void Print(std::ostream& os, bitset); // NOLINT |
| 311 #ifdef DEBUG |
| 312 static void Print(bitset); |
| 313 #endif |
| 314 |
| 315 static bitset NumberBits(bitset bits); |
| 316 |
| 317 static bool IsBitset(Type* type) { |
| 318 return reinterpret_cast<uintptr_t>(type) & 1; |
545 } | 319 } |
546 | 320 |
547 // Casting and conversion. | 321 static Type* NewForTesting(bitset bits) { return New(bits); } |
548 | 322 |
549 static inline TypeImpl* cast(typename Config::Base* object); | 323 private: |
| 324 friend class Type; |
550 | 325 |
551 // Printing. | 326 static Type* New(bitset bits) { |
| 327 return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u)); |
| 328 } |
552 | 329 |
553 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; | 330 struct Boundary { |
| 331 bitset internal; |
| 332 bitset external; |
| 333 double min; |
| 334 }; |
| 335 static const Boundary BoundariesArray[]; |
| 336 static inline const Boundary* Boundaries(); |
| 337 static inline size_t BoundariesSize(); |
| 338 }; |
554 | 339 |
555 void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT | 340 // ----------------------------------------------------------------------------- |
| 341 // Superclass for non-bitset types (internal). |
| 342 class TypeBase { |
| 343 protected: |
| 344 friend class Type; |
556 | 345 |
557 #ifdef DEBUG | 346 enum Kind { |
558 void Print(); | 347 kClass, |
559 #endif | 348 kConstant, |
| 349 kContext, |
| 350 kArray, |
| 351 kFunction, |
| 352 kTuple, |
| 353 kUnion, |
| 354 kRange |
| 355 }; |
560 | 356 |
561 bool IsUnionForTesting() { return IsUnion(); } | 357 Kind kind() const { return kind_; } |
| 358 explicit TypeBase(Kind kind) : kind_(kind) {} |
562 | 359 |
563 protected: | 360 static bool IsKind(Type* type, Kind kind) { |
564 // Friends. | 361 if (BitsetType::IsBitset(type)) return false; |
| 362 TypeBase* base = reinterpret_cast<TypeBase*>(type); |
| 363 return base->kind() == kind; |
| 364 } |
565 | 365 |
566 template<class> friend class Iterator; | 366 // The hacky conversion to/from Type*. |
567 template<class> friend class TypeImpl; | 367 static Type* AsType(TypeBase* type) { return reinterpret_cast<Type*>(type); } |
| 368 static TypeBase* FromType(Type* type) { |
| 369 return reinterpret_cast<TypeBase*>(type); |
| 370 } |
568 | 371 |
569 // Handle conversion. | 372 private: |
| 373 Kind kind_; |
| 374 }; |
570 | 375 |
571 template<class T> | 376 // ----------------------------------------------------------------------------- |
572 static typename Config::template Handle<T>::type handle(T* type) { | 377 // Class types. |
573 return Config::handle(type); | 378 |
| 379 class ClassType : public TypeBase { |
| 380 public: |
| 381 i::Handle<i::Map> Map() { return map_; } |
| 382 |
| 383 private: |
| 384 friend class Type; |
| 385 friend class BitsetType; |
| 386 |
| 387 static Type* New(i::Handle<i::Map> map, Zone* zone) { |
| 388 return AsType(new (zone->New(sizeof(ClassType))) |
| 389 ClassType(BitsetType::Lub(*map), map)); |
574 } | 390 } |
575 TypeImpl* unhandle() { return this; } | |
576 | 391 |
577 // Internal inspection. | 392 static ClassType* cast(Type* type) { |
| 393 DCHECK(IsKind(type, kClass)); |
| 394 return static_cast<ClassType*>(FromType(type)); |
| 395 } |
578 | 396 |
579 bool IsNone() { return this == None(); } | 397 ClassType(BitsetType::bitset bitset, i::Handle<i::Map> map) |
580 bool IsAny() { return this == Any(); } | 398 : TypeBase(kClass), bitset_(bitset), map_(map) {} |
581 bool IsBitset() { return Config::is_bitset(this); } | |
582 bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); } | |
583 | 399 |
584 bitset AsBitset() { | 400 BitsetType::bitset Lub() { return bitset_; } |
585 DCHECK(this->IsBitset()); | 401 |
586 return static_cast<BitsetType*>(this)->Bitset(); | 402 BitsetType::bitset bitset_; |
| 403 Handle<i::Map> map_; |
| 404 }; |
| 405 |
| 406 // ----------------------------------------------------------------------------- |
| 407 // Constant types. |
| 408 |
| 409 class ConstantType : public TypeBase { |
| 410 public: |
| 411 i::Handle<i::Object> Value() { return object_; } |
| 412 |
| 413 private: |
| 414 friend class Type; |
| 415 friend class BitsetType; |
| 416 |
| 417 static Type* New(i::Handle<i::Object> value, Zone* zone) { |
| 418 BitsetType::bitset bitset = BitsetType::Lub(*value); |
| 419 return AsType(new (zone->New(sizeof(ConstantType))) |
| 420 ConstantType(bitset, value)); |
587 } | 421 } |
588 UnionType* AsUnion() { return UnionType::cast(this); } | |
589 | 422 |
590 bitset Representation(); | 423 static ConstantType* cast(Type* type) { |
| 424 DCHECK(IsKind(type, kConstant)); |
| 425 return static_cast<ConstantType*>(FromType(type)); |
| 426 } |
591 | 427 |
592 // Auxiliary functions. | 428 ConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object) |
593 bool SemanticMaybe(TypeImpl* that); | 429 : TypeBase(kConstant), bitset_(bitset), object_(object) {} |
594 | 430 |
595 bitset BitsetGlb() { return BitsetType::Glb(this); } | 431 BitsetType::bitset Lub() { return bitset_; } |
596 bitset BitsetLub() { return BitsetType::Lub(this); } | |
597 | 432 |
598 bool SlowIs(TypeImpl* that); | 433 BitsetType::bitset bitset_; |
599 bool SemanticIs(TypeImpl* that); | 434 Handle<i::Object> object_; |
| 435 }; |
| 436 // TODO(neis): Also cache value if numerical. |
| 437 // TODO(neis): Allow restricting the representation. |
600 | 438 |
| 439 // ----------------------------------------------------------------------------- |
| 440 // Range types. |
| 441 |
| 442 class RangeType : public TypeBase { |
| 443 public: |
601 struct Limits { | 444 struct Limits { |
602 double min; | 445 double min; |
603 double max; | 446 double max; |
604 Limits(double min, double max) : min(min), max(max) {} | 447 Limits(double min, double max) : min(min), max(max) {} |
605 explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {} | 448 explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {} |
606 bool IsEmpty(); | 449 bool IsEmpty(); |
607 static Limits Empty() { return Limits(1, 0); } | 450 static Limits Empty() { return Limits(1, 0); } |
608 static Limits Intersect(Limits lhs, Limits rhs); | 451 static Limits Intersect(Limits lhs, Limits rhs); |
609 static Limits Union(Limits lhs, Limits rhs); | 452 static Limits Union(Limits lhs, Limits rhs); |
610 }; | 453 }; |
611 | 454 |
612 static bool Overlap(RangeType* lhs, RangeType* rhs); | 455 double Min() { return limits_.min; } |
613 static bool Contains(RangeType* lhs, RangeType* rhs); | 456 double Max() { return limits_.max; } |
614 static bool Contains(RangeType* range, ConstantType* constant); | |
615 static bool Contains(RangeType* range, i::Object* val); | |
616 | 457 |
617 static int UpdateRange( | 458 private: |
618 RangeHandle type, UnionHandle result, int size, Region* region); | 459 friend class Type; |
| 460 friend class BitsetType; |
| 461 friend class UnionType; |
619 | 462 |
620 static Limits IntersectRangeAndBitset(TypeHandle range, TypeHandle bits, | 463 static Type* New(double min, double max, BitsetType::bitset representation, |
621 Region* region); | 464 Zone* zone) { |
622 static Limits ToLimits(bitset bits, Region* region); | 465 return New(Limits(min, max), representation, zone); |
| 466 } |
623 | 467 |
624 bool SimplyEquals(TypeImpl* that); | 468 static bool IsInteger(double x) { |
625 template<class TypeHandle> | 469 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
626 bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); } | 470 } |
627 | 471 |
628 static int AddToUnion( | 472 static Type* New(Limits lim, BitsetType::bitset representation, Zone* zone) { |
629 TypeHandle type, UnionHandle result, int size, Region* region); | 473 DCHECK(IsInteger(lim.min) && IsInteger(lim.max)); |
630 static int IntersectAux(TypeHandle type, TypeHandle other, UnionHandle result, | 474 DCHECK(lim.min <= lim.max); |
631 int size, Limits* limits, Region* region); | 475 DCHECK(REPRESENTATION(representation) == representation); |
632 static TypeHandle NormalizeUnion(UnionHandle unioned, int size, | 476 BitsetType::bitset bits = |
633 Region* region); | 477 SEMANTIC(BitsetType::Lub(lim.min, lim.max)) | representation; |
634 static TypeHandle NormalizeRangeAndBitset(RangeHandle range, bitset* bits, | 478 |
635 Region* region); | 479 return AsType(new (zone->New(sizeof(RangeType))) RangeType(bits, lim)); |
| 480 } |
| 481 |
| 482 static RangeType* cast(Type* type) { |
| 483 DCHECK(IsKind(type, kRange)); |
| 484 return static_cast<RangeType*>(FromType(type)); |
| 485 } |
| 486 |
| 487 RangeType(BitsetType::bitset bitset, Limits limits) |
| 488 : TypeBase(kRange), bitset_(bitset), limits_(limits) {} |
| 489 |
| 490 BitsetType::bitset Lub() { return bitset_; } |
| 491 |
| 492 BitsetType::bitset bitset_; |
| 493 Limits limits_; |
636 }; | 494 }; |
637 | 495 |
| 496 // ----------------------------------------------------------------------------- |
| 497 // Context types. |
| 498 |
| 499 class ContextType : public TypeBase { |
| 500 public: |
| 501 Type* Outer() { return outer_; } |
| 502 |
| 503 private: |
| 504 friend class Type; |
| 505 |
| 506 static Type* New(Type* outer, Zone* zone) { |
| 507 return AsType(new (zone->New(sizeof(ContextType))) ContextType(outer)); |
| 508 } |
| 509 |
| 510 static ContextType* cast(Type* type) { |
| 511 DCHECK(IsKind(type, kContext)); |
| 512 return static_cast<ContextType*>(FromType(type)); |
| 513 } |
| 514 |
| 515 explicit ContextType(Type* outer) : TypeBase(kContext), outer_(outer) {} |
| 516 |
| 517 Type* outer_; |
| 518 }; |
638 | 519 |
639 // ----------------------------------------------------------------------------- | 520 // ----------------------------------------------------------------------------- |
640 // Bitset types (internal). | 521 // Array types. |
641 | 522 |
642 template<class Config> | 523 class ArrayType : public TypeBase { |
643 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { | 524 public: |
644 protected: | 525 Type* Element() { return element_; } |
645 friend class TypeImpl<Config>; | |
646 | 526 |
647 enum : uint32_t { | 527 private: |
648 #define DECLARE_TYPE(type, value) k##type = (value), | 528 friend class Type; |
649 BITSET_TYPE_LIST(DECLARE_TYPE) | |
650 #undef DECLARE_TYPE | |
651 kUnusedEOL = 0 | |
652 }; | |
653 | 529 |
654 static bitset SignedSmall(); | 530 explicit ArrayType(Type* element) : TypeBase(kArray), element_(element) {} |
655 static bitset UnsignedSmall(); | |
656 | 531 |
657 bitset Bitset() { return Config::as_bitset(this); } | 532 static Type* New(Type* element, Zone* zone) { |
658 | 533 return AsType(new (zone->New(sizeof(ArrayType))) ArrayType(element)); |
659 static TypeImpl* New(bitset bits) { | |
660 return Config::from_bitset(bits); | |
661 } | |
662 static TypeHandle New(bitset bits, Region* region) { | |
663 return Config::from_bitset(bits, region); | |
664 } | 534 } |
665 | 535 |
666 static bool IsInhabited(bitset bits) { | 536 static ArrayType* cast(Type* type) { |
667 return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone; | 537 DCHECK(IsKind(type, kArray)); |
| 538 return static_cast<ArrayType*>(FromType(type)); |
668 } | 539 } |
669 | 540 |
670 static bool SemanticIsInhabited(bitset bits) { | 541 Type* element_; |
671 return SEMANTIC(bits) != kNone; | 542 }; |
| 543 |
| 544 // ----------------------------------------------------------------------------- |
| 545 // Superclass for types with variable number of type fields. |
| 546 class StructuralType : public TypeBase { |
| 547 public: |
| 548 int LengthForTesting() { return Length(); } |
| 549 |
| 550 protected: |
| 551 friend class Type; |
| 552 |
| 553 int Length() { return length_; } |
| 554 |
| 555 Type* Get(int i) { |
| 556 DCHECK(0 <= i && i < this->Length()); |
| 557 return elements_[i]; |
672 } | 558 } |
673 | 559 |
674 static bool Is(bitset bits1, bitset bits2) { | 560 void Set(int i, Type* type) { |
675 return (bits1 | bits2) == bits2; | 561 DCHECK(0 <= i && i < this->Length()); |
| 562 elements_[i] = type; |
676 } | 563 } |
677 | 564 |
678 static double Min(bitset); | 565 void Shrink(int length) { |
679 static double Max(bitset); | 566 DCHECK(2 <= length && length <= this->Length()); |
| 567 length_ = length; |
| 568 } |
680 | 569 |
681 static bitset Glb(TypeImpl* type); // greatest lower bound that's a bitset | 570 StructuralType(Kind kind, int length, i::Zone* zone) |
682 static bitset Glb(double min, double max); | 571 : TypeBase(kind), length_(length) { |
683 static bitset Lub(TypeImpl* type); // least upper bound that's a bitset | 572 elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length)); |
684 static bitset Lub(i::Map* map); | 573 } |
685 static bitset Lub(i::Object* value); | |
686 static bitset Lub(double value); | |
687 static bitset Lub(double min, double max); | |
688 static bitset ExpandInternals(bitset bits); | |
689 | |
690 static const char* Name(bitset); | |
691 static void Print(std::ostream& os, bitset); // NOLINT | |
692 #ifdef DEBUG | |
693 static void Print(bitset); | |
694 #endif | |
695 | |
696 static bitset NumberBits(bitset bits); | |
697 | 574 |
698 private: | 575 private: |
699 struct Boundary { | 576 int length_; |
700 bitset internal; | 577 Type** elements_; |
701 bitset external; | |
702 double min; | |
703 }; | |
704 static const Boundary BoundariesArray[]; | |
705 static inline const Boundary* Boundaries(); | |
706 static inline size_t BoundariesSize(); | |
707 }; | 578 }; |
708 | 579 |
| 580 // ----------------------------------------------------------------------------- |
| 581 // Function types. |
709 | 582 |
710 // ----------------------------------------------------------------------------- | 583 class FunctionType : public StructuralType { |
711 // Superclass for non-bitset types (internal). | 584 public: |
712 // Contains a tag and a variable number of type or value fields. | 585 int Arity() { return this->Length() - 2; } |
| 586 Type* Result() { return this->Get(0); } |
| 587 Type* Receiver() { return this->Get(1); } |
| 588 Type* Parameter(int i) { return this->Get(2 + i); } |
713 | 589 |
714 template<class Config> | 590 void InitParameter(int i, Type* type) { this->Set(2 + i, type); } |
715 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { | |
716 protected: | |
717 template<class> friend class TypeImpl; | |
718 friend struct ZoneTypeConfig; // For tags. | |
719 friend struct HeapTypeConfig; | |
720 | 591 |
721 enum Tag { | 592 private: |
722 kClassTag, | 593 friend class Type; |
723 kConstantTag, | |
724 kContextTag, | |
725 kArrayTag, | |
726 kFunctionTag, | |
727 kTupleTag, | |
728 kUnionTag | |
729 }; | |
730 | 594 |
731 int Length() { | 595 FunctionType(Type* result, Type* receiver, int arity, Zone* zone) |
732 return Config::struct_length(Config::as_struct(this)); | 596 : StructuralType(kFunction, 2 + arity, zone) { |
733 } | 597 Set(0, result); |
734 TypeHandle Get(int i) { | 598 Set(1, receiver); |
735 DCHECK(0 <= i && i < this->Length()); | |
736 return Config::struct_get(Config::as_struct(this), i); | |
737 } | |
738 void Set(int i, TypeHandle type) { | |
739 DCHECK(0 <= i && i < this->Length()); | |
740 Config::struct_set(Config::as_struct(this), i, type); | |
741 } | |
742 void Shrink(int length) { | |
743 DCHECK(2 <= length && length <= this->Length()); | |
744 Config::struct_shrink(Config::as_struct(this), length); | |
745 } | |
746 template<class V> i::Handle<V> GetValue(int i) { | |
747 DCHECK(0 <= i && i < this->Length()); | |
748 return Config::template struct_get_value<V>(Config::as_struct(this), i); | |
749 } | |
750 template<class V> void SetValue(int i, i::Handle<V> x) { | |
751 DCHECK(0 <= i && i < this->Length()); | |
752 Config::struct_set_value(Config::as_struct(this), i, x); | |
753 } | 599 } |
754 | 600 |
755 static TypeHandle New(Tag tag, int length, Region* region) { | 601 static Type* New(Type* result, Type* receiver, int arity, Zone* zone) { |
756 DCHECK(1 <= length); | 602 return AsType(new (zone->New(sizeof(FunctionType))) |
757 return Config::from_struct(Config::struct_create(tag, length, region)); | 603 FunctionType(result, receiver, arity, zone)); |
| 604 } |
| 605 |
| 606 static FunctionType* cast(Type* type) { |
| 607 DCHECK(IsKind(type, kFunction)); |
| 608 return static_cast<FunctionType*>(FromType(type)); |
758 } | 609 } |
759 }; | 610 }; |
760 | 611 |
| 612 // ----------------------------------------------------------------------------- |
| 613 // Tuple types. |
| 614 |
| 615 class TupleType : public StructuralType { |
| 616 public: |
| 617 int Arity() { return this->Length(); } |
| 618 Type* Element(int i) { return this->Get(i); } |
| 619 |
| 620 void InitElement(int i, Type* type) { this->Set(i, type); } |
| 621 |
| 622 private: |
| 623 friend class Type; |
| 624 |
| 625 TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {} |
| 626 |
| 627 static Type* New(int length, Zone* zone) { |
| 628 return AsType(new (zone->New(sizeof(TupleType))) TupleType(length, zone)); |
| 629 } |
| 630 |
| 631 static TupleType* cast(Type* type) { |
| 632 DCHECK(IsKind(type, kTuple)); |
| 633 return static_cast<TupleType*>(FromType(type)); |
| 634 } |
| 635 }; |
761 | 636 |
762 // ----------------------------------------------------------------------------- | 637 // ----------------------------------------------------------------------------- |
763 // Union types (internal). | 638 // Union types (internal). |
764 // A union is a structured type with the following invariants: | 639 // A union is a structured type with the following invariants: |
765 // - its length is at least 2 | 640 // - its length is at least 2 |
766 // - at most one field is a bitset, and it must go into index 0 | 641 // - at most one field is a bitset, and it must go into index 0 |
767 // - no field is a union | 642 // - no field is a union |
768 // - no field is a subtype of any other field | 643 // - no field is a subtype of any other field |
769 template<class Config> | 644 class UnionType : public StructuralType { |
770 class TypeImpl<Config>::UnionType : public StructuralType { | 645 private: |
771 public: | 646 friend Type; |
772 static UnionHandle New(int length, Region* region) { | 647 friend BitsetType; |
773 return Config::template cast<UnionType>( | 648 |
774 StructuralType::New(StructuralType::kUnionTag, length, region)); | 649 UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {} |
775 } | 650 |
776 | 651 static Type* New(int length, Zone* zone) { |
777 static UnionType* cast(TypeImpl* type) { | 652 return AsType(new (zone->New(sizeof(UnionType))) UnionType(length, zone)); |
778 DCHECK(type->IsUnion()); | 653 } |
779 return static_cast<UnionType*>(type); | 654 |
| 655 static UnionType* cast(Type* type) { |
| 656 DCHECK(IsKind(type, kUnion)); |
| 657 return static_cast<UnionType*>(FromType(type)); |
780 } | 658 } |
781 | 659 |
782 bool Wellformed(); | 660 bool Wellformed(); |
783 }; | 661 }; |
784 | 662 |
785 | 663 class Type { |
786 // ----------------------------------------------------------------------------- | |
787 // Class types. | |
788 | |
789 template<class Config> | |
790 class TypeImpl<Config>::ClassType : public StructuralType { | |
791 public: | 664 public: |
792 i::Handle<i::Map> Map() { | 665 typedef BitsetType::bitset bitset; // Internal |
793 return Config::is_class(this) ? Config::as_class(this) : | 666 |
794 this->template GetValue<i::Map>(1); | 667 // Constructors. |
795 } | 668 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ |
796 | 669 static Type* type() { return BitsetType::New(BitsetType::k##type); } |
797 static ClassHandle New(i::Handle<i::Map> map, Region* region) { | 670 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) |
798 ClassHandle type = | 671 #undef DEFINE_TYPE_CONSTRUCTOR |
799 Config::template cast<ClassType>(Config::from_class(map, region)); | 672 |
800 if (!type->IsClass()) { | 673 static Type* SignedSmall() { |
801 type = Config::template cast<ClassType>( | 674 return BitsetType::New(BitsetType::SignedSmall()); |
802 StructuralType::New(StructuralType::kClassTag, 2, region)); | 675 } |
803 type->Set(0, BitsetType::New(BitsetType::Lub(*map), region)); | 676 static Type* UnsignedSmall() { |
804 type->SetValue(1, map); | 677 return BitsetType::New(BitsetType::UnsignedSmall()); |
| 678 } |
| 679 |
| 680 static Type* Class(i::Handle<i::Map> map, Zone* zone) { |
| 681 return ClassType::New(map, zone); |
| 682 } |
| 683 static Type* Constant(i::Handle<i::Object> value, Zone* zone) { |
| 684 return ConstantType::New(value, zone); |
| 685 } |
| 686 static Type* Range(double min, double max, Zone* zone) { |
| 687 return RangeType::New(min, max, REPRESENTATION(BitsetType::kTagged | |
| 688 BitsetType::kUntaggedNumber), |
| 689 zone); |
| 690 } |
| 691 static Type* Context(Type* outer, Zone* zone) { |
| 692 return ContextType::New(outer, zone); |
| 693 } |
| 694 static Type* Array(Type* element, Zone* zone) { |
| 695 return ArrayType::New(element, zone); |
| 696 } |
| 697 static Type* Function(Type* result, Type* receiver, int arity, Zone* zone) { |
| 698 return FunctionType::New(result, receiver, arity, zone); |
| 699 } |
| 700 static Type* Function(Type* result, Zone* zone) { |
| 701 return Function(result, Any(), 0, zone); |
| 702 } |
| 703 static Type* Function(Type* result, Type* param0, Zone* zone) { |
| 704 Type* function = Function(result, Any(), 1, zone); |
| 705 function->AsFunction()->InitParameter(0, param0); |
| 706 return function; |
| 707 } |
| 708 static Type* Function(Type* result, Type* param0, Type* param1, Zone* zone) { |
| 709 Type* function = Function(result, Any(), 2, zone); |
| 710 function->AsFunction()->InitParameter(0, param0); |
| 711 function->AsFunction()->InitParameter(1, param1); |
| 712 return function; |
| 713 } |
| 714 static Type* Function(Type* result, Type* param0, Type* param1, Type* param2, |
| 715 Zone* zone) { |
| 716 Type* function = Function(result, Any(), 3, zone); |
| 717 function->AsFunction()->InitParameter(0, param0); |
| 718 function->AsFunction()->InitParameter(1, param1); |
| 719 function->AsFunction()->InitParameter(2, param2); |
| 720 return function; |
| 721 } |
| 722 static Type* Function(Type* result, int arity, Type** params, Zone* zone) { |
| 723 Type* function = Function(result, Any(), arity, zone); |
| 724 for (int i = 0; i < arity; ++i) { |
| 725 function->AsFunction()->InitParameter(i, params[i]); |
805 } | 726 } |
806 return type; | 727 return function; |
807 } | 728 } |
808 | 729 static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone) { |
809 static ClassType* cast(TypeImpl* type) { | 730 Type* tuple = TupleType::New(3, zone); |
810 DCHECK(type->IsClass()); | 731 tuple->AsTuple()->InitElement(0, first); |
811 return static_cast<ClassType*>(type); | 732 tuple->AsTuple()->InitElement(1, second); |
812 } | 733 tuple->AsTuple()->InitElement(2, third); |
| 734 return tuple; |
| 735 } |
| 736 |
| 737 #define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \ |
| 738 static Type* Name(Isolate* isolate, Zone* zone); |
| 739 SIMD128_TYPES(CONSTRUCT_SIMD_TYPE) |
| 740 #undef CONSTRUCT_SIMD_TYPE |
| 741 |
| 742 static Type* Union(Type* type1, Type* type2, Zone* reg); |
| 743 static Type* Intersect(Type* type1, Type* type2, Zone* reg); |
| 744 |
| 745 static Type* Of(double value, Zone* zone) { |
| 746 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value))); |
| 747 } |
| 748 static Type* Of(i::Object* value, Zone* zone) { |
| 749 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value))); |
| 750 } |
| 751 static Type* Of(i::Handle<i::Object> value, Zone* zone) { |
| 752 return Of(*value, zone); |
| 753 } |
| 754 |
| 755 // Extraction of components. |
| 756 static Type* Representation(Type* t, Zone* zone); |
| 757 static Type* Semantic(Type* t, Zone* zone); |
| 758 |
| 759 // Predicates. |
| 760 bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); } |
| 761 |
| 762 bool Is(Type* that) { return this == that || this->SlowIs(that); } |
| 763 bool Maybe(Type* that); |
| 764 bool Equals(Type* that) { return this->Is(that) && that->Is(this); } |
| 765 |
| 766 // Equivalent to Constant(val)->Is(this), but avoiding allocation. |
| 767 bool Contains(i::Object* val); |
| 768 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } |
| 769 |
| 770 // State-dependent versions of the above that consider subtyping between |
| 771 // a constant and its map class. |
| 772 static Type* NowOf(i::Object* value, Zone* zone); |
| 773 static Type* NowOf(i::Handle<i::Object> value, Zone* zone) { |
| 774 return NowOf(*value, zone); |
| 775 } |
| 776 bool NowIs(Type* that); |
| 777 bool NowContains(i::Object* val); |
| 778 bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); } |
| 779 |
| 780 bool NowStable(); |
| 781 |
| 782 // Inspection. |
| 783 bool IsRange() { return IsKind(TypeBase::kRange); } |
| 784 bool IsClass() { return IsKind(TypeBase::kClass); } |
| 785 bool IsConstant() { return IsKind(TypeBase::kConstant); } |
| 786 bool IsContext() { return IsKind(TypeBase::kContext); } |
| 787 bool IsArray() { return IsKind(TypeBase::kArray); } |
| 788 bool IsFunction() { return IsKind(TypeBase::kFunction); } |
| 789 bool IsTuple() { return IsKind(TypeBase::kTuple); } |
| 790 |
| 791 ClassType* AsClass() { return ClassType::cast(this); } |
| 792 ConstantType* AsConstant() { return ConstantType::cast(this); } |
| 793 RangeType* AsRange() { return RangeType::cast(this); } |
| 794 ContextType* AsContext() { return ContextType::cast(this); } |
| 795 ArrayType* AsArray() { return ArrayType::cast(this); } |
| 796 FunctionType* AsFunction() { return FunctionType::cast(this); } |
| 797 TupleType* AsTuple() { return TupleType::cast(this); } |
| 798 |
| 799 // Minimum and maximum of a numeric type. |
| 800 // These functions do not distinguish between -0 and +0. If the type equals |
| 801 // kNaN, they return NaN; otherwise kNaN is ignored. Only call these |
| 802 // functions on subtypes of Number. |
| 803 double Min(); |
| 804 double Max(); |
| 805 |
| 806 // Extracts a range from the type: if the type is a range or a union |
| 807 // containing a range, that range is returned; otherwise, NULL is returned. |
| 808 Type* GetRange(); |
| 809 |
| 810 static bool IsInteger(i::Object* x); |
| 811 static bool IsInteger(double x) { |
| 812 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
| 813 } |
| 814 |
| 815 int NumClasses(); |
| 816 int NumConstants(); |
| 817 |
| 818 template <class T> |
| 819 class Iterator { |
| 820 public: |
| 821 bool Done() const { return index_ < 0; } |
| 822 i::Handle<T> Current(); |
| 823 void Advance(); |
| 824 |
| 825 private: |
| 826 friend class Type; |
| 827 |
| 828 Iterator() : index_(-1) {} |
| 829 explicit Iterator(Type* type) : type_(type), index_(-1) { Advance(); } |
| 830 |
| 831 inline bool matches(Type* type); |
| 832 inline Type* get_type(); |
| 833 |
| 834 Type* type_; |
| 835 int index_; |
| 836 }; |
| 837 |
| 838 Iterator<i::Map> Classes() { |
| 839 if (this->IsBitset()) return Iterator<i::Map>(); |
| 840 return Iterator<i::Map>(this); |
| 841 } |
| 842 Iterator<i::Object> Constants() { |
| 843 if (this->IsBitset()) return Iterator<i::Object>(); |
| 844 return Iterator<i::Object>(this); |
| 845 } |
| 846 |
| 847 // Printing. |
| 848 |
| 849 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; |
| 850 |
| 851 void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT |
| 852 |
| 853 #ifdef DEBUG |
| 854 void Print(); |
| 855 #endif |
| 856 |
| 857 // Helpers for testing. |
| 858 bool IsBitsetForTesting() { return IsBitset(); } |
| 859 bool IsUnionForTesting() { return IsUnion(); } |
| 860 bitset AsBitsetForTesting() { return AsBitset(); } |
| 861 UnionType* AsUnionForTesting() { return AsUnion(); } |
813 | 862 |
814 private: | 863 private: |
815 template<class> friend class TypeImpl; | 864 // Friends. |
816 bitset Lub() { | 865 template <class> |
817 return Config::is_class(this) ? | 866 friend class Iterator; |
818 BitsetType::Lub(*Config::as_class(this)) : | 867 friend BitsetType; |
819 this->Get(0)->AsBitset(); | 868 friend UnionType; |
820 } | 869 |
| 870 // Internal inspection. |
| 871 bool IsKind(TypeBase::Kind kind) { return TypeBase::IsKind(this, kind); } |
| 872 |
| 873 bool IsNone() { return this == None(); } |
| 874 bool IsAny() { return this == Any(); } |
| 875 bool IsBitset() { return BitsetType::IsBitset(this); } |
| 876 bool IsUnion() { return IsKind(TypeBase::kUnion); } |
| 877 |
| 878 bitset AsBitset() { |
| 879 DCHECK(this->IsBitset()); |
| 880 return reinterpret_cast<BitsetType*>(this)->Bitset(); |
| 881 } |
| 882 UnionType* AsUnion() { return UnionType::cast(this); } |
| 883 |
| 884 bitset Representation(); |
| 885 |
| 886 // Auxiliary functions. |
| 887 bool SemanticMaybe(Type* that); |
| 888 |
| 889 bitset BitsetGlb() { return BitsetType::Glb(this); } |
| 890 bitset BitsetLub() { return BitsetType::Lub(this); } |
| 891 |
| 892 bool SlowIs(Type* that); |
| 893 bool SemanticIs(Type* that); |
| 894 |
| 895 static bool Overlap(RangeType* lhs, RangeType* rhs); |
| 896 static bool Contains(RangeType* lhs, RangeType* rhs); |
| 897 static bool Contains(RangeType* range, ConstantType* constant); |
| 898 static bool Contains(RangeType* range, i::Object* val); |
| 899 |
| 900 static int UpdateRange(Type* type, UnionType* result, int size, Zone* zone); |
| 901 |
| 902 static RangeType::Limits IntersectRangeAndBitset(Type* range, Type* bits, |
| 903 Zone* zone); |
| 904 static RangeType::Limits ToLimits(bitset bits, Zone* zone); |
| 905 |
| 906 bool SimplyEquals(Type* that); |
| 907 |
| 908 static int AddToUnion(Type* type, UnionType* result, int size, Zone* zone); |
| 909 static int IntersectAux(Type* type, Type* other, UnionType* result, int size, |
| 910 RangeType::Limits* limits, Zone* zone); |
| 911 static Type* NormalizeUnion(Type* unioned, int size, Zone* zone); |
| 912 static Type* NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone); |
821 }; | 913 }; |
822 | 914 |
823 | |
824 // ----------------------------------------------------------------------------- | |
825 // Constant types. | |
826 | |
827 template<class Config> | |
828 class TypeImpl<Config>::ConstantType : public StructuralType { | |
829 public: | |
830 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } | |
831 | |
832 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { | |
833 ConstantHandle type = Config::template cast<ConstantType>( | |
834 StructuralType::New(StructuralType::kConstantTag, 2, region)); | |
835 type->Set(0, BitsetType::New(BitsetType::Lub(*value), region)); | |
836 type->SetValue(1, value); | |
837 return type; | |
838 } | |
839 | |
840 static ConstantType* cast(TypeImpl* type) { | |
841 DCHECK(type->IsConstant()); | |
842 return static_cast<ConstantType*>(type); | |
843 } | |
844 | |
845 private: | |
846 template<class> friend class TypeImpl; | |
847 bitset Lub() { return this->Get(0)->AsBitset(); } | |
848 }; | |
849 // TODO(neis): Also cache value if numerical. | |
850 // TODO(neis): Allow restricting the representation. | |
851 | |
852 | |
853 // ----------------------------------------------------------------------------- | |
854 // Range types. | |
855 | |
856 template <class Config> | |
857 class TypeImpl<Config>::RangeType : public TypeImpl<Config> { | |
858 public: | |
859 double Min() { return Config::range_get_double(Config::as_range(this), 0); } | |
860 double Max() { return Config::range_get_double(Config::as_range(this), 1); } | |
861 | |
862 static RangeHandle New(double min, double max, TypeHandle representation, | |
863 Region* region) { | |
864 DCHECK(IsInteger(min) && IsInteger(max)); | |
865 DCHECK(min <= max); | |
866 bitset representation_bits = representation->AsBitset(); | |
867 DCHECK(REPRESENTATION(representation_bits) == representation_bits); | |
868 | |
869 typename Config::template Handle<typename Config::Range>::type range = | |
870 Config::range_create(region); | |
871 | |
872 bitset bits = SEMANTIC(BitsetType::Lub(min, max)) | representation_bits; | |
873 Config::range_set_bitset(range, bits); | |
874 Config::range_set_double(range, 0, min, region); | |
875 Config::range_set_double(range, 1, max, region); | |
876 return Config::template cast<RangeType>(Config::from_range(range)); | |
877 } | |
878 | |
879 static RangeHandle New(Limits lim, bitset representation, Region* region) { | |
880 return New(lim.min, lim.max, BitsetType::New(representation, region), | |
881 region); | |
882 } | |
883 | |
884 static RangeType* cast(TypeImpl* type) { | |
885 DCHECK(type->IsRange()); | |
886 return static_cast<RangeType*>(type); | |
887 } | |
888 | |
889 private: | |
890 template<class> friend class TypeImpl; | |
891 bitset Lub() { | |
892 return Config::range_get_bitset(Config::as_range(this)); | |
893 } | |
894 }; | |
895 | |
896 | |
897 // ----------------------------------------------------------------------------- | |
898 // Context types. | |
899 | |
900 template<class Config> | |
901 class TypeImpl<Config>::ContextType : public StructuralType { | |
902 public: | |
903 TypeHandle Outer() { return this->Get(0); } | |
904 | |
905 static ContextHandle New(TypeHandle outer, Region* region) { | |
906 ContextHandle type = Config::template cast<ContextType>( | |
907 StructuralType::New(StructuralType::kContextTag, 1, region)); | |
908 type->Set(0, outer); | |
909 return type; | |
910 } | |
911 | |
912 static ContextType* cast(TypeImpl* type) { | |
913 DCHECK(type->IsContext()); | |
914 return static_cast<ContextType*>(type); | |
915 } | |
916 }; | |
917 | |
918 | |
919 // ----------------------------------------------------------------------------- | |
920 // Array types. | |
921 | |
922 template<class Config> | |
923 class TypeImpl<Config>::ArrayType : public StructuralType { | |
924 public: | |
925 TypeHandle Element() { return this->Get(0); } | |
926 | |
927 static ArrayHandle New(TypeHandle element, Region* region) { | |
928 ArrayHandle type = Config::template cast<ArrayType>( | |
929 StructuralType::New(StructuralType::kArrayTag, 1, region)); | |
930 type->Set(0, element); | |
931 return type; | |
932 } | |
933 | |
934 static ArrayType* cast(TypeImpl* type) { | |
935 DCHECK(type->IsArray()); | |
936 return static_cast<ArrayType*>(type); | |
937 } | |
938 }; | |
939 | |
940 | |
941 // ----------------------------------------------------------------------------- | |
942 // Function types. | |
943 | |
944 template<class Config> | |
945 class TypeImpl<Config>::FunctionType : public StructuralType { | |
946 public: | |
947 int Arity() { return this->Length() - 2; } | |
948 TypeHandle Result() { return this->Get(0); } | |
949 TypeHandle Receiver() { return this->Get(1); } | |
950 TypeHandle Parameter(int i) { return this->Get(2 + i); } | |
951 | |
952 void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); } | |
953 | |
954 static FunctionHandle New( | |
955 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | |
956 FunctionHandle type = Config::template cast<FunctionType>( | |
957 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region)); | |
958 type->Set(0, result); | |
959 type->Set(1, receiver); | |
960 return type; | |
961 } | |
962 | |
963 static FunctionType* cast(TypeImpl* type) { | |
964 DCHECK(type->IsFunction()); | |
965 return static_cast<FunctionType*>(type); | |
966 } | |
967 }; | |
968 | |
969 | |
970 // ----------------------------------------------------------------------------- | |
971 // Tuple types. | |
972 | |
973 template <class Config> | |
974 class TypeImpl<Config>::TupleType : public StructuralType { | |
975 public: | |
976 int Arity() { return this->Length(); } | |
977 TypeHandle Element(int i) { return this->Get(i); } | |
978 | |
979 void InitElement(int i, TypeHandle type) { this->Set(i, type); } | |
980 | |
981 static TupleHandle New(int length, Region* region) { | |
982 TupleHandle type = Config::template cast<TupleType>( | |
983 StructuralType::New(StructuralType::kTupleTag, length, region)); | |
984 return type; | |
985 } | |
986 | |
987 static TupleType* cast(TypeImpl* type) { | |
988 DCHECK(type->IsTuple()); | |
989 return static_cast<TupleType*>(type); | |
990 } | |
991 }; | |
992 | |
993 | |
994 // ----------------------------------------------------------------------------- | |
995 // Type iterators. | |
996 | |
997 template<class Config> template<class T> | |
998 class TypeImpl<Config>::Iterator { | |
999 public: | |
1000 bool Done() const { return index_ < 0; } | |
1001 i::Handle<T> Current(); | |
1002 void Advance(); | |
1003 | |
1004 private: | |
1005 template<class> friend class TypeImpl; | |
1006 | |
1007 Iterator() : index_(-1) {} | |
1008 explicit Iterator(TypeHandle type) : type_(type), index_(-1) { | |
1009 Advance(); | |
1010 } | |
1011 | |
1012 inline bool matches(TypeHandle type); | |
1013 inline TypeHandle get_type(); | |
1014 | |
1015 TypeHandle type_; | |
1016 int index_; | |
1017 }; | |
1018 | |
1019 | |
1020 // ----------------------------------------------------------------------------- | |
1021 // Zone-allocated types; they are either (odd) integers to represent bitsets, or | |
1022 // (even) pointers to structures for everything else. | |
1023 | |
1024 struct ZoneTypeConfig { | |
1025 typedef TypeImpl<ZoneTypeConfig> Type; | |
1026 class Base {}; | |
1027 typedef void* Struct; | |
1028 // Hack: the Struct and Range types can be aliased in memory, the first | |
1029 // pointer word of each both must be the tag (kRangeStructTag for Range, | |
1030 // anything else for Struct) so that we can differentiate them. | |
1031 struct Range { | |
1032 void* tag; | |
1033 int bitset; | |
1034 double limits[2]; | |
1035 }; | |
1036 typedef i::Zone Region; | |
1037 template<class T> struct Handle { typedef T* type; }; | |
1038 | |
1039 static const int kRangeStructTag = 0x1000; | |
1040 | |
1041 template<class T> static inline T* null_handle() { return nullptr; } | |
1042 template<class T> static inline T* handle(T* type); | |
1043 template<class T> static inline T* cast(Type* type); | |
1044 | |
1045 static inline bool is_bitset(Type* type); | |
1046 static inline bool is_class(Type* type); | |
1047 static inline bool is_struct(Type* type, int tag); | |
1048 static inline bool is_range(Type* type); | |
1049 | |
1050 static inline Type::bitset as_bitset(Type* type); | |
1051 static inline i::Handle<i::Map> as_class(Type* type); | |
1052 static inline Struct* as_struct(Type* type); | |
1053 static inline Range* as_range(Type* type); | |
1054 | |
1055 static inline Type* from_bitset(Type::bitset); | |
1056 static inline Type* from_bitset(Type::bitset, Zone* zone); | |
1057 static inline Type* from_class(i::Handle<i::Map> map, Zone* zone); | |
1058 static inline Type* from_struct(Struct* structured); | |
1059 static inline Type* from_range(Range* range); | |
1060 | |
1061 static inline Struct* struct_create(int tag, int length, Zone* zone); | |
1062 static inline void struct_shrink(Struct* structure, int length); | |
1063 static inline int struct_tag(Struct* structure); | |
1064 static inline int struct_length(Struct* structure); | |
1065 static inline Type* struct_get(Struct* structure, int i); | |
1066 static inline void struct_set(Struct* structure, int i, Type* type); | |
1067 template<class V> | |
1068 static inline i::Handle<V> struct_get_value(Struct* structure, int i); | |
1069 template<class V> static inline void struct_set_value( | |
1070 Struct* structure, int i, i::Handle<V> x); | |
1071 | |
1072 static inline Range* range_create(Zone* zone); | |
1073 static inline int range_get_bitset(Range* range); | |
1074 static inline void range_set_bitset(Range* range, int); | |
1075 static inline double range_get_double(Range*, int index); | |
1076 static inline void range_set_double(Range*, int index, double value, Zone*); | |
1077 }; | |
1078 | |
1079 typedef TypeImpl<ZoneTypeConfig> Type; | |
1080 | |
1081 // ----------------------------------------------------------------------------- | 915 // ----------------------------------------------------------------------------- |
1082 // Type bounds. A simple struct to represent a pair of lower/upper types. | 916 // Type bounds. A simple struct to represent a pair of lower/upper types. |
1083 | 917 |
1084 template<class Config> | 918 struct Bounds { |
1085 struct BoundsImpl { | 919 Type* lower; |
1086 typedef TypeImpl<Config> Type; | 920 Type* upper; |
1087 typedef typename Type::TypeHandle TypeHandle; | 921 |
1088 typedef typename Type::Region Region; | 922 Bounds() |
1089 | 923 : // Make sure accessing uninitialized bounds crashes big-time. |
1090 TypeHandle lower; | 924 lower(nullptr), |
1091 TypeHandle upper; | 925 upper(nullptr) {} |
1092 | 926 explicit Bounds(Type* t) : lower(t), upper(t) {} |
1093 BoundsImpl() : // Make sure accessing uninitialized bounds crashes big-time. | 927 Bounds(Type* l, Type* u) : lower(l), upper(u) { DCHECK(lower->Is(upper)); } |
1094 lower(Config::template null_handle<Type>()), | |
1095 upper(Config::template null_handle<Type>()) {} | |
1096 explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {} | |
1097 BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) { | |
1098 DCHECK(lower->Is(upper)); | |
1099 } | |
1100 | 928 |
1101 // Unrestricted bounds. | 929 // Unrestricted bounds. |
1102 static BoundsImpl Unbounded() { | 930 static Bounds Unbounded() { return Bounds(Type::None(), Type::Any()); } |
1103 return BoundsImpl(Type::None(), Type::Any()); | |
1104 } | |
1105 | 931 |
1106 // Meet: both b1 and b2 are known to hold. | 932 // Meet: both b1 and b2 are known to hold. |
1107 static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) { | 933 static Bounds Both(Bounds b1, Bounds b2, Zone* zone) { |
1108 TypeHandle lower = Type::Union(b1.lower, b2.lower, region); | 934 Type* lower = Type::Union(b1.lower, b2.lower, zone); |
1109 TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region); | 935 Type* upper = Type::Intersect(b1.upper, b2.upper, zone); |
1110 // Lower bounds are considered approximate, correct as necessary. | 936 // Lower bounds are considered approximate, correct as necessary. |
1111 if (!lower->Is(upper)) lower = upper; | 937 if (!lower->Is(upper)) lower = upper; |
1112 return BoundsImpl(lower, upper); | 938 return Bounds(lower, upper); |
1113 } | 939 } |
1114 | 940 |
1115 // Join: either b1 or b2 is known to hold. | 941 // Join: either b1 or b2 is known to hold. |
1116 static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) { | 942 static Bounds Either(Bounds b1, Bounds b2, Zone* zone) { |
1117 TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region); | 943 Type* lower = Type::Intersect(b1.lower, b2.lower, zone); |
1118 TypeHandle upper = Type::Union(b1.upper, b2.upper, region); | 944 Type* upper = Type::Union(b1.upper, b2.upper, zone); |
1119 return BoundsImpl(lower, upper); | 945 return Bounds(lower, upper); |
1120 } | 946 } |
1121 | 947 |
1122 static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) { | 948 static Bounds NarrowLower(Bounds b, Type* t, Zone* zone) { |
1123 TypeHandle lower = Type::Union(b.lower, t, region); | 949 Type* lower = Type::Union(b.lower, t, zone); |
1124 // Lower bounds are considered approximate, correct as necessary. | 950 // Lower bounds are considered approximate, correct as necessary. |
1125 if (!lower->Is(b.upper)) lower = b.upper; | 951 if (!lower->Is(b.upper)) lower = b.upper; |
1126 return BoundsImpl(lower, b.upper); | 952 return Bounds(lower, b.upper); |
1127 } | 953 } |
1128 static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region* region) { | 954 static Bounds NarrowUpper(Bounds b, Type* t, Zone* zone) { |
1129 TypeHandle lower = b.lower; | 955 Type* lower = b.lower; |
1130 TypeHandle upper = Type::Intersect(b.upper, t, region); | 956 Type* upper = Type::Intersect(b.upper, t, zone); |
1131 // Lower bounds are considered approximate, correct as necessary. | 957 // Lower bounds are considered approximate, correct as necessary. |
1132 if (!lower->Is(upper)) lower = upper; | 958 if (!lower->Is(upper)) lower = upper; |
1133 return BoundsImpl(lower, upper); | 959 return Bounds(lower, upper); |
1134 } | 960 } |
1135 | 961 |
1136 bool Narrows(BoundsImpl that) { | 962 bool Narrows(Bounds that) { |
1137 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 963 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
1138 } | 964 } |
1139 }; | 965 }; |
1140 | 966 |
1141 typedef BoundsImpl<ZoneTypeConfig> Bounds; | |
1142 | |
1143 class FieldType : public Object { | 967 class FieldType : public Object { |
1144 public: | 968 public: |
1145 static FieldType* None(); | 969 static FieldType* None(); |
1146 static FieldType* Any(); | 970 static FieldType* Any(); |
1147 static Handle<FieldType> None(Isolate* isolate); | 971 static Handle<FieldType> None(Isolate* isolate); |
1148 static Handle<FieldType> Any(Isolate* isolate); | 972 static Handle<FieldType> Any(Isolate* isolate); |
1149 static FieldType* Class(i::Map* map); | 973 static FieldType* Class(i::Map* map); |
1150 static Handle<FieldType> Class(i::Handle<i::Map> map, Isolate* isolate); | 974 static Handle<FieldType> Class(i::Handle<i::Map> map, Isolate* isolate); |
1151 static FieldType* cast(Object* object); | 975 static FieldType* cast(Object* object); |
1152 | 976 |
1153 bool NowContains(Object* value); | 977 bool NowContains(Object* value); |
1154 bool NowContains(Handle<Object> value); | 978 bool NowContains(Handle<Object> value); |
1155 bool IsClass(); | 979 bool IsClass(); |
1156 Handle<i::Map> AsClass(); | 980 Handle<i::Map> AsClass(); |
1157 bool IsNone() { return this == None(); } | 981 bool IsNone() { return this == None(); } |
1158 bool IsAny() { return this == Any(); } | 982 bool IsAny() { return this == Any(); } |
1159 bool NowStable(); | 983 bool NowStable(); |
1160 bool NowIs(FieldType* other); | 984 bool NowIs(FieldType* other); |
1161 bool NowIs(Handle<FieldType> other); | 985 bool NowIs(Handle<FieldType> other); |
1162 Type* Convert(Zone* zone); | 986 Type* Convert(Zone* zone); |
1163 | 987 |
1164 void PrintTo(std::ostream& os); | 988 void PrintTo(std::ostream& os); |
1165 }; | 989 }; |
1166 | 990 |
1167 } // namespace internal | 991 } // namespace internal |
1168 } // namespace v8 | 992 } // namespace v8 |
1169 | 993 |
1170 #endif // V8_TYPES_H_ | 994 #endif // V8_TYPES_H_ |
OLD | NEW |