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