Home | History | Annotate | Download | only in compiler
      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_COMMON_OPERATOR_H_
      6 #define V8_COMPILER_COMMON_OPERATOR_H_
      7 
      8 #include "src/assembler.h"
      9 #include "src/base/compiler-specific.h"
     10 #include "src/compiler/frame-states.h"
     11 #include "src/deoptimize-reason.h"
     12 #include "src/globals.h"
     13 #include "src/machine-type.h"
     14 #include "src/zone/zone-containers.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 namespace compiler {
     19 
     20 // Forward declarations.
     21 class CallDescriptor;
     22 struct CommonOperatorGlobalCache;
     23 class Operator;
     24 class Type;
     25 class Node;
     26 
     27 // Prediction hint for branches.
     28 enum class BranchHint : uint8_t { kNone, kTrue, kFalse };
     29 
     30 inline BranchHint NegateBranchHint(BranchHint hint) {
     31   switch (hint) {
     32     case BranchHint::kNone:
     33       return hint;
     34     case BranchHint::kTrue:
     35       return BranchHint::kFalse;
     36     case BranchHint::kFalse:
     37       return BranchHint::kTrue;
     38   }
     39   UNREACHABLE();
     40   return hint;
     41 }
     42 
     43 inline size_t hash_value(BranchHint hint) { return static_cast<size_t>(hint); }
     44 
     45 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BranchHint);
     46 
     47 V8_EXPORT_PRIVATE BranchHint BranchHintOf(const Operator* const);
     48 
     49 // Helper function for return nodes, because returns have a hidden value input.
     50 int ValueInputCountOfReturn(Operator const* const op);
     51 
     52 // Parameters for the {Deoptimize} operator.
     53 class DeoptimizeParameters final {
     54  public:
     55   DeoptimizeParameters(DeoptimizeKind kind, DeoptimizeReason reason)
     56       : kind_(kind), reason_(reason) {}
     57 
     58   DeoptimizeKind kind() const { return kind_; }
     59   DeoptimizeReason reason() const { return reason_; }
     60 
     61  private:
     62   DeoptimizeKind const kind_;
     63   DeoptimizeReason const reason_;
     64 };
     65 
     66 bool operator==(DeoptimizeParameters, DeoptimizeParameters);
     67 bool operator!=(DeoptimizeParameters, DeoptimizeParameters);
     68 
     69 size_t hast_value(DeoptimizeParameters p);
     70 
     71 std::ostream& operator<<(std::ostream&, DeoptimizeParameters p);
     72 
     73 DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const);
     74 
     75 
     76 class SelectParameters final {
     77  public:
     78   explicit SelectParameters(MachineRepresentation representation,
     79                             BranchHint hint = BranchHint::kNone)
     80       : representation_(representation), hint_(hint) {}
     81 
     82   MachineRepresentation representation() const { return representation_; }
     83   BranchHint hint() const { return hint_; }
     84 
     85  private:
     86   const MachineRepresentation representation_;
     87   const BranchHint hint_;
     88 };
     89 
     90 bool operator==(SelectParameters const&, SelectParameters const&);
     91 bool operator!=(SelectParameters const&, SelectParameters const&);
     92 
     93 size_t hash_value(SelectParameters const& p);
     94 
     95 std::ostream& operator<<(std::ostream&, SelectParameters const& p);
     96 
     97 V8_EXPORT_PRIVATE SelectParameters const& SelectParametersOf(
     98     const Operator* const);
     99 
    100 V8_EXPORT_PRIVATE CallDescriptor const* CallDescriptorOf(const Operator* const);
    101 
    102 V8_EXPORT_PRIVATE size_t ProjectionIndexOf(const Operator* const);
    103 
    104 V8_EXPORT_PRIVATE MachineRepresentation
    105 PhiRepresentationOf(const Operator* const);
    106 
    107 // The {IrOpcode::kParameter} opcode represents an incoming parameter to the
    108 // function. This class bundles the index and a debug name for such operators.
    109 class ParameterInfo final {
    110  public:
    111   ParameterInfo(int index, const char* debug_name)
    112       : index_(index), debug_name_(debug_name) {}
    113 
    114   int index() const { return index_; }
    115   const char* debug_name() const { return debug_name_; }
    116 
    117  private:
    118   int index_;
    119   const char* debug_name_;
    120 };
    121 
    122 std::ostream& operator<<(std::ostream&, ParameterInfo const&);
    123 
    124 V8_EXPORT_PRIVATE int ParameterIndexOf(const Operator* const);
    125 const ParameterInfo& ParameterInfoOf(const Operator* const);
    126 
    127 class RelocatablePtrConstantInfo final {
    128  public:
    129   enum Type { kInt32, kInt64 };
    130 
    131   RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode)
    132       : value_(value), rmode_(rmode), type_(kInt32) {}
    133   RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode)
    134       : value_(value), rmode_(rmode), type_(kInt64) {}
    135 
    136   intptr_t value() const { return value_; }
    137   RelocInfo::Mode rmode() const { return rmode_; }
    138   Type type() const { return type_; }
    139 
    140  private:
    141   intptr_t value_;
    142   RelocInfo::Mode rmode_;
    143   Type type_;
    144 };
    145 
    146 bool operator==(RelocatablePtrConstantInfo const& lhs,
    147                 RelocatablePtrConstantInfo const& rhs);
    148 bool operator!=(RelocatablePtrConstantInfo const& lhs,
    149                 RelocatablePtrConstantInfo const& rhs);
    150 
    151 std::ostream& operator<<(std::ostream&, RelocatablePtrConstantInfo const&);
    152 
    153 size_t hash_value(RelocatablePtrConstantInfo const& p);
    154 
    155 // Used to define a sparse set of inputs. This can be used to efficiently encode
    156 // nodes that can have a lot of inputs, but where many inputs can have the same
    157 // value.
    158 class SparseInputMask final {
    159  public:
    160   typedef uint32_t BitMaskType;
    161 
    162   // The mask representing a dense input set.
    163   static const BitMaskType kDenseBitMask = 0x0;
    164   // The bits representing the end of a sparse input set.
    165   static const BitMaskType kEndMarker = 0x1;
    166   // The mask for accessing a sparse input entry in the bitmask.
    167   static const BitMaskType kEntryMask = 0x1;
    168 
    169   // The number of bits in the mask, minus one for the end marker.
    170   static const int kMaxSparseInputs = (sizeof(BitMaskType) * kBitsPerByte - 1);
    171 
    172   // An iterator over a node's sparse inputs.
    173   class InputIterator final {
    174    public:
    175     InputIterator() {}
    176     InputIterator(BitMaskType bit_mask, Node* parent);
    177 
    178     Node* parent() const { return parent_; }
    179     int real_index() const { return real_index_; }
    180 
    181     // Advance the iterator to the next sparse input. Only valid if the iterator
    182     // has not reached the end.
    183     void Advance();
    184 
    185     // Get the current sparse input's real node value. Only valid if the
    186     // current sparse input is real.
    187     Node* GetReal() const;
    188 
    189     // Get the current sparse input, returning either a real input node if
    190     // the current sparse input is real, or the given {empty_value} if the
    191     // current sparse input is empty.
    192     Node* Get(Node* empty_value) const {
    193       return IsReal() ? GetReal() : empty_value;
    194     }
    195 
    196     // True if the current sparse input is a real input node.
    197     bool IsReal() const;
    198 
    199     // True if the current sparse input is an empty value.
    200     bool IsEmpty() const { return !IsReal(); }
    201 
    202     // True if the iterator has reached the end of the sparse inputs.
    203     bool IsEnd() const;
    204 
    205    private:
    206     BitMaskType bit_mask_;
    207     Node* parent_;
    208     int real_index_;
    209   };
    210 
    211   explicit SparseInputMask(BitMaskType bit_mask) : bit_mask_(bit_mask) {}
    212 
    213   // Provides a SparseInputMask representing a dense input set.
    214   static SparseInputMask Dense() { return SparseInputMask(kDenseBitMask); }
    215 
    216   BitMaskType mask() const { return bit_mask_; }
    217 
    218   bool IsDense() const { return bit_mask_ == SparseInputMask::kDenseBitMask; }
    219 
    220   // Counts how many real values are in the sparse array. Only valid for
    221   // non-dense masks.
    222   int CountReal() const;
    223 
    224   // Returns an iterator over the sparse inputs of {node}.
    225   InputIterator IterateOverInputs(Node* node);
    226 
    227  private:
    228   //
    229   // The sparse input mask has a bitmask specifying if the node's inputs are
    230   // represented sparsely. If the bitmask value is 0, then the inputs are dense;
    231   // otherwise, they should be interpreted as follows:
    232   //
    233   //   * The bitmask represents which values are real, with 1 for real values
    234   //     and 0 for empty values.
    235   //   * The inputs to the node are the real values, in the order of the 1s from
    236   //     least- to most-significant.
    237   //   * The top bit of the bitmask is a guard indicating the end of the values,
    238   //     whether real or empty (and is not representative of a real input
    239   //     itself). This is used so that we don't have to additionally store a
    240   //     value count.
    241   //
    242   // So, for N 1s in the bitmask, there are N - 1 inputs into the node.
    243   BitMaskType bit_mask_;
    244 };
    245 
    246 bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs);
    247 bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs);
    248 
    249 class TypedStateValueInfo final {
    250  public:
    251   TypedStateValueInfo(ZoneVector<MachineType> const* machine_types,
    252                       SparseInputMask sparse_input_mask)
    253       : machine_types_(machine_types), sparse_input_mask_(sparse_input_mask) {}
    254 
    255   ZoneVector<MachineType> const* machine_types() const {
    256     return machine_types_;
    257   }
    258   SparseInputMask sparse_input_mask() const { return sparse_input_mask_; }
    259 
    260  private:
    261   ZoneVector<MachineType> const* machine_types_;
    262   SparseInputMask sparse_input_mask_;
    263 };
    264 
    265 bool operator==(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs);
    266 bool operator!=(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs);
    267 
    268 std::ostream& operator<<(std::ostream&, TypedStateValueInfo const&);
    269 
    270 size_t hash_value(TypedStateValueInfo const& p);
    271 
    272 // Used to mark a region (as identified by BeginRegion/FinishRegion) as either
    273 // JavaScript-observable or not (i.e. allocations are not JavaScript observable
    274 // themselves, but transitioning stores are).
    275 enum class RegionObservability : uint8_t { kObservable, kNotObservable };
    276 
    277 size_t hash_value(RegionObservability);
    278 
    279 std::ostream& operator<<(std::ostream&, RegionObservability);
    280 
    281 RegionObservability RegionObservabilityOf(Operator const*) WARN_UNUSED_RESULT;
    282 
    283 std::ostream& operator<<(std::ostream& os,
    284                          const ZoneVector<MachineType>* types);
    285 
    286 Type* TypeGuardTypeOf(Operator const*) WARN_UNUSED_RESULT;
    287 
    288 int OsrValueIndexOf(Operator const*);
    289 
    290 enum class OsrGuardType { kUninitialized, kSignedSmall, kAny };
    291 size_t hash_value(OsrGuardType type);
    292 std::ostream& operator<<(std::ostream&, OsrGuardType);
    293 OsrGuardType OsrGuardTypeOf(Operator const*);
    294 
    295 SparseInputMask SparseInputMaskOf(Operator const*);
    296 
    297 ZoneVector<MachineType> const* MachineTypesOf(Operator const*)
    298     WARN_UNUSED_RESULT;
    299 
    300 // Interface for building common operators that can be used at any level of IR,
    301 // including JavaScript, mid-level, and low-level.
    302 class V8_EXPORT_PRIVATE CommonOperatorBuilder final
    303     : public NON_EXPORTED_BASE(ZoneObject) {
    304  public:
    305   explicit CommonOperatorBuilder(Zone* zone);
    306 
    307   const Operator* Dead();
    308   const Operator* End(size_t control_input_count);
    309   const Operator* Branch(BranchHint = BranchHint::kNone);
    310   const Operator* IfTrue();
    311   const Operator* IfFalse();
    312   const Operator* IfSuccess();
    313   const Operator* IfException();
    314   const Operator* Switch(size_t control_output_count);
    315   const Operator* IfValue(int32_t value);
    316   const Operator* IfDefault();
    317   const Operator* Throw();
    318   const Operator* Deoptimize(DeoptimizeKind kind, DeoptimizeReason reason);
    319   const Operator* DeoptimizeIf(DeoptimizeKind kind, DeoptimizeReason reason);
    320   const Operator* DeoptimizeUnless(DeoptimizeKind kind,
    321                                    DeoptimizeReason reason);
    322   const Operator* TrapIf(int32_t trap_id);
    323   const Operator* TrapUnless(int32_t trap_id);
    324   const Operator* Return(int value_input_count = 1);
    325   const Operator* Terminate();
    326 
    327   const Operator* Start(int value_output_count);
    328   const Operator* Loop(int control_input_count);
    329   const Operator* Merge(int control_input_count);
    330   const Operator* Parameter(int index, const char* debug_name = nullptr);
    331 
    332   const Operator* OsrNormalEntry();
    333   const Operator* OsrLoopEntry();
    334   const Operator* OsrValue(int index);
    335   const Operator* OsrGuard(OsrGuardType type);
    336 
    337   const Operator* Int32Constant(int32_t);
    338   const Operator* Int64Constant(int64_t);
    339   const Operator* Float32Constant(volatile float);
    340   const Operator* Float64Constant(volatile double);
    341   const Operator* ExternalConstant(const ExternalReference&);
    342   const Operator* NumberConstant(volatile double);
    343   const Operator* PointerConstant(intptr_t);
    344   const Operator* HeapConstant(const Handle<HeapObject>&);
    345 
    346   const Operator* RelocatableInt32Constant(int32_t value,
    347                                            RelocInfo::Mode rmode);
    348   const Operator* RelocatableInt64Constant(int64_t value,
    349                                            RelocInfo::Mode rmode);
    350 
    351   const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone);
    352   const Operator* Phi(MachineRepresentation representation,
    353                       int value_input_count);
    354   const Operator* EffectPhi(int effect_input_count);
    355   const Operator* InductionVariablePhi(int value_input_count);
    356   const Operator* LoopExit();
    357   const Operator* LoopExitValue();
    358   const Operator* LoopExitEffect();
    359   const Operator* Checkpoint();
    360   const Operator* BeginRegion(RegionObservability);
    361   const Operator* FinishRegion();
    362   const Operator* StateValues(int arguments, SparseInputMask bitmask);
    363   const Operator* TypedStateValues(const ZoneVector<MachineType>* types,
    364                                    SparseInputMask bitmask);
    365   const Operator* ArgumentsObjectState();
    366   const Operator* ObjectState(int pointer_slots);
    367   const Operator* TypedObjectState(const ZoneVector<MachineType>* types);
    368   const Operator* FrameState(BailoutId bailout_id,
    369                              OutputFrameStateCombine state_combine,
    370                              const FrameStateFunctionInfo* function_info);
    371   const Operator* Call(const CallDescriptor* descriptor);
    372   const Operator* TailCall(const CallDescriptor* descriptor);
    373   const Operator* Projection(size_t index);
    374   const Operator* Retain();
    375   const Operator* TypeGuard(Type* type);
    376 
    377   // Constructs a new merge or phi operator with the same opcode as {op}, but
    378   // with {size} inputs.
    379   const Operator* ResizeMergeOrPhi(const Operator* op, int size);
    380 
    381   // Constructs function info for frame state construction.
    382   const FrameStateFunctionInfo* CreateFrameStateFunctionInfo(
    383       FrameStateType type, int parameter_count, int local_count,
    384       Handle<SharedFunctionInfo> shared_info);
    385 
    386  private:
    387   Zone* zone() const { return zone_; }
    388 
    389   const CommonOperatorGlobalCache& cache_;
    390   Zone* const zone_;
    391 
    392   DISALLOW_COPY_AND_ASSIGN(CommonOperatorBuilder);
    393 };
    394 
    395 }  // namespace compiler
    396 }  // namespace internal
    397 }  // namespace v8
    398 
    399 #endif  // V8_COMPILER_COMMON_OPERATOR_H_
    400