Line data Source code
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 13228 : inline BranchHint NegateBranchHint(BranchHint hint) {
31 13228 : switch (hint) {
32 : case BranchHint::kNone:
33 13224 : return hint;
34 : case BranchHint::kTrue:
35 : return BranchHint::kFalse;
36 : case BranchHint::kFalse:
37 2 : return BranchHint::kTrue;
38 : }
39 0 : UNREACHABLE();
40 : return hint;
41 : }
42 :
43 31398 : 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 10398 : : 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 39277598 : Node* Get(Node* empty_value) const {
193 39277598 : 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 128041144 : 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 13998784 : 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 32490986 : BitMaskType mask() const { return bit_mask_; }
217 :
218 5865373 : 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 : // The ArgumentsElementsState and ArgumentsLengthState can either describe an
301 : // unmapped arguments backing store or the backing store of the rest parameters.
302 : // IsRestOf(op) is true in the second case.
303 : bool IsRestOf(Operator const*);
304 :
305 : // Interface for building common operators that can be used at any level of IR,
306 : // including JavaScript, mid-level, and low-level.
307 : class V8_EXPORT_PRIVATE CommonOperatorBuilder final
308 : : public NON_EXPORTED_BASE(ZoneObject) {
309 : public:
310 : explicit CommonOperatorBuilder(Zone* zone);
311 :
312 : const Operator* Dead();
313 : const Operator* End(size_t control_input_count);
314 : const Operator* Branch(BranchHint = BranchHint::kNone);
315 : const Operator* IfTrue();
316 : const Operator* IfFalse();
317 : const Operator* IfSuccess();
318 : const Operator* IfException();
319 : const Operator* Switch(size_t control_output_count);
320 : const Operator* IfValue(int32_t value);
321 : const Operator* IfDefault();
322 : const Operator* Throw();
323 : const Operator* Deoptimize(DeoptimizeKind kind, DeoptimizeReason reason);
324 : const Operator* DeoptimizeIf(DeoptimizeKind kind, DeoptimizeReason reason);
325 : const Operator* DeoptimizeUnless(DeoptimizeKind kind,
326 : DeoptimizeReason reason);
327 : const Operator* TrapIf(int32_t trap_id);
328 : const Operator* TrapUnless(int32_t trap_id);
329 : const Operator* Return(int value_input_count = 1);
330 : const Operator* Terminate();
331 :
332 : const Operator* Start(int value_output_count);
333 : const Operator* Loop(int control_input_count);
334 : const Operator* Merge(int control_input_count);
335 : const Operator* Parameter(int index, const char* debug_name = nullptr);
336 :
337 : const Operator* OsrNormalEntry();
338 : const Operator* OsrLoopEntry();
339 : const Operator* OsrValue(int index);
340 : const Operator* OsrGuard(OsrGuardType type);
341 :
342 : const Operator* Int32Constant(int32_t);
343 : const Operator* Int64Constant(int64_t);
344 : const Operator* Float32Constant(volatile float);
345 : const Operator* Float64Constant(volatile double);
346 : const Operator* ExternalConstant(const ExternalReference&);
347 : const Operator* NumberConstant(volatile double);
348 : const Operator* PointerConstant(intptr_t);
349 : const Operator* HeapConstant(const Handle<HeapObject>&);
350 :
351 : const Operator* RelocatableInt32Constant(int32_t value,
352 : RelocInfo::Mode rmode);
353 : const Operator* RelocatableInt64Constant(int64_t value,
354 : RelocInfo::Mode rmode);
355 :
356 : const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone);
357 : const Operator* Phi(MachineRepresentation representation,
358 : int value_input_count);
359 : const Operator* EffectPhi(int effect_input_count);
360 : const Operator* InductionVariablePhi(int value_input_count);
361 : const Operator* LoopExit();
362 : const Operator* LoopExitValue();
363 : const Operator* LoopExitEffect();
364 : const Operator* Checkpoint();
365 : const Operator* BeginRegion(RegionObservability);
366 : const Operator* FinishRegion();
367 : const Operator* StateValues(int arguments, SparseInputMask bitmask);
368 : const Operator* TypedStateValues(const ZoneVector<MachineType>* types,
369 : SparseInputMask bitmask);
370 : const Operator* ArgumentsElementsState(bool is_rest);
371 : const Operator* ArgumentsLengthState(bool is_rest);
372 : const Operator* ObjectState(int pointer_slots);
373 : const Operator* TypedObjectState(const ZoneVector<MachineType>* types);
374 : const Operator* FrameState(BailoutId bailout_id,
375 : OutputFrameStateCombine state_combine,
376 : const FrameStateFunctionInfo* function_info);
377 : const Operator* Call(const CallDescriptor* descriptor);
378 : const Operator* TailCall(const CallDescriptor* descriptor);
379 : const Operator* Projection(size_t index);
380 : const Operator* Retain();
381 : const Operator* TypeGuard(Type* type);
382 :
383 : // Constructs a new merge or phi operator with the same opcode as {op}, but
384 : // with {size} inputs.
385 : const Operator* ResizeMergeOrPhi(const Operator* op, int size);
386 :
387 : // Constructs function info for frame state construction.
388 : const FrameStateFunctionInfo* CreateFrameStateFunctionInfo(
389 : FrameStateType type, int parameter_count, int local_count,
390 : Handle<SharedFunctionInfo> shared_info);
391 :
392 : private:
393 : Zone* zone() const { return zone_; }
394 :
395 : const CommonOperatorGlobalCache& cache_;
396 : Zone* const zone_;
397 :
398 : DISALLOW_COPY_AND_ASSIGN(CommonOperatorBuilder);
399 : };
400 :
401 : } // namespace compiler
402 : } // namespace internal
403 : } // namespace v8
404 :
405 : #endif // V8_COMPILER_COMMON_OPERATOR_H_
|