LCOV - code coverage report
Current view: top level - src/compiler - representation-change.h (source / functions) Hit Total Coverage
Test: app.info Lines: 19 20 95.0 %
Date: 2019-03-21 Functions: 0 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             :   static Truncation Generalize(Truncation t1, Truncation t2) {
      40             :     return Truncation(
      41             :         Generalize(t1.kind(), t2.kind()),
      42   105388361 :         GeneralizeIdentifyZeros(t1.identify_zeros(), t2.identify_zeros()));
      43             :   }
      44             : 
      45             :   // Queries.
      46             :   bool IsUnused() const { return kind_ == TruncationKind::kNone; }
      47             :   bool IsUsedAsBool() const {
      48      151296 :     return LessGeneral(kind_, TruncationKind::kBool);
      49             :   }
      50             :   bool IsUsedAsWord32() const {
      51     1397582 :     return LessGeneral(kind_, TruncationKind::kWord32);
      52             :   }
      53             :   bool IsUsedAsFloat64() const {
      54      783186 :     return LessGeneral(kind_, TruncationKind::kFloat64);
      55             :   }
      56             :   bool IdentifiesUndefinedAndZero() {
      57             :     return LessGeneral(kind_, TruncationKind::kWord32) ||
      58             :            LessGeneral(kind_, TruncationKind::kBool);
      59             :   }
      60             :   bool IdentifiesZeroAndMinusZero() const {
      61             :     return identify_zeros() == kIdentifyZeros;
      62             :   }
      63             : 
      64             :   // Operators.
      65             :   bool operator==(Truncation other) const {
      66   105385066 :     return kind() == other.kind() && identify_zeros() == other.identify_zeros();
      67             :   }
      68   105385066 :   bool operator!=(Truncation other) const { return !(*this == other); }
      69             : 
      70             :   // Debug utilities.
      71             :   const char* description() const;
      72             :   bool IsLessGeneralThan(Truncation other) {
      73           0 :     return LessGeneral(kind(), other.kind()) &&
      74             :            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   284918304 :         feedback_(feedback) {}
     160             :   static UseInfo TruncatingWord32() {
     161     6608393 :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
     162             :   }
     163             :   static UseInfo Word64() {
     164       44880 :     return UseInfo(MachineRepresentation::kWord64, Truncation::Any());
     165             :   }
     166             :   static UseInfo Word() {
     167     1624716 :     return UseInfo(MachineType::PointerRepresentation(), Truncation::Any());
     168             :   }
     169             :   static UseInfo Bool() {
     170     4148286 :     return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
     171             :   }
     172             :   static UseInfo Float32() {
     173        5528 :     return UseInfo(MachineRepresentation::kFloat32, Truncation::Any());
     174             :   }
     175             :   static UseInfo TruncatingFloat64(
     176             :       IdentifyZeros identify_zeros = kDistinguishZeros) {
     177             :     return UseInfo(MachineRepresentation::kFloat64,
     178     1982305 :                    Truncation::Float64(identify_zeros));
     179             :   }
     180             :   static UseInfo AnyTagged() {
     181   315520381 :     return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
     182             :   }
     183             :   static UseInfo TaggedSigned() {
     184     1735432 :     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             :       const VectorSlotPair& feedback) {
     193             :     return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
     194             :                    TypeCheckKind::kHeapObject, feedback);
     195             :   }
     196             :   static UseInfo CheckedSignedSmallAsTaggedSigned(
     197             :       const VectorSlotPair& feedback,
     198             :       IdentifyZeros identify_zeros = kDistinguishZeros) {
     199             :     return UseInfo(MachineRepresentation::kTaggedSigned,
     200             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
     201             :                    feedback);
     202             :   }
     203             :   static UseInfo CheckedSignedSmallAsWord32(IdentifyZeros identify_zeros,
     204             :                                             const VectorSlotPair& feedback) {
     205             :     return UseInfo(MachineRepresentation::kWord32,
     206             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSignedSmall,
     207             :                    feedback);
     208             :   }
     209             :   static UseInfo CheckedSigned32AsWord32(IdentifyZeros identify_zeros,
     210             :                                          const VectorSlotPair& feedback) {
     211             :     return UseInfo(MachineRepresentation::kWord32,
     212             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSigned32,
     213             :                    feedback);
     214             :   }
     215             :   static UseInfo CheckedSigned64AsWord64(IdentifyZeros identify_zeros,
     216             :                                          const VectorSlotPair& feedback) {
     217             :     return UseInfo(MachineRepresentation::kWord64,
     218             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSigned64,
     219             :                    feedback);
     220             :   }
     221             :   static UseInfo CheckedNumberAsFloat64(IdentifyZeros identify_zeros,
     222             :                                         const VectorSlotPair& feedback) {
     223             :     return UseInfo(MachineRepresentation::kFloat64,
     224             :                    Truncation::Any(identify_zeros), TypeCheckKind::kNumber,
     225             :                    feedback);
     226             :   }
     227             :   static UseInfo CheckedNumberAsWord32(const VectorSlotPair& feedback) {
     228             :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
     229             :                    TypeCheckKind::kNumber, feedback);
     230             :   }
     231             :   static UseInfo CheckedNumberOrOddballAsFloat64(
     232             :       IdentifyZeros identify_zeros, const VectorSlotPair& feedback) {
     233             :     return UseInfo(MachineRepresentation::kFloat64,
     234             :                    Truncation::Any(identify_zeros),
     235             :                    TypeCheckKind::kNumberOrOddball, feedback);
     236             :   }
     237             :   static UseInfo CheckedNumberOrOddballAsWord32(
     238             :       const VectorSlotPair& feedback) {
     239             :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
     240             :                    TypeCheckKind::kNumberOrOddball, feedback);
     241             :   }
     242             : 
     243             :   // Undetermined representation.
     244             :   static UseInfo Any() {
     245    33241126 :     return UseInfo(MachineRepresentation::kNone, Truncation::Any());
     246             :   }
     247             :   static UseInfo AnyTruncatingToBool() {
     248       13000 :     return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
     249             :   }
     250             : 
     251             :   // Value not used.
     252             :   static UseInfo None() {
     253   198625051 :     return UseInfo(MachineRepresentation::kNone, Truncation::None());
     254             :   }
     255             : 
     256             :   MachineRepresentation representation() const { return representation_; }
     257             :   Truncation truncation() const { return truncation_; }
     258             :   TypeCheckKind type_check() const { return type_check_; }
     259             :   CheckForMinusZeroMode minus_zero_check() const {
     260             :     return truncation().IdentifiesZeroAndMinusZero()
     261             :                ? CheckForMinusZeroMode::kDontCheckForMinusZero
     262        4651 :                : CheckForMinusZeroMode::kCheckForMinusZero;
     263             :   }
     264             :   const VectorSlotPair& feedback() const { return feedback_; }
     265             : 
     266             :  private:
     267             :   MachineRepresentation representation_;
     268             :   Truncation truncation_;
     269             :   TypeCheckKind type_check_;
     270             :   VectorSlotPair feedback_;
     271             : };
     272             : 
     273             : // Contains logic related to changing the representation of values for constants
     274             : // and other nodes, as well as lowering Simplified->Machine operators.
     275             : // Eagerly folds any representation changes for constants.
     276             : class RepresentationChanger final {
     277             :  public:
     278             :   RepresentationChanger(JSGraph* jsgraph, Isolate* isolate);
     279             : 
     280             :   // Changes representation from {output_type} to {use_rep}. The {truncation}
     281             :   // parameter is only used for sanity checking - if the changer cannot figure
     282             :   // out signedness for the word32->float64 conversion, then we check that the
     283             :   // uses truncate to word32 (so they do not care about signedness).
     284             :   Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
     285             :                              Type output_type, Node* use_node,
     286             :                              UseInfo use_info);
     287             :   const Operator* Int32OperatorFor(IrOpcode::Value opcode);
     288             :   const Operator* Int32OverflowOperatorFor(IrOpcode::Value opcode);
     289             :   const Operator* Int64OperatorFor(IrOpcode::Value opcode);
     290             :   const Operator* TaggedSignedOperatorFor(IrOpcode::Value opcode);
     291             :   const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
     292             :   const Operator* Uint32OverflowOperatorFor(IrOpcode::Value opcode);
     293             :   const Operator* Float64OperatorFor(IrOpcode::Value opcode);
     294             : 
     295             :   MachineType TypeForBasePointer(const FieldAccess& access) {
     296             :     return access.tag() != 0 ? MachineType::AnyTagged()
     297             :                              : MachineType::Pointer();
     298             :   }
     299             : 
     300             :   MachineType TypeForBasePointer(const ElementAccess& access) {
     301             :     return access.tag() != 0 ? MachineType::AnyTagged()
     302             :                              : MachineType::Pointer();
     303             :   }
     304             : 
     305             :  private:
     306             :   TypeCache const* cache_;
     307             :   JSGraph* jsgraph_;
     308             :   Isolate* isolate_;
     309             : 
     310             :   friend class RepresentationChangerTester;  // accesses the below fields.
     311             : 
     312             :   bool testing_type_errors_;  // If {true}, don't abort on a type error.
     313             :   bool type_error_;           // Set when a type error is detected.
     314             : 
     315             :   Node* GetTaggedSignedRepresentationFor(Node* node,
     316             :                                          MachineRepresentation output_rep,
     317             :                                          Type output_type, Node* use_node,
     318             :                                          UseInfo use_info);
     319             :   Node* GetTaggedPointerRepresentationFor(Node* node,
     320             :                                           MachineRepresentation output_rep,
     321             :                                           Type output_type, Node* use_node,
     322             :                                           UseInfo use_info);
     323             :   Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep,
     324             :                                    Type output_type, Truncation truncation);
     325             :   Node* GetFloat32RepresentationFor(Node* node,
     326             :                                     MachineRepresentation output_rep,
     327             :                                     Type output_type, Truncation truncation);
     328             :   Node* GetFloat64RepresentationFor(Node* node,
     329             :                                     MachineRepresentation output_rep,
     330             :                                     Type output_type, Node* use_node,
     331             :                                     UseInfo use_info);
     332             :   Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
     333             :                                    Type output_type, Node* use_node,
     334             :                                    UseInfo use_info);
     335             :   Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
     336             :                                 Type output_type);
     337             :   Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
     338             :                                    Type output_type, Node* use_node,
     339             :                                    UseInfo use_info);
     340             :   Node* TypeError(Node* node, MachineRepresentation output_rep,
     341             :                   Type output_type, MachineRepresentation use);
     342             :   Node* MakeTruncatedInt32Constant(double value);
     343             :   Node* InsertChangeBitToTagged(Node* node);
     344             :   Node* InsertChangeFloat32ToFloat64(Node* node);
     345             :   Node* InsertChangeFloat64ToInt32(Node* node);
     346             :   Node* InsertChangeFloat64ToUint32(Node* node);
     347             :   Node* InsertChangeInt32ToFloat64(Node* node);
     348             :   Node* InsertChangeTaggedSignedToInt32(Node* node);
     349             :   Node* InsertChangeTaggedToFloat64(Node* node);
     350             :   Node* InsertChangeUint32ToFloat64(Node* node);
     351             :   Node* InsertConversion(Node* node, const Operator* op, Node* use_node);
     352             :   Node* InsertTruncateInt64ToInt32(Node* node);
     353             :   Node* InsertUnconditionalDeopt(Node* node, DeoptimizeReason reason);
     354             : 
     355             :   JSGraph* jsgraph() const { return jsgraph_; }
     356             :   Isolate* isolate() const { return isolate_; }
     357             :   Factory* factory() const { return isolate()->factory(); }
     358             :   SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
     359             :   MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
     360             : };
     361             : 
     362             : }  // namespace compiler
     363             : }  // namespace internal
     364             : }  // namespace v8
     365             : 
     366             : #endif  // V8_COMPILER_REPRESENTATION_CHANGE_H_

Generated by: LCOV version 1.10