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

Generated by: LCOV version 1.10