• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NegateBranchHint(BranchHint hint)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 
hash_value(BranchHint hint)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:
DeoptimizeParameters(DeoptimizeKind kind,DeoptimizeReason reason)55   DeoptimizeParameters(DeoptimizeKind kind, DeoptimizeReason reason)
56       : kind_(kind), reason_(reason) {}
57 
kind()58   DeoptimizeKind kind() const { return kind_; }
reason()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)
representation_(representation)80       : representation_(representation), hint_(hint) {}
81 
representation()82   MachineRepresentation representation() const { return representation_; }
hint()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:
ParameterInfo(int index,const char * debug_name)111   ParameterInfo(int index, const char* debug_name)
112       : index_(index), debug_name_(debug_name) {}
113 
index()114   int index() const { return index_; }
debug_name()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 
RelocatablePtrConstantInfo(int32_t value,RelocInfo::Mode rmode)131   RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode)
132       : value_(value), rmode_(rmode), type_(kInt32) {}
RelocatablePtrConstantInfo(int64_t value,RelocInfo::Mode rmode)133   RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode)
134       : value_(value), rmode_(rmode), type_(kInt64) {}
135 
value()136   intptr_t value() const { return value_; }
rmode()137   RelocInfo::Mode rmode() const { return rmode_; }
type()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:
InputIterator()175     InputIterator() {}
176     InputIterator(BitMaskType bit_mask, Node* parent);
177 
parent()178     Node* parent() const { return parent_; }
real_index()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.
Get(Node * empty_value)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.
IsEmpty()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 
SparseInputMask(BitMaskType bit_mask)211   explicit SparseInputMask(BitMaskType bit_mask) : bit_mask_(bit_mask) {}
212 
213   // Provides a SparseInputMask representing a dense input set.
Dense()214   static SparseInputMask Dense() { return SparseInputMask(kDenseBitMask); }
215 
mask()216   BitMaskType mask() const { return bit_mask_; }
217 
IsDense()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:
TypedStateValueInfo(ZoneVector<MachineType> const * machine_types,SparseInputMask sparse_input_mask)251   TypedStateValueInfo(ZoneVector<MachineType> const* machine_types,
252                       SparseInputMask sparse_input_mask)
253       : machine_types_(machine_types), sparse_input_mask_(sparse_input_mask) {}
254 
machine_types()255   ZoneVector<MachineType> const* machine_types() const {
256     return machine_types_;
257   }
sparse_input_mask()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
NON_EXPORTED_BASE(ZoneObject)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