LCOV - code coverage report
Current view: top level - src/compiler - representation-change.h (source / functions) Hit Total Coverage
Test: app.info Lines: 30 30 100.0 %
Date: 2019-01-20 Functions: 2 2 100.0 %

          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             : #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
       6             : #define V8_COMPILER_REPRESENTATION_CHANGE_H_
       7             : 
       8             : #include "src/compiler/js-graph.h"
       9             : #include "src/compiler/simplified-operator.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : namespace compiler {
      14             : 
      15             : // Foward declarations.
      16             : class TypeCache;
      17             : 
      18             : enum IdentifyZeros { kIdentifyZeros, kDistinguishZeros };
      19             : 
      20             : class Truncation final {
      21             :  public:
      22             :   // Constructors.
      23             :   static Truncation None() {
      24             :     return Truncation(TruncationKind::kNone, kIdentifyZeros);
      25             :   }
      26             :   static Truncation Bool() {
      27             :     return Truncation(TruncationKind::kBool, kIdentifyZeros);
      28             :   }
      29             :   static Truncation Word32() {
      30             :     return Truncation(TruncationKind::kWord32, kIdentifyZeros);
      31             :   }
      32             :   static Truncation Float64(IdentifyZeros identify_zeros = kDistinguishZeros) {
      33             :     return Truncation(TruncationKind::kFloat64, identify_zeros);
      34             :   }
      35             :   static Truncation Any(IdentifyZeros identify_zeros = kDistinguishZeros) {
      36             :     return Truncation(TruncationKind::kAny, identify_zeros);
      37             :   }
      38             : 
      39    88835260 :   static Truncation Generalize(Truncation t1, Truncation t2) {
      40             :     return Truncation(
      41             :         Generalize(t1.kind(), t2.kind()),
      42    88835260 :         GeneralizeIdentifyZeros(t1.identify_zeros(), t2.identify_zeros()));
      43             :   }
      44             : 
      45             :   // Queries.
      46             :   bool IsUnused() const { return kind_ == TruncationKind::kNone; }
      47             :   bool IsUsedAsBool() const {
      48      133292 :     return LessGeneral(kind_, TruncationKind::kBool);
      49             :   }
      50             :   bool IsUsedAsWord32() const {
      51     1545673 :     return LessGeneral(kind_, TruncationKind::kWord32);
      52             :   }
      53             :   bool IsUsedAsFloat64() const {
      54      769916 :     return LessGeneral(kind_, TruncationKind::kFloat64);
      55             :   }
      56             :   bool IdentifiesUndefinedAndZero() {
      57             :     return LessGeneral(kind_, TruncationKind::kWord32) ||
      58             :            LessGeneral(kind_, TruncationKind::kBool);
      59             :   }
      60        5975 :   bool IdentifiesZeroAndMinusZero() const {
      61       77883 :     return identify_zeros() == kIdentifyZeros;
      62             :   }
      63             : 
      64             :   // Operators.
      65   159028516 :   bool operator==(Truncation other) const {
      66   159028516 :     return kind() == other.kind() && identify_zeros() == other.identify_zeros();
      67             :   }
      68    88834375 :   bool operator!=(Truncation other) const { return !(*this == other); }
      69             : 
      70             :   // Debug utilities.
      71             :   const char* description() const;
      72          21 :   bool IsLessGeneralThan(Truncation other) {
      73          21 :     return LessGeneral(kind(), other.kind()) &&
      74          14 :            LessGeneralIdentifyZeros(identify_zeros(), other.identify_zeros());
      75             :   }
      76             : 
      77             :   IdentifyZeros identify_zeros() const { return identify_zeros_; }
      78             : 
      79             :  private:
      80             :   enum class TruncationKind : uint8_t {
      81             :     kNone,
      82             :     kBool,
      83             :     kWord32,
      84             :     kFloat64,
      85             :     kAny
      86             :   };
      87             : 
      88             :   explicit Truncation(TruncationKind kind, IdentifyZeros identify_zeros)
      89             :       : kind_(kind), identify_zeros_(identify_zeros) {
      90             :     DCHECK(kind == TruncationKind::kAny || kind == TruncationKind::kFloat64 ||
      91             :            identify_zeros == kIdentifyZeros);
      92             :   }
      93             :   TruncationKind kind() const { return kind_; }
      94             : 
      95             :   TruncationKind kind_;
      96             :   IdentifyZeros identify_zeros_;
      97             : 
      98             :   static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2);
      99             :   static IdentifyZeros GeneralizeIdentifyZeros(IdentifyZeros i1,
     100             :                                                IdentifyZeros i2);
     101             :   static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
     102             :   static bool LessGeneralIdentifyZeros(IdentifyZeros u1, IdentifyZeros u2);
     103             : };
     104             : 
     105             : enum class TypeCheckKind : uint8_t {
     106             :   kNone,
     107             :   kSignedSmall,
     108             :   kSigned32,
     109             :   kSigned64,
     110             :   kNumber,
     111             :   kNumberOrOddball,
     112             :   kHeapObject
     113             : };
     114             : 
     115             : inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) {
     116             :   switch (type_check) {
     117             :     case TypeCheckKind::kNone:
     118             :       return os << "None";
     119             :     case TypeCheckKind::kSignedSmall:
     120             :       return os << "SignedSmall";
     121             :     case TypeCheckKind::kSigned32:
     122             :       return os << "Signed32";
     123             :     case TypeCheckKind::kSigned64:
     124             :       return os << "Signed64";
     125             :     case TypeCheckKind::kNumber:
     126             :       return os << "Number";
     127             :     case TypeCheckKind::kNumberOrOddball:
     128             :       return os << "NumberOrOddball";
     129             :     case TypeCheckKind::kHeapObject:
     130             :       return os << "HeapObject";
     131             :   }
     132             :   UNREACHABLE();
     133             : }
     134             : 
     135             : // The {UseInfo} class is used to describe a use of an input of a node.
     136             : //
     137             : // This information is used in two different ways, based on the phase:
     138             : //
     139             : // 1. During propagation, the use info is used to inform the input node
     140             : //    about what part of the input is used (we call this truncation) and what
     141             : //    is the preferred representation. For conversions that will require
     142             : //    checks, we also keep track of whether a minus zero check is needed.
     143             : //
     144             : // 2. During lowering, the use info is used to properly convert the input
     145             : //    to the preferred representation. The preferred representation might be
     146             : //    insufficient to do the conversion (e.g. word32->float64 conv), so we also
     147             : //    need the signedness information to produce the correct value.
     148             : //    Additionally, use info may contain {CheckParameters} which contains
     149             : //    information for the deoptimizer such as a CallIC on which speculation
     150             : //    should be disallowed if the check fails.
     151             : class UseInfo {
     152             :  public:
     153             :   UseInfo(MachineRepresentation representation, Truncation truncation,
     154             :           TypeCheckKind type_check = TypeCheckKind::kNone,
     155             :           const VectorSlotPair& feedback = VectorSlotPair())
     156             :       : representation_(representation),
     157             :         truncation_(truncation),
     158             :         type_check_(type_check),
     159   239752304 :         feedback_(feedback) {}
     160             :   static UseInfo TruncatingWord32() {
     161     7911856 :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
     162             :   }
     163             :   static UseInfo Word64() {
     164      167286 :     return UseInfo(MachineRepresentation::kWord64, Truncation::Any());
     165             :   }
     166             :   static UseInfo Word() {
     167     1655366 :     return UseInfo(MachineType::PointerRepresentation(), Truncation::Any());
     168             :   }
     169             :   static UseInfo Bool() {
     170     4025603 :     return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
     171             :   }
     172             :   static UseInfo Float32() {
     173        5152 :     return UseInfo(MachineRepresentation::kFloat32, Truncation::Any());
     174             :   }
     175             :   static UseInfo TruncatingFloat64(
     176             :       IdentifyZeros identify_zeros = kDistinguishZeros) {
     177             :     return UseInfo(MachineRepresentation::kFloat64,
     178     1985643 :                    Truncation::Float64(identify_zeros));
     179             :   }
     180             :   static UseInfo AnyTagged() {
     181   258764402 :     return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
     182             :   }
     183             :   static UseInfo TaggedSigned() {
     184     1643335 :     return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any());
     185             :   }
     186             :   static UseInfo TaggedPointer() {
     187             :     return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any());
     188             :   }
     189             : 
     190             :   // Possibly deoptimizing conversions.
     191             :   static UseInfo CheckedHeapObjectAsTaggedPointer() {
     192             :     return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
     193      250780 :                    TypeCheckKind::kHeapObject);
     194             :   }
     195             :   static UseInfo CheckedSignedSmallAsTaggedSigned(
     196             :       const VectorSlotPair& feedback,
     197             :       IdentifyZeros identify_zeros = kDistinguishZeros) {
     198             :     return UseInfo(MachineRepresentation::kTaggedSigned,
     199             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
     200             :                    feedback);
     201             :   }
     202             :   static UseInfo CheckedSignedSmallAsWord32(IdentifyZeros identify_zeros,
     203             :                                             const VectorSlotPair& feedback) {
     204             :     return UseInfo(MachineRepresentation::kWord32,
     205             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
     206             :                    feedback);
     207             :   }
     208             :   static UseInfo CheckedSigned32AsWord32(IdentifyZeros identify_zeros,
     209             :                                          const VectorSlotPair& feedback) {
     210             :     return UseInfo(MachineRepresentation::kWord32,
     211             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSigned32,
     212             :                    feedback);
     213             :   }
     214             :   static UseInfo CheckedSigned64AsWord64(IdentifyZeros identify_zeros,
     215             :                                          const VectorSlotPair& feedback) {
     216             :     return UseInfo(MachineRepresentation::kWord64,
     217             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSigned64,
     218             :                    feedback);
     219             :   }
     220             :   static UseInfo CheckedNumberAsFloat64(IdentifyZeros identify_zeros,
     221             :                                         const VectorSlotPair& feedback) {
     222             :     return UseInfo(MachineRepresentation::kFloat64,
     223             :                    Truncation::Any(identify_zeros), TypeCheckKind::kNumber,
     224             :                    feedback);
     225             :   }
     226             :   static UseInfo CheckedNumberAsWord32(const VectorSlotPair& feedback) {
     227             :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
     228             :                    TypeCheckKind::kNumber, feedback);
     229             :   }
     230             :   static UseInfo CheckedNumberOrOddballAsFloat64(
     231             :       IdentifyZeros identify_zeros, const VectorSlotPair& feedback) {
     232             :     return UseInfo(MachineRepresentation::kFloat64,
     233             :                    Truncation::Any(identify_zeros),
     234             :                    TypeCheckKind::kNumberOrOddball, feedback);
     235             :   }
     236             :   static UseInfo CheckedNumberOrOddballAsWord32(
     237             :       const VectorSlotPair& feedback) {
     238             :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
     239             :                    TypeCheckKind::kNumberOrOddball, feedback);
     240             :   }
     241             : 
     242             :   // Undetermined representation.
     243             :   static UseInfo Any() {
     244    29638429 :     return UseInfo(MachineRepresentation::kNone, Truncation::Any());
     245             :   }
     246             :   static UseInfo AnyTruncatingToBool() {
     247       13478 :     return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
     248             :   }
     249             : 
     250             :   // Value not used.
     251             :   static UseInfo None() {
     252   167357591 :     return UseInfo(MachineRepresentation::kNone, Truncation::None());
     253             :   }
     254             : 
     255             :   MachineRepresentation representation() const { return representation_; }
     256             :   Truncation truncation() const { return truncation_; }
     257             :   TypeCheckKind type_check() const { return type_check_; }
     258             :   CheckForMinusZeroMode minus_zero_check() const {
     259             :     return truncation().IdentifiesZeroAndMinusZero()
     260             :                ? CheckForMinusZeroMode::kDontCheckForMinusZero
     261        5091 :                : CheckForMinusZeroMode::kCheckForMinusZero;
     262             :   }
     263             :   const VectorSlotPair& feedback() const { return feedback_; }
     264             : 
     265             :  private:
     266             :   MachineRepresentation representation_;
     267             :   Truncation truncation_;
     268             :   TypeCheckKind type_check_;
     269             :   VectorSlotPair feedback_;
     270             : };
     271             : 
     272             : // Contains logic related to changing the representation of values for constants
     273             : // and other nodes, as well as lowering Simplified->Machine operators.
     274             : // Eagerly folds any representation changes for constants.
     275             : class RepresentationChanger final {
     276             :  public:
     277             :   RepresentationChanger(JSGraph* jsgraph, Isolate* isolate);
     278             : 
     279             :   // Changes representation from {output_type} to {use_rep}. The {truncation}
     280             :   // parameter is only used for sanity checking - if the changer cannot figure
     281             :   // out signedness for the word32->float64 conversion, then we check that the
     282             :   // uses truncate to word32 (so they do not care about signedness).
     283             :   Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
     284             :                              Type output_type, Node* use_node,
     285             :                              UseInfo use_info);
     286             :   const Operator* Int32OperatorFor(IrOpcode::Value opcode);
     287             :   const Operator* Int32OverflowOperatorFor(IrOpcode::Value opcode);
     288             :   const Operator* Int64OperatorFor(IrOpcode::Value opcode);
     289             :   const Operator* TaggedSignedOperatorFor(IrOpcode::Value opcode);
     290             :   const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
     291             :   const Operator* Uint32OverflowOperatorFor(IrOpcode::Value opcode);
     292             :   const Operator* Float64OperatorFor(IrOpcode::Value opcode);
     293             : 
     294             :   MachineType TypeForBasePointer(const FieldAccess& access) {
     295             :     return access.tag() != 0 ? MachineType::AnyTagged()
     296             :                              : MachineType::Pointer();
     297             :   }
     298             : 
     299             :   MachineType TypeForBasePointer(const ElementAccess& access) {
     300             :     return access.tag() != 0 ? MachineType::AnyTagged()
     301             :                              : MachineType::Pointer();
     302             :   }
     303             : 
     304             :  private:
     305             :   TypeCache const* cache_;
     306             :   JSGraph* jsgraph_;
     307             :   Isolate* isolate_;
     308             : 
     309             :   friend class RepresentationChangerTester;  // accesses the below fields.
     310             : 
     311             :   bool testing_type_errors_;  // If {true}, don't abort on a type error.
     312             :   bool type_error_;           // Set when a type error is detected.
     313             : 
     314             :   Node* GetTaggedSignedRepresentationFor(Node* node,
     315             :                                          MachineRepresentation output_rep,
     316             :                                          Type output_type, Node* use_node,
     317             :                                          UseInfo use_info);
     318             :   Node* GetTaggedPointerRepresentationFor(Node* node,
     319             :                                           MachineRepresentation output_rep,
     320             :                                           Type output_type, Node* use_node,
     321             :                                           UseInfo use_info);
     322             :   Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep,
     323             :                                    Type output_type, Truncation truncation);
     324             :   Node* GetFloat32RepresentationFor(Node* node,
     325             :                                     MachineRepresentation output_rep,
     326             :                                     Type output_type, Truncation truncation);
     327             :   Node* GetFloat64RepresentationFor(Node* node,
     328             :                                     MachineRepresentation output_rep,
     329             :                                     Type output_type, Node* use_node,
     330             :                                     UseInfo use_info);
     331             :   Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
     332             :                                    Type output_type, Node* use_node,
     333             :                                    UseInfo use_info);
     334             :   Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
     335             :                                 Type output_type);
     336             :   Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
     337             :                                    Type output_type, Node* use_node,
     338             :                                    UseInfo use_info);
     339             :   Node* TypeError(Node* node, MachineRepresentation output_rep,
     340             :                   Type output_type, MachineRepresentation use);
     341             :   Node* MakeTruncatedInt32Constant(double value);
     342             :   Node* InsertChangeBitToTagged(Node* node);
     343             :   Node* InsertChangeFloat32ToFloat64(Node* node);
     344             :   Node* InsertChangeFloat64ToInt32(Node* node);
     345             :   Node* InsertChangeFloat64ToUint32(Node* node);
     346             :   Node* InsertChangeInt32ToFloat64(Node* node);
     347             :   Node* InsertChangeTaggedSignedToInt32(Node* node);
     348             :   Node* InsertChangeTaggedToFloat64(Node* node);
     349             :   Node* InsertChangeUint32ToFloat64(Node* node);
     350             :   Node* InsertConversion(Node* node, const Operator* op, Node* use_node);
     351             :   Node* InsertTruncateInt64ToInt32(Node* node);
     352             :   Node* InsertUnconditionalDeopt(Node* node, DeoptimizeReason reason);
     353             : 
     354             :   JSGraph* jsgraph() const { return jsgraph_; }
     355             :   Isolate* isolate() const { return isolate_; }
     356      159694 :   Factory* factory() const { return isolate()->factory(); }
     357      874241 :   SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
     358      537599 :   MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
     359             : };
     360             : 
     361             : }  // namespace compiler
     362             : }  // namespace internal
     363             : }  // namespace v8
     364             : 
     365             : #endif  // V8_COMPILER_REPRESENTATION_CHANGE_H_

Generated by: LCOV version 1.10