Chromium Code Reviews| 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 "handles.h" | 8 #include "handles.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| 11 namespace internal { | 11 namespace internal { |
| 12 | 12 |
| 13 // SUMMARY | |
| 14 // | |
| 13 // A simple type system for compiler-internal use. It is based entirely on | 15 // A simple type system for compiler-internal use. It is based entirely on |
| 14 // union types, and all subtyping hence amounts to set inclusion. Besides the | 16 // union types, and all subtyping hence amounts to set inclusion. Besides the |
| 15 // obvious primitive types and some predefined unions, the type language also | 17 // obvious primitive types and some predefined unions, the type language also |
| 16 // can express class types (a.k.a. specific maps) and singleton types (i.e., | 18 // can express class types (a.k.a. specific maps) and singleton types (i.e., |
| 17 // concrete constants). | 19 // concrete constants). |
| 18 // | 20 // |
| 19 // Types consist of two dimensions: semantic (value range) and representation. | 21 // Types consist of two dimensions: semantic (value range) and representation. |
| 20 // Both are related through subtyping. | 22 // Both are related through subtyping. |
| 21 // | 23 // |
| 24 // SEMANTIC DIMENSION | |
| 25 // | |
| 22 // The following equations and inequations hold for the semantic axis: | 26 // The following equations and inequations hold for the semantic axis: |
| 23 // | 27 // |
| 24 // None <= T | 28 // None <= T |
| 25 // T <= Any | 29 // T <= Any |
| 26 // | 30 // |
| 27 // Number = Signed32 \/ Unsigned32 \/ Double | 31 // Number = Signed32 \/ Unsigned32 \/ Double |
| 28 // Smi <= Signed32 | 32 // Smi <= Signed32 |
| 29 // Name = String \/ Symbol | 33 // Name = String \/ Symbol |
| 30 // UniqueName = InternalizedString \/ Symbol | 34 // UniqueName = InternalizedString \/ Symbol |
| 31 // InternalizedString < String | 35 // InternalizedString < String |
| 32 // | 36 // |
| 33 // Receiver = Object \/ Proxy | 37 // Receiver = Object \/ Proxy |
| 34 // Array < Object | 38 // Array < Object |
| 35 // Function < Object | 39 // Function < Object |
| 36 // RegExp < Object | 40 // RegExp < Object |
| 37 // Undetectable < Object | 41 // Undetectable < Object |
| 38 // Detectable = Receiver \/ Number \/ Name - Undetectable | 42 // Detectable = Receiver \/ Number \/ Name - Undetectable |
| 39 // | 43 // |
| 40 // Class(map) < T iff instance_type(map) < T | 44 // Class(map) < T iff instance_type(map) < T |
| 41 // Constant(x) < T iff instance_type(map(x)) < T | 45 // Constant(x) < T iff instance_type(map(x)) < T |
| 42 // | 46 // |
| 43 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can | 47 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can |
| 44 // change! (Its instance type cannot, however.) | 48 // change! (Its instance type cannot, however.) |
| 45 // TODO(rossberg): the latter is not currently true for proxies, because of fix, | 49 // TODO(rossberg): the latter is not currently true for proxies, because of fix, |
| 46 // but will hold once we implement direct proxies. | 50 // but will hold once we implement direct proxies. |
| 47 // | 51 // |
| 52 // REPRESENTATIONAL DIMENSION | |
| 53 // | |
| 48 // For the representation axis, the following holds: | 54 // For the representation axis, the following holds: |
| 49 // | 55 // |
| 50 // None <= R | 56 // None <= R |
| 51 // R <= Any | 57 // R <= Any |
| 52 // | 58 // |
| 53 // UntaggedInt <= UntaggedInt8 \/ UntaggedInt16 \/ UntaggedInt32) | 59 // UntaggedInt <= UntaggedInt8 \/ UntaggedInt16 \/ UntaggedInt32) |
| 54 // UntaggedFloat <= UntaggedFloat32 \/ UntaggedFloat64 | 60 // UntaggedFloat <= UntaggedFloat32 \/ UntaggedFloat64 |
| 55 // UntaggedNumber <= UntaggedInt \/ UntaggedFloat | 61 // UntaggedNumber <= UntaggedInt \/ UntaggedFloat |
| 56 // Untagged <= UntaggedNumber \/ UntaggedPtr | 62 // Untagged <= UntaggedNumber \/ UntaggedPtr |
| 57 // Tagged <= TaggedInt \/ TaggedPtr | 63 // Tagged <= TaggedInt \/ TaggedPtr |
| 58 // | 64 // |
| 59 // Subtyping relates the two dimensions, for example: | 65 // Subtyping relates the two dimensions, for example: |
| 60 // | 66 // |
| 61 // Number <= Tagged \/ UntaggedNumber | 67 // Number <= Tagged \/ UntaggedNumber |
| 62 // Object <= TaggedPtr \/ UntaggedPtr | 68 // Object <= TaggedPtr \/ UntaggedPtr |
| 63 // | 69 // |
| 64 // That holds because the semantic type constructors defined by the API create | 70 // That holds because the semantic type constructors defined by the API create |
| 65 // types that allow for all possible representations, and dually, the ones for | 71 // types that allow for all possible representations, and dually, the ones for |
| 66 // representation types initially include all semantic ranges. Representations | 72 // representation types initially include all semantic ranges. Representations |
| 67 // can then e.g. be narrowed for a given semantic type using intersection: | 73 // can then e.g. be narrowed for a given semantic type using intersection: |
| 68 // | 74 // |
| 69 // SignedSmall /\ TaggedInt (a 'smi') | 75 // SignedSmall /\ TaggedInt (a 'smi') |
| 70 // Number /\ TaggedPtr (a heap number) | 76 // Number /\ TaggedPtr (a heap number) |
| 71 // | 77 // |
| 78 // PREDICATES | |
| 79 // | |
| 72 // There are two main functions for testing types: | 80 // There are two main functions for testing types: |
| 73 // | 81 // |
| 74 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) | 82 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) |
| 75 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) | 83 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) |
| 76 // | 84 // |
| 77 // Typically, the former is to be used to select representations (e.g., via | 85 // Typically, the former is to be used to select representations (e.g., via |
| 78 // T->Is(SignedSmall())), and the latter to check whether a specific case needs | 86 // T->Is(SignedSmall())), and the latter to check whether a specific case needs |
| 79 // handling (e.g., via T->Maybe(Number())). | 87 // handling (e.g., via T->Maybe(Number())). |
| 80 // | 88 // |
| 81 // There is no functionality to discover whether a type is a leaf in the | 89 // There is no functionality to discover whether a type is a leaf in the |
| 82 // lattice. That is intentional. It should always be possible to refine the | 90 // lattice. That is intentional. It should always be possible to refine the |
| 83 // lattice (e.g., splitting up number types further) without invalidating any | 91 // lattice (e.g., splitting up number types further) without invalidating any |
| 84 // existing assumptions or tests. | 92 // existing assumptions or tests. |
| 85 // Consequently, do not use pointer equality for type tests, always use Is! | 93 // Consequently, do not use pointer equality for type tests, always use Is! |
| 86 // | 94 // |
| 95 // PROPERTIES | |
| 96 // | |
| 97 // Various formal properties hold for constructors, operators, and predicates | |
| 98 // over types. For example, constructors are injective, subtyping is a partial | |
| 99 // order, and union and intersection satisfy the usual algebraic properties. | |
| 100 // | |
| 101 // See test/cctest/test-typing.cc for a comprehensive executable specification, | |
|
Benedikt Meurer
2014/04/10 10:54:50
Nit: test-types.cc
| |
| 102 // especially with respect to the more exotic temporal constructors and | |
| 103 // predicates (prefixed 'Now'). | |
| 104 // | |
| 105 // IMPLEMENTATION | |
| 106 // | |
| 87 // Internally, all 'primitive' types, and their unions, are represented as | 107 // Internally, all 'primitive' types, and their unions, are represented as |
| 88 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or | 108 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or |
| 89 // unions containing Class'es or Constant's, currently require allocation. | 109 // unions containing Class'es or Constant's, currently require allocation. |
| 90 // Note that the bitset representation is closed under both Union and Intersect. | 110 // Note that the bitset representation is closed under both Union and Intersect. |
| 91 // | 111 // |
| 92 // There are two type representations, using different allocation: | 112 // There are two type representations, using different allocation: |
| 93 // | 113 // |
| 94 // - class Type (zone-allocated, for compiler and concurrent compilation) | 114 // - class Type (zone-allocated, for compiler and concurrent compilation) |
| 95 // - class HeapType (heap-allocated, for persistent types) | 115 // - class HeapType (heap-allocated, for persistent types) |
| 96 // | 116 // |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 bool Narrows(BoundsImpl that) { | 521 bool Narrows(BoundsImpl that) { |
| 502 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 522 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
| 503 } | 523 } |
| 504 }; | 524 }; |
| 505 | 525 |
| 506 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 526 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
| 507 | 527 |
| 508 } } // namespace v8::internal | 528 } } // namespace v8::internal |
| 509 | 529 |
| 510 #endif // V8_TYPES_H_ | 530 #endif // V8_TYPES_H_ |
| OLD | NEW |