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