LCOV - code coverage report
Current view: top level - src/compiler - representation-change.h (source / functions) Hit Total Coverage
Test: app.info Lines: 15 15 100.0 %
Date: 2017-10-20 Functions: 1 1 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    91597272 :   static Truncation Generalize(Truncation t1, Truncation t2) {
      40             :     return Truncation(
      41             :         Generalize(t1.kind(), t2.kind()),
      42    91597272 :         GeneralizeIdentifyZeros(t1.identify_zeros(), t2.identify_zeros()));
      43             :   }
      44             : 
      45             :   // Queries.
      46             :   bool IsUnused() const { return kind_ == TruncationKind::kNone; }
      47             :   bool IsUsedAsBool() const {
      48      180046 :     return LessGeneral(kind_, TruncationKind::kBool);
      49             :   }
      50             :   bool IsUsedAsWord32() const {
      51     1420817 :     return LessGeneral(kind_, TruncationKind::kWord32);
      52             :   }
      53             :   bool IsUsedAsFloat64() const {
      54      799017 :     return LessGeneral(kind_, TruncationKind::kFloat64);
      55             :   }
      56             :   bool IdentifiesUndefinedAndZero() {
      57             :     return LessGeneral(kind_, TruncationKind::kWord32) ||
      58             :            LessGeneral(kind_, TruncationKind::kBool);
      59             :   }
      60             :   bool IdentifiesUndefinedAndNaN() {
      61             :     return LessGeneral(kind_, TruncationKind::kFloat64) ||
      62             :            LessGeneral(kind_, TruncationKind::kWord64);
      63             :   }
      64        6120 :   bool IdentifiesZeroAndMinusZero() const {
      65             :     return identify_zeros() == kIdentifyZeros;
      66             :   }
      67             : 
      68             :   // Operators.
      69   163626343 :   bool operator==(Truncation other) const {
      70   163626343 :     return kind() == other.kind() && identify_zeros() == other.identify_zeros();
      71             :   }
      72    91596678 :   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             : }
     136             : 
     137             : // The {UseInfo} class is used to describe a use of an input of a node.
     138             : //
     139             : // This information is used in two different ways, based on the phase:
     140             : //
     141             : // 1. During propagation, the use info is used to inform the input node
     142             : //    about what part of the input is used (we call this truncation) and what
     143             : //    is the preferred representation. For conversions that will require
     144             : //    checks, we also keep track of whether a minus zero check is needed.
     145             : //
     146             : // 2. During lowering, the use info is used to properly convert the input
     147             : //    to the preferred representation. The preferred representation might be
     148             : //    insufficient to do the conversion (e.g. word32->float64 conv), so we also
     149             : //    need the signedness information to produce the correct value.
     150             : class UseInfo {
     151             :  public:
     152             :   UseInfo(MachineRepresentation representation, Truncation truncation,
     153             :           TypeCheckKind type_check = TypeCheckKind::kNone)
     154             :       : representation_(representation),
     155             :         truncation_(truncation),
     156      131386 :         type_check_(type_check) {}
     157             :   static UseInfo TruncatingWord32() {
     158             :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
     159             :   }
     160             :   static UseInfo TruncatingWord64() {
     161             :     return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
     162             :   }
     163             :   static UseInfo Bool() {
     164             :     return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
     165             :   }
     166             :   static UseInfo Float32() {
     167             :     return UseInfo(MachineRepresentation::kFloat32, Truncation::Any());
     168             :   }
     169             :   static UseInfo TruncatingFloat64() {
     170             :     return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
     171             :   }
     172             :   static UseInfo PointerInt() {
     173             :     return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
     174             :   }
     175             :   static UseInfo AnyTagged() {
     176             :     return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
     177             :   }
     178             :   static UseInfo TaggedSigned() {
     179             :     return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any());
     180             :   }
     181             :   static UseInfo TaggedPointer() {
     182             :     return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any());
     183             :   }
     184             : 
     185             :   // Possibly deoptimizing conversions.
     186             :   static UseInfo CheckedHeapObjectAsTaggedPointer() {
     187             :     return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
     188             :                    TypeCheckKind::kHeapObject);
     189             :   }
     190             :   static UseInfo CheckedSignedSmallAsTaggedSigned() {
     191             :     return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any(),
     192             :                    TypeCheckKind::kSignedSmall);
     193             :   }
     194             :   static UseInfo CheckedSignedSmallAsWord32(IdentifyZeros identify_zeros) {
     195             :     return UseInfo(MachineRepresentation::kWord32,
     196             :                    Truncation::Any(identify_zeros),
     197             :                    TypeCheckKind::kSignedSmall);
     198             :   }
     199             :   static UseInfo CheckedSigned32AsWord32(IdentifyZeros identify_zeros) {
     200             :     return UseInfo(MachineRepresentation::kWord32,
     201             :                    Truncation::Any(identify_zeros), TypeCheckKind::kSigned32);
     202             :   }
     203             :   static UseInfo CheckedNumberAsFloat64() {
     204             :     return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
     205             :                    TypeCheckKind::kNumber);
     206             :   }
     207             :   static UseInfo CheckedNumberAsWord32() {
     208             :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
     209             :                    TypeCheckKind::kNumber);
     210             :   }
     211             :   static UseInfo CheckedNumberOrOddballAsFloat64() {
     212             :     return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
     213             :                    TypeCheckKind::kNumberOrOddball);
     214             :   }
     215             :   static UseInfo CheckedNumberOrOddballAsWord32() {
     216             :     return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
     217             :                    TypeCheckKind::kNumberOrOddball);
     218             :   }
     219             : 
     220             :   // Undetermined representation.
     221             :   static UseInfo Any() {
     222             :     return UseInfo(MachineRepresentation::kNone, Truncation::Any());
     223             :   }
     224             :   static UseInfo AnyTruncatingToBool() {
     225             :     return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
     226             :   }
     227             : 
     228             :   // Value not used.
     229             :   static UseInfo None() {
     230             :     return UseInfo(MachineRepresentation::kNone, Truncation::None());
     231             :   }
     232             : 
     233             :   MachineRepresentation representation() const { return representation_; }
     234             :   Truncation truncation() const { return truncation_; }
     235             :   TypeCheckKind type_check() const { return type_check_; }
     236             :   CheckForMinusZeroMode minus_zero_check() const {
     237             :     return truncation().IdentifiesZeroAndMinusZero()
     238             :                ? CheckForMinusZeroMode::kDontCheckForMinusZero
     239        6015 :                : CheckForMinusZeroMode::kCheckForMinusZero;
     240             :   }
     241             : 
     242             :  private:
     243             :   MachineRepresentation representation_;
     244             :   Truncation truncation_;
     245             :   TypeCheckKind type_check_;
     246             : };
     247             : 
     248             : // Contains logic related to changing the representation of values for constants
     249             : // and other nodes, as well as lowering Simplified->Machine operators.
     250             : // Eagerly folds any representation changes for constants.
     251             : class RepresentationChanger final {
     252             :  public:
     253             :   RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
     254             :       : jsgraph_(jsgraph),
     255             :         isolate_(isolate),
     256             :         testing_type_errors_(false),
     257      443668 :         type_error_(false) {}
     258             : 
     259             :   // Changes representation from {output_type} to {use_rep}. The {truncation}
     260             :   // parameter is only used for sanity checking - if the changer cannot figure
     261             :   // out signedness for the word32->float64 conversion, then we check that the
     262             :   // uses truncate to word32 (so they do not care about signedness).
     263             :   Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
     264             :                              Type* output_type, Node* use_node,
     265             :                              UseInfo use_info);
     266             :   const Operator* Int32OperatorFor(IrOpcode::Value opcode);
     267             :   const Operator* Int32OverflowOperatorFor(IrOpcode::Value opcode);
     268             :   const Operator* TaggedSignedOperatorFor(IrOpcode::Value opcode);
     269             :   const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
     270             :   const Operator* Uint32OverflowOperatorFor(IrOpcode::Value opcode);
     271             :   const Operator* Float64OperatorFor(IrOpcode::Value opcode);
     272             : 
     273             :   MachineType TypeForBasePointer(const FieldAccess& access) {
     274             :     return access.tag() != 0 ? MachineType::AnyTagged()
     275             :                              : MachineType::Pointer();
     276             :   }
     277             : 
     278             :   MachineType TypeForBasePointer(const ElementAccess& access) {
     279             :     return access.tag() != 0 ? MachineType::AnyTagged()
     280             :                              : MachineType::Pointer();
     281             :   }
     282             : 
     283             :  private:
     284             :   JSGraph* jsgraph_;
     285             :   Isolate* isolate_;
     286             : 
     287             :   friend class RepresentationChangerTester;  // accesses the below fields.
     288             : 
     289             :   bool testing_type_errors_;  // If {true}, don't abort on a type error.
     290             :   bool type_error_;           // Set when a type error is detected.
     291             : 
     292             :   Node* GetTaggedSignedRepresentationFor(Node* node,
     293             :                                          MachineRepresentation output_rep,
     294             :                                          Type* output_type, Node* use_node,
     295             :                                          UseInfo use_info);
     296             :   Node* GetTaggedPointerRepresentationFor(Node* node,
     297             :                                           MachineRepresentation output_rep,
     298             :                                           Type* output_type, Node* use_node,
     299             :                                           UseInfo use_info);
     300             :   Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep,
     301             :                                    Type* output_type, Truncation truncation);
     302             :   Node* GetFloat32RepresentationFor(Node* node,
     303             :                                     MachineRepresentation output_rep,
     304             :                                     Type* output_type, Truncation truncation);
     305             :   Node* GetFloat64RepresentationFor(Node* node,
     306             :                                     MachineRepresentation output_rep,
     307             :                                     Type* output_type, Node* use_node,
     308             :                                     UseInfo use_info);
     309             :   Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
     310             :                                    Type* output_type, Node* use_node,
     311             :                                    UseInfo use_info);
     312             :   Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
     313             :                                 Type* output_type);
     314             :   Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
     315             :                                    Type* output_type);
     316             :   Node* TypeError(Node* node, MachineRepresentation output_rep,
     317             :                   Type* output_type, MachineRepresentation use);
     318             :   Node* MakeTruncatedInt32Constant(double value);
     319             :   Node* InsertChangeBitToTagged(Node* node);
     320             :   Node* InsertChangeFloat32ToFloat64(Node* node);
     321             :   Node* InsertChangeFloat64ToInt32(Node* node);
     322             :   Node* InsertChangeFloat64ToUint32(Node* node);
     323             :   Node* InsertChangeInt32ToFloat64(Node* node);
     324             :   Node* InsertChangeTaggedSignedToInt32(Node* node);
     325             :   Node* InsertChangeTaggedToFloat64(Node* node);
     326             :   Node* InsertChangeUint32ToFloat64(Node* node);
     327             : 
     328             :   Node* InsertConversion(Node* node, const Operator* op, Node* use_node);
     329             : 
     330             :   JSGraph* jsgraph() const { return jsgraph_; }
     331             :   Isolate* isolate() const { return isolate_; }
     332       46663 :   Factory* factory() const { return isolate()->factory(); }
     333      899931 :   SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
     334      542995 :   MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
     335             : };
     336             : 
     337             : }  // namespace compiler
     338             : }  // namespace internal
     339             : }  // namespace v8
     340             : 
     341             : #endif  // V8_COMPILER_REPRESENTATION_CHANGE_H_

Generated by: LCOV version 1.10