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