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/base/compiler-specific.h"
9 #include "src/codegen/machine-type.h"
10 #include "src/codegen/reloc-info.h"
11 #include "src/codegen/string-constants.h"
12 #include "src/common/globals.h"
13 #include "src/compiler/feedback-source.h"
14 #include "src/compiler/frame-states.h"
15 #include "src/compiler/linkage.h"
16 #include "src/compiler/node-properties.h"
17 #include "src/deoptimizer/deoptimize-reason.h"
18 #include "src/zone/zone-containers.h"
19 #include "src/zone/zone-handle-set.h"
20 
21 namespace v8 {
22 namespace internal {
23 
24 class StringConstantBase;
25 
26 namespace compiler {
27 
28 // Forward declarations.
29 class CallDescriptor;
30 struct CommonOperatorGlobalCache;
31 class Operator;
32 class Type;
33 class Node;
34 
35 // Prediction hint for branches.
36 enum class BranchHint : uint8_t { kNone, kTrue, kFalse };
37 
NegateBranchHint(BranchHint hint)38 inline BranchHint NegateBranchHint(BranchHint hint) {
39   switch (hint) {
40     case BranchHint::kNone:
41       return hint;
42     case BranchHint::kTrue:
43       return BranchHint::kFalse;
44     case BranchHint::kFalse:
45       return BranchHint::kTrue;
46   }
47   UNREACHABLE();
48 }
49 
hash_value(BranchHint hint)50 inline size_t hash_value(BranchHint hint) { return static_cast<size_t>(hint); }
51 
52 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BranchHint);
53 
54 enum class IsSafetyCheck : uint8_t {
55   kCriticalSafetyCheck,
56   kSafetyCheck,
57   kNoSafetyCheck
58 };
59 
60 // Get the more critical safety check of the two arguments.
61 IsSafetyCheck CombineSafetyChecks(IsSafetyCheck, IsSafetyCheck);
62 
63 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, IsSafetyCheck);
hash_value(IsSafetyCheck is_safety_check)64 inline size_t hash_value(IsSafetyCheck is_safety_check) {
65   return static_cast<size_t>(is_safety_check);
66 }
67 
68 enum class TrapId : uint32_t {
69 #define DEF_ENUM(Name, ...) k##Name,
70   FOREACH_WASM_TRAPREASON(DEF_ENUM)
71 #undef DEF_ENUM
72       kInvalid
73 };
74 
hash_value(TrapId id)75 inline size_t hash_value(TrapId id) { return static_cast<uint32_t>(id); }
76 
77 std::ostream& operator<<(std::ostream&, TrapId trap_id);
78 
79 TrapId TrapIdOf(const Operator* const op);
80 
81 struct BranchOperatorInfo {
82   BranchHint hint;
83   IsSafetyCheck is_safety_check;
84 };
85 
hash_value(const BranchOperatorInfo & info)86 inline size_t hash_value(const BranchOperatorInfo& info) {
87   return base::hash_combine(info.hint, info.is_safety_check);
88 }
89 
90 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BranchOperatorInfo);
91 
92 inline bool operator==(const BranchOperatorInfo& a,
93                        const BranchOperatorInfo& b) {
94   return a.hint == b.hint && a.is_safety_check == b.is_safety_check;
95 }
96 
97 V8_EXPORT_PRIVATE const BranchOperatorInfo& BranchOperatorInfoOf(
98     const Operator* const) V8_WARN_UNUSED_RESULT;
99 V8_EXPORT_PRIVATE BranchHint BranchHintOf(const Operator* const)
100     V8_WARN_UNUSED_RESULT;
101 
102 // Helper function for return nodes, because returns have a hidden value input.
103 int ValueInputCountOfReturn(Operator const* const op);
104 
105 // Parameters for the {Deoptimize} operator.
106 class DeoptimizeParameters final {
107  public:
DeoptimizeParameters(DeoptimizeKind kind,DeoptimizeReason reason,FeedbackSource const & feedback,IsSafetyCheck is_safety_check)108   DeoptimizeParameters(DeoptimizeKind kind, DeoptimizeReason reason,
109                        FeedbackSource const& feedback,
110                        IsSafetyCheck is_safety_check)
111       : kind_(kind),
112         reason_(reason),
113         feedback_(feedback),
114         is_safety_check_(is_safety_check) {}
115 
kind()116   DeoptimizeKind kind() const { return kind_; }
reason()117   DeoptimizeReason reason() const { return reason_; }
feedback()118   const FeedbackSource& feedback() const { return feedback_; }
is_safety_check()119   IsSafetyCheck is_safety_check() const { return is_safety_check_; }
120 
121  private:
122   DeoptimizeKind const kind_;
123   DeoptimizeReason const reason_;
124   FeedbackSource const feedback_;
125   IsSafetyCheck is_safety_check_;
126 };
127 
128 bool operator==(DeoptimizeParameters, DeoptimizeParameters);
129 bool operator!=(DeoptimizeParameters, DeoptimizeParameters);
130 
131 size_t hast_value(DeoptimizeParameters p);
132 
133 std::ostream& operator<<(std::ostream&, DeoptimizeParameters p);
134 
135 DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const)
136     V8_WARN_UNUSED_RESULT;
137 
138 IsSafetyCheck IsSafetyCheckOf(const Operator* op) V8_WARN_UNUSED_RESULT;
139 
140 class SelectParameters final {
141  public:
142   explicit SelectParameters(MachineRepresentation representation,
143                             BranchHint hint = BranchHint::kNone)
representation_(representation)144       : representation_(representation), hint_(hint) {}
145 
representation()146   MachineRepresentation representation() const { return representation_; }
hint()147   BranchHint hint() const { return hint_; }
148 
149  private:
150   const MachineRepresentation representation_;
151   const BranchHint hint_;
152 };
153 
154 bool operator==(SelectParameters const&, SelectParameters const&);
155 bool operator!=(SelectParameters const&, SelectParameters const&);
156 
157 size_t hash_value(SelectParameters const& p);
158 
159 std::ostream& operator<<(std::ostream&, SelectParameters const& p);
160 
161 V8_EXPORT_PRIVATE SelectParameters const& SelectParametersOf(
162     const Operator* const) V8_WARN_UNUSED_RESULT;
163 
164 V8_EXPORT_PRIVATE CallDescriptor const* CallDescriptorOf(const Operator* const)
165     V8_WARN_UNUSED_RESULT;
166 
167 V8_EXPORT_PRIVATE size_t ProjectionIndexOf(const Operator* const)
168     V8_WARN_UNUSED_RESULT;
169 
170 V8_EXPORT_PRIVATE MachineRepresentation
171 PhiRepresentationOf(const Operator* const) V8_WARN_UNUSED_RESULT;
172 
173 // The {IrOpcode::kParameter} opcode represents an incoming parameter to the
174 // function. This class bundles the index and a debug name for such operators.
175 class ParameterInfo final {
176  public:
ParameterInfo(int index,const char * debug_name)177   ParameterInfo(int index, const char* debug_name)
178       : index_(index), debug_name_(debug_name) {}
179 
index()180   int index() const { return index_; }
debug_name()181   const char* debug_name() const { return debug_name_; }
182 
183  private:
184   int index_;
185   const char* debug_name_;
186 };
187 
188 std::ostream& operator<<(std::ostream&, ParameterInfo const&);
189 
190 V8_EXPORT_PRIVATE int ParameterIndexOf(const Operator* const)
191     V8_WARN_UNUSED_RESULT;
192 const ParameterInfo& ParameterInfoOf(const Operator* const)
193     V8_WARN_UNUSED_RESULT;
194 
195 struct ObjectStateInfo final : std::pair<uint32_t, int> {
ObjectStateInfofinal196   ObjectStateInfo(uint32_t object_id, int size)
197       : std::pair<uint32_t, int>(object_id, size) {}
object_idfinal198   uint32_t object_id() const { return first; }
sizefinal199   int size() const { return second; }
200 };
201 std::ostream& operator<<(std::ostream&, ObjectStateInfo const&);
202 size_t hash_value(ObjectStateInfo const& p);
203 
204 struct TypedObjectStateInfo final
205     : std::pair<uint32_t, const ZoneVector<MachineType>*> {
TypedObjectStateInfofinal206   TypedObjectStateInfo(uint32_t object_id,
207                        const ZoneVector<MachineType>* machine_types)
208       : std::pair<uint32_t, const ZoneVector<MachineType>*>(object_id,
209                                                             machine_types) {}
object_idfinal210   uint32_t object_id() const { return first; }
machine_typesfinal211   const ZoneVector<MachineType>* machine_types() const { return second; }
212 };
213 std::ostream& operator<<(std::ostream&, TypedObjectStateInfo const&);
214 size_t hash_value(TypedObjectStateInfo const& p);
215 
216 class RelocatablePtrConstantInfo final {
217  public:
218   enum Type { kInt32, kInt64 };
219 
RelocatablePtrConstantInfo(int32_t value,RelocInfo::Mode rmode)220   RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode)
221       : value_(value), rmode_(rmode), type_(kInt32) {}
RelocatablePtrConstantInfo(int64_t value,RelocInfo::Mode rmode)222   RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode)
223       : value_(value), rmode_(rmode), type_(kInt64) {}
224 
value()225   intptr_t value() const { return value_; }
rmode()226   RelocInfo::Mode rmode() const { return rmode_; }
type()227   Type type() const { return type_; }
228 
229  private:
230   intptr_t value_;
231   RelocInfo::Mode rmode_;
232   Type type_;
233 };
234 
235 bool operator==(RelocatablePtrConstantInfo const& lhs,
236                 RelocatablePtrConstantInfo const& rhs);
237 bool operator!=(RelocatablePtrConstantInfo const& lhs,
238                 RelocatablePtrConstantInfo const& rhs);
239 
240 std::ostream& operator<<(std::ostream&, RelocatablePtrConstantInfo const&);
241 
242 size_t hash_value(RelocatablePtrConstantInfo const& p);
243 
244 // Used to define a sparse set of inputs. This can be used to efficiently encode
245 // nodes that can have a lot of inputs, but where many inputs can have the same
246 // value.
247 class SparseInputMask final {
248  public:
249   using BitMaskType = uint32_t;
250 
251   // The mask representing a dense input set.
252   static const BitMaskType kDenseBitMask = 0x0;
253   // The bits representing the end of a sparse input set.
254   static const BitMaskType kEndMarker = 0x1;
255   // The mask for accessing a sparse input entry in the bitmask.
256   static const BitMaskType kEntryMask = 0x1;
257 
258   // The number of bits in the mask, minus one for the end marker.
259   static const int kMaxSparseInputs = (sizeof(BitMaskType) * kBitsPerByte - 1);
260 
261   // An iterator over a node's sparse inputs.
262   class InputIterator final {
263    public:
264     InputIterator() = default;
265     InputIterator(BitMaskType bit_mask, Node* parent);
266 
parent()267     Node* parent() const { return parent_; }
real_index()268     int real_index() const { return real_index_; }
269 
270     // Advance the iterator to the next sparse input. Only valid if the iterator
271     // has not reached the end.
272     void Advance();
273 
274     // Get the current sparse input's real node value. Only valid if the
275     // current sparse input is real.
276     Node* GetReal() const;
277 
278     // Advance to the next real value or the end. Only valid if the iterator is
279     // not dense. Returns the number of empty values that were skipped. This can
280     // return 0 and in that case, it does not advance.
281     size_t AdvanceToNextRealOrEnd();
282 
283     // Get the current sparse input, returning either a real input node if
284     // the current sparse input is real, or the given {empty_value} if the
285     // current sparse input is empty.
Get(Node * empty_value)286     Node* Get(Node* empty_value) const {
287       return IsReal() ? GetReal() : empty_value;
288     }
289 
290     // True if the current sparse input is a real input node.
291     bool IsReal() const;
292 
293     // True if the current sparse input is an empty value.
IsEmpty()294     bool IsEmpty() const { return !IsReal(); }
295 
296     // True if the iterator has reached the end of the sparse inputs.
297     bool IsEnd() const;
298 
299    private:
300     BitMaskType bit_mask_;
301     Node* parent_;
302     int real_index_;
303   };
304 
SparseInputMask(BitMaskType bit_mask)305   explicit SparseInputMask(BitMaskType bit_mask) : bit_mask_(bit_mask) {}
306 
307   // Provides a SparseInputMask representing a dense input set.
Dense()308   static SparseInputMask Dense() { return SparseInputMask(kDenseBitMask); }
309 
mask()310   BitMaskType mask() const { return bit_mask_; }
311 
IsDense()312   bool IsDense() const { return bit_mask_ == SparseInputMask::kDenseBitMask; }
313 
314   // Counts how many real values are in the sparse array. Only valid for
315   // non-dense masks.
316   int CountReal() const;
317 
318   // Returns an iterator over the sparse inputs of {node}.
319   InputIterator IterateOverInputs(Node* node);
320 
321  private:
322   //
323   // The sparse input mask has a bitmask specifying if the node's inputs are
324   // represented sparsely. If the bitmask value is 0, then the inputs are dense;
325   // otherwise, they should be interpreted as follows:
326   //
327   //   * The bitmask represents which values are real, with 1 for real values
328   //     and 0 for empty values.
329   //   * The inputs to the node are the real values, in the order of the 1s from
330   //     least- to most-significant.
331   //   * The top bit of the bitmask is a guard indicating the end of the values,
332   //     whether real or empty (and is not representative of a real input
333   //     itself). This is used so that we don't have to additionally store a
334   //     value count.
335   //
336   // So, for N 1s in the bitmask, there are N - 1 inputs into the node.
337   BitMaskType bit_mask_;
338 };
339 
340 bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs);
341 bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs);
342 
343 class TypedStateValueInfo final {
344  public:
TypedStateValueInfo(ZoneVector<MachineType> const * machine_types,SparseInputMask sparse_input_mask)345   TypedStateValueInfo(ZoneVector<MachineType> const* machine_types,
346                       SparseInputMask sparse_input_mask)
347       : machine_types_(machine_types), sparse_input_mask_(sparse_input_mask) {}
348 
machine_types()349   ZoneVector<MachineType> const* machine_types() const {
350     return machine_types_;
351   }
sparse_input_mask()352   SparseInputMask sparse_input_mask() const { return sparse_input_mask_; }
353 
354  private:
355   ZoneVector<MachineType> const* machine_types_;
356   SparseInputMask sparse_input_mask_;
357 };
358 
359 bool operator==(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs);
360 bool operator!=(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs);
361 
362 std::ostream& operator<<(std::ostream&, TypedStateValueInfo const&);
363 
364 size_t hash_value(TypedStateValueInfo const& p);
365 
366 // Used to mark a region (as identified by BeginRegion/FinishRegion) as either
367 // JavaScript-observable or not (i.e. allocations are not JavaScript observable
368 // themselves, but transitioning stores are).
369 enum class RegionObservability : uint8_t { kObservable, kNotObservable };
370 
371 size_t hash_value(RegionObservability);
372 
373 std::ostream& operator<<(std::ostream&, RegionObservability);
374 
375 RegionObservability RegionObservabilityOf(Operator const*)
376     V8_WARN_UNUSED_RESULT;
377 
378 std::ostream& operator<<(std::ostream& os,
379                          const ZoneVector<MachineType>* types);
380 
381 Type TypeGuardTypeOf(Operator const*) V8_WARN_UNUSED_RESULT;
382 
383 int OsrValueIndexOf(Operator const*) V8_WARN_UNUSED_RESULT;
384 
385 SparseInputMask SparseInputMaskOf(Operator const*) V8_WARN_UNUSED_RESULT;
386 
387 ZoneVector<MachineType> const* MachineTypesOf(Operator const*)
388     V8_WARN_UNUSED_RESULT;
389 
390 // The ArgumentsElementsState and ArgumentsLengthState can describe the layout
391 // for backing stores of arguments objects of various types:
392 //
393 //                        +------------------------------------+
394 //  - kUnmappedArguments: | arg0, ... argK-1, argK, ... argN-1 |  {length:N}
395 //                        +------------------------------------+
396 //                        +------------------------------------+
397 //  - kMappedArguments:   | hole, ...   hole, argK, ... argN-1 |  {length:N}
398 //                        +------------------------------------+
399 //                                          +------------------+
400 //  - kRestParameter:                       | argK, ... argN-1 |  {length:N-K}
401 //                                          +------------------+
402 //
403 // Here {K} represents the number for formal parameters of the active function,
404 // whereas {N} represents the actual number of arguments passed at runtime.
405 // Note that {N < K} can happen and causes {K} to be capped accordingly.
406 //
407 // Also note that it is possible for an arguments object of {kMappedArguments}
408 // type to carry a backing store of {kUnappedArguments} type when {K == 0}.
409 using ArgumentsStateType = CreateArgumentsType;
410 
411 ArgumentsStateType ArgumentsStateTypeOf(Operator const*) V8_WARN_UNUSED_RESULT;
412 
413 uint32_t ObjectIdOf(Operator const*);
414 
415 MachineRepresentation DeadValueRepresentationOf(Operator const*)
416     V8_WARN_UNUSED_RESULT;
417 
418 class IfValueParameters final {
419  public:
420   IfValueParameters(int32_t value, int32_t comparison_order,
421                     BranchHint hint = BranchHint::kNone)
value_(value)422       : value_(value), comparison_order_(comparison_order), hint_(hint) {}
423 
value()424   int32_t value() const { return value_; }
comparison_order()425   int32_t comparison_order() const { return comparison_order_; }
hint()426   BranchHint hint() const { return hint_; }
427 
428  private:
429   int32_t value_;
430   int32_t comparison_order_;
431   BranchHint hint_;
432 };
433 
434 V8_EXPORT_PRIVATE bool operator==(IfValueParameters const&,
435                                   IfValueParameters const&);
436 
437 size_t hash_value(IfValueParameters const&);
438 
439 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
440                                            IfValueParameters const&);
441 
442 V8_EXPORT_PRIVATE IfValueParameters const& IfValueParametersOf(
443     const Operator* op) V8_WARN_UNUSED_RESULT;
444 
445 const FrameStateInfo& FrameStateInfoOf(const Operator* op)
446     V8_WARN_UNUSED_RESULT;
447 
448 V8_EXPORT_PRIVATE Handle<HeapObject> HeapConstantOf(const Operator* op)
449     V8_WARN_UNUSED_RESULT;
450 
451 const StringConstantBase* StringConstantBaseOf(const Operator* op)
452     V8_WARN_UNUSED_RESULT;
453 
454 const char* StaticAssertSourceOf(const Operator* op);
455 
456 // Interface for building common operators that can be used at any level of IR,
457 // including JavaScript, mid-level, and low-level.
458 class V8_EXPORT_PRIVATE CommonOperatorBuilder final
NON_EXPORTED_BASE(ZoneObject)459     : public NON_EXPORTED_BASE(ZoneObject) {
460  public:
461   explicit CommonOperatorBuilder(Zone* zone);
462   CommonOperatorBuilder(const CommonOperatorBuilder&) = delete;
463   CommonOperatorBuilder& operator=(const CommonOperatorBuilder&) = delete;
464 
465   const Operator* Dead();
466   const Operator* DeadValue(MachineRepresentation rep);
467   const Operator* Unreachable();
468   const Operator* StaticAssert(const char* source);
469   const Operator* End(size_t control_input_count);
470   const Operator* Branch(BranchHint = BranchHint::kNone,
471                          IsSafetyCheck = IsSafetyCheck::kSafetyCheck);
472   const Operator* IfTrue();
473   const Operator* IfFalse();
474   const Operator* IfSuccess();
475   const Operator* IfException();
476   const Operator* Switch(size_t control_output_count);
477   const Operator* IfValue(int32_t value, int32_t order = 0,
478                           BranchHint hint = BranchHint::kNone);
479   const Operator* IfDefault(BranchHint hint = BranchHint::kNone);
480   const Operator* Throw();
481   const Operator* Deoptimize(DeoptimizeKind kind, DeoptimizeReason reason,
482                              FeedbackSource const& feedback);
483   const Operator* DeoptimizeIf(
484       DeoptimizeKind kind, DeoptimizeReason reason,
485       FeedbackSource const& feedback,
486       IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
487   const Operator* DeoptimizeUnless(
488       DeoptimizeKind kind, DeoptimizeReason reason,
489       FeedbackSource const& feedback,
490       IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
491   const Operator* TrapIf(TrapId trap_id);
492   const Operator* TrapUnless(TrapId trap_id);
493   const Operator* Return(int value_input_count = 1);
494   const Operator* Terminate();
495 
496   const Operator* Start(int value_output_count);
497   const Operator* Loop(int control_input_count);
498   const Operator* Merge(int control_input_count);
499   const Operator* Parameter(int index, const char* debug_name = nullptr);
500 
501   const Operator* OsrValue(int index);
502 
503   const Operator* Int32Constant(int32_t);
504   const Operator* Int64Constant(int64_t);
505   const Operator* TaggedIndexConstant(int32_t value);
506   const Operator* Float32Constant(volatile float);
507   const Operator* Float64Constant(volatile double);
508   const Operator* ExternalConstant(const ExternalReference&);
509   const Operator* NumberConstant(volatile double);
510   const Operator* PointerConstant(intptr_t);
511   const Operator* HeapConstant(const Handle<HeapObject>&);
512   const Operator* CompressedHeapConstant(const Handle<HeapObject>&);
513   const Operator* ObjectId(uint32_t);
514 
515   const Operator* RelocatableInt32Constant(int32_t value,
516                                            RelocInfo::Mode rmode);
517   const Operator* RelocatableInt64Constant(int64_t value,
518                                            RelocInfo::Mode rmode);
519 
520   const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone);
521   const Operator* Phi(MachineRepresentation representation,
522                       int value_input_count);
523   const Operator* EffectPhi(int effect_input_count);
524   const Operator* InductionVariablePhi(int value_input_count);
525   const Operator* LoopExit();
526   const Operator* LoopExitValue();
527   const Operator* LoopExitEffect();
528   const Operator* Checkpoint();
529   const Operator* BeginRegion(RegionObservability);
530   const Operator* FinishRegion();
531   const Operator* StateValues(int arguments, SparseInputMask bitmask);
532   const Operator* TypedStateValues(const ZoneVector<MachineType>* types,
533                                    SparseInputMask bitmask);
534   const Operator* ArgumentsElementsState(ArgumentsStateType type);
535   const Operator* ArgumentsLengthState();
536   const Operator* ObjectState(uint32_t object_id, int pointer_slots);
537   const Operator* TypedObjectState(uint32_t object_id,
538                                    const ZoneVector<MachineType>* types);
539   const Operator* FrameState(BailoutId bailout_id,
540                              OutputFrameStateCombine state_combine,
541                              const FrameStateFunctionInfo* function_info);
542   const Operator* Call(const CallDescriptor* call_descriptor);
543   const Operator* TailCall(const CallDescriptor* call_descriptor);
544   const Operator* Projection(size_t index);
545   const Operator* Retain();
546   const Operator* TypeGuard(Type type);
547   const Operator* FoldConstant();
548 
549   // Constructs a new merge or phi operator with the same opcode as {op}, but
550   // with {size} inputs.
551   const Operator* ResizeMergeOrPhi(const Operator* op, int size);
552 
553   // Constructs function info for frame state construction.
554   const FrameStateFunctionInfo* CreateFrameStateFunctionInfo(
555       FrameStateType type, int parameter_count, int local_count,
556       Handle<SharedFunctionInfo> shared_info);
557 
558   const Operator* MarkAsSafetyCheck(const Operator* op,
559                                     IsSafetyCheck safety_check);
560 
561   const Operator* DelayedStringConstant(const StringConstantBase* str);
562 
563  private:
564   Zone* zone() const { return zone_; }
565 
566   const CommonOperatorGlobalCache& cache_;
567   Zone* const zone_;
568 };
569 
570 // Node wrappers.
571 
572 class CommonNodeWrapperBase : public NodeWrapper {
573  public:
CommonNodeWrapperBase(Node * node)574   explicit constexpr CommonNodeWrapperBase(Node* node) : NodeWrapper(node) {}
575 
576   // Valid iff this node has exactly one effect input.
effect()577   Effect effect() const {
578     DCHECK_EQ(node()->op()->EffectInputCount(), 1);
579     return Effect{NodeProperties::GetEffectInput(node())};
580   }
581 
582   // Valid iff this node has exactly one control input.
control()583   Control control() const {
584     DCHECK_EQ(node()->op()->ControlInputCount(), 1);
585     return Control{NodeProperties::GetControlInput(node())};
586   }
587 };
588 
589 #define DEFINE_INPUT_ACCESSORS(Name, name, TheIndex, Type) \
590   static constexpr int Name##Index() { return TheIndex; }  \
591   TNode<Type> name() const {                               \
592     return TNode<Type>::UncheckedCast(                     \
593         NodeProperties::GetValueInput(node(), TheIndex));  \
594   }
595 
596 class StartNode final : public CommonNodeWrapperBase {
597  public:
StartNode(Node * node)598   explicit constexpr StartNode(Node* node) : CommonNodeWrapperBase(node) {
599     CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kStart);
600   }
601 
602   // The receiver is counted as part of formal parameters.
603   static constexpr int kReceiverOutputCount = 1;
604   // These outputs are in addition to formal parameters.
605   static constexpr int kExtraOutputCount = 4;
606 
607   // Takes the formal parameter count of the current function (including
608   // receiver) and returns the number of value outputs of the start node.
OutputArityForFormalParameterCount(int argc)609   static constexpr int OutputArityForFormalParameterCount(int argc) {
610     constexpr int kClosure = 1;
611     constexpr int kNewTarget = 1;
612     constexpr int kArgCount = 1;
613     constexpr int kContext = 1;
614     STATIC_ASSERT(kClosure + kNewTarget + kArgCount + kContext ==
615                   kExtraOutputCount);
616     // Checking related linkage methods here since they rely on Start node
617     // layout.
618     CONSTEXPR_DCHECK(Linkage::kJSCallClosureParamIndex == -1);
619     CONSTEXPR_DCHECK(Linkage::GetJSCallNewTargetParamIndex(argc) == argc + 0);
620     CONSTEXPR_DCHECK(Linkage::GetJSCallArgCountParamIndex(argc) == argc + 1);
621     CONSTEXPR_DCHECK(Linkage::GetJSCallContextParamIndex(argc) == argc + 2);
622     return argc + kClosure + kNewTarget + kArgCount + kContext;
623   }
624 
FormalParameterCount()625   int FormalParameterCount() const {
626     DCHECK_GE(node()->op()->ValueOutputCount(),
627               kExtraOutputCount + kReceiverOutputCount);
628     return node()->op()->ValueOutputCount() - kExtraOutputCount;
629   }
630 
FormalParameterCountWithoutReceiver()631   int FormalParameterCountWithoutReceiver() const {
632     DCHECK_GE(node()->op()->ValueOutputCount(),
633               kExtraOutputCount + kReceiverOutputCount);
634     return node()->op()->ValueOutputCount() - kExtraOutputCount -
635            kReceiverOutputCount;
636   }
637 };
638 
639 #undef DEFINE_INPUT_ACCESSORS
640 
641 }  // namespace compiler
642 }  // namespace internal
643 }  // namespace v8
644 
645 #endif  // V8_COMPILER_COMMON_OPERATOR_H_
646