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

Generated by: LCOV version 1.10