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 : #include "src/zone/zone-handle-set.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace compiler {
20 :
21 : // Forward declarations.
22 : class CallDescriptor;
23 : struct CommonOperatorGlobalCache;
24 : class Operator;
25 : class Type;
26 : class Node;
27 :
28 : // Prediction hint for branches.
29 : enum class BranchHint : uint8_t { kNone, kTrue, kFalse };
30 :
31 13723 : inline BranchHint NegateBranchHint(BranchHint hint) {
32 13723 : switch (hint) {
33 : case BranchHint::kNone:
34 9599 : return hint;
35 : case BranchHint::kTrue:
36 : return BranchHint::kFalse;
37 : case BranchHint::kFalse:
38 4120 : return BranchHint::kTrue;
39 : }
40 0 : UNREACHABLE();
41 : }
42 :
43 35864 : 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 : struct ObjectStateInfo final : std::pair<uint32_t, int> {
128 : ObjectStateInfo(uint32_t object_id, int size)
129 : : std::pair<uint32_t, int>(object_id, size) {}
130 : uint32_t object_id() const { return first; }
131 : int size() const { return second; }
132 : };
133 : std::ostream& operator<<(std::ostream&, ObjectStateInfo const&);
134 : size_t hash_value(ObjectStateInfo const& p);
135 :
136 : struct TypedObjectStateInfo final
137 : : std::pair<uint32_t, const ZoneVector<MachineType>*> {
138 : TypedObjectStateInfo(uint32_t object_id,
139 : const ZoneVector<MachineType>* machine_types)
140 : : std::pair<uint32_t, const ZoneVector<MachineType>*>(object_id,
141 : machine_types) {}
142 : uint32_t object_id() const { return first; }
143 : const ZoneVector<MachineType>* machine_types() const { return second; }
144 : };
145 : std::ostream& operator<<(std::ostream&, TypedObjectStateInfo const&);
146 : size_t hash_value(TypedObjectStateInfo const& p);
147 :
148 : class RelocatablePtrConstantInfo final {
149 : public:
150 : enum Type { kInt32, kInt64 };
151 :
152 : RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode)
153 2334 : : value_(value), rmode_(rmode), type_(kInt32) {}
154 : RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode)
155 : : value_(value), rmode_(rmode), type_(kInt64) {}
156 :
157 : intptr_t value() const { return value_; }
158 : RelocInfo::Mode rmode() const { return rmode_; }
159 : Type type() const { return type_; }
160 :
161 : private:
162 : intptr_t value_;
163 : RelocInfo::Mode rmode_;
164 : Type type_;
165 : };
166 :
167 : bool operator==(RelocatablePtrConstantInfo const& lhs,
168 : RelocatablePtrConstantInfo const& rhs);
169 : bool operator!=(RelocatablePtrConstantInfo const& lhs,
170 : RelocatablePtrConstantInfo const& rhs);
171 :
172 : std::ostream& operator<<(std::ostream&, RelocatablePtrConstantInfo const&);
173 :
174 : size_t hash_value(RelocatablePtrConstantInfo const& p);
175 :
176 : // Used to define a sparse set of inputs. This can be used to efficiently encode
177 : // nodes that can have a lot of inputs, but where many inputs can have the same
178 : // value.
179 : class SparseInputMask final {
180 : public:
181 : typedef uint32_t BitMaskType;
182 :
183 : // The mask representing a dense input set.
184 : static const BitMaskType kDenseBitMask = 0x0;
185 : // The bits representing the end of a sparse input set.
186 : static const BitMaskType kEndMarker = 0x1;
187 : // The mask for accessing a sparse input entry in the bitmask.
188 : static const BitMaskType kEntryMask = 0x1;
189 :
190 : // The number of bits in the mask, minus one for the end marker.
191 : static const int kMaxSparseInputs = (sizeof(BitMaskType) * kBitsPerByte - 1);
192 :
193 : // An iterator over a node's sparse inputs.
194 : class InputIterator final {
195 : public:
196 : InputIterator() {}
197 : InputIterator(BitMaskType bit_mask, Node* parent);
198 :
199 : Node* parent() const { return parent_; }
200 : int real_index() const { return real_index_; }
201 :
202 : // Advance the iterator to the next sparse input. Only valid if the iterator
203 : // has not reached the end.
204 : void Advance();
205 :
206 : // Get the current sparse input's real node value. Only valid if the
207 : // current sparse input is real.
208 : Node* GetReal() const;
209 :
210 : // Get the current sparse input, returning either a real input node if
211 : // the current sparse input is real, or the given {empty_value} if the
212 : // current sparse input is empty.
213 41620391 : Node* Get(Node* empty_value) const {
214 41620391 : return IsReal() ? GetReal() : empty_value;
215 : }
216 :
217 : // True if the current sparse input is a real input node.
218 : bool IsReal() const;
219 :
220 : // True if the current sparse input is an empty value.
221 136384183 : bool IsEmpty() const { return !IsReal(); }
222 :
223 : // True if the iterator has reached the end of the sparse inputs.
224 : bool IsEnd() const;
225 :
226 : private:
227 : BitMaskType bit_mask_;
228 : Node* parent_;
229 : int real_index_;
230 : };
231 :
232 9078999 : explicit SparseInputMask(BitMaskType bit_mask) : bit_mask_(bit_mask) {}
233 :
234 : // Provides a SparseInputMask representing a dense input set.
235 : static SparseInputMask Dense() { return SparseInputMask(kDenseBitMask); }
236 :
237 7255107 : BitMaskType mask() const { return bit_mask_; }
238 :
239 3674752 : bool IsDense() const { return bit_mask_ == SparseInputMask::kDenseBitMask; }
240 :
241 : // Counts how many real values are in the sparse array. Only valid for
242 : // non-dense masks.
243 : int CountReal() const;
244 :
245 : // Returns an iterator over the sparse inputs of {node}.
246 : InputIterator IterateOverInputs(Node* node);
247 :
248 : private:
249 : //
250 : // The sparse input mask has a bitmask specifying if the node's inputs are
251 : // represented sparsely. If the bitmask value is 0, then the inputs are dense;
252 : // otherwise, they should be interpreted as follows:
253 : //
254 : // * The bitmask represents which values are real, with 1 for real values
255 : // and 0 for empty values.
256 : // * The inputs to the node are the real values, in the order of the 1s from
257 : // least- to most-significant.
258 : // * The top bit of the bitmask is a guard indicating the end of the values,
259 : // whether real or empty (and is not representative of a real input
260 : // itself). This is used so that we don't have to additionally store a
261 : // value count.
262 : //
263 : // So, for N 1s in the bitmask, there are N - 1 inputs into the node.
264 : BitMaskType bit_mask_;
265 : };
266 :
267 : bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs);
268 : bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs);
269 :
270 : class TypedStateValueInfo final {
271 : public:
272 : TypedStateValueInfo(ZoneVector<MachineType> const* machine_types,
273 : SparseInputMask sparse_input_mask)
274 : : machine_types_(machine_types), sparse_input_mask_(sparse_input_mask) {}
275 :
276 : ZoneVector<MachineType> const* machine_types() const {
277 : return machine_types_;
278 : }
279 : SparseInputMask sparse_input_mask() const { return sparse_input_mask_; }
280 :
281 : private:
282 : ZoneVector<MachineType> const* machine_types_;
283 : SparseInputMask sparse_input_mask_;
284 : };
285 :
286 : bool operator==(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs);
287 : bool operator!=(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs);
288 :
289 : std::ostream& operator<<(std::ostream&, TypedStateValueInfo const&);
290 :
291 : size_t hash_value(TypedStateValueInfo const& p);
292 :
293 : // Used to mark a region (as identified by BeginRegion/FinishRegion) as either
294 : // JavaScript-observable or not (i.e. allocations are not JavaScript observable
295 : // themselves, but transitioning stores are).
296 : enum class RegionObservability : uint8_t { kObservable, kNotObservable };
297 :
298 : size_t hash_value(RegionObservability);
299 :
300 : std::ostream& operator<<(std::ostream&, RegionObservability);
301 :
302 : RegionObservability RegionObservabilityOf(Operator const*) WARN_UNUSED_RESULT;
303 :
304 : std::ostream& operator<<(std::ostream& os,
305 : const ZoneVector<MachineType>* types);
306 :
307 : Type* TypeGuardTypeOf(Operator const*) WARN_UNUSED_RESULT;
308 :
309 : int OsrValueIndexOf(Operator const*);
310 :
311 : SparseInputMask SparseInputMaskOf(Operator const*);
312 :
313 : ZoneVector<MachineType> const* MachineTypesOf(Operator const*)
314 : WARN_UNUSED_RESULT;
315 :
316 : // The ArgumentsElementsState and ArgumentsLengthState can describe the layout
317 : // for backing stores of arguments objects of various types:
318 : //
319 : // +------------------------------------+
320 : // - kUnmappedArguments: | arg0, ... argK-1, argK, ... argN-1 | {length:N}
321 : // +------------------------------------+
322 : // +------------------------------------+
323 : // - kMappedArguments: | hole, ... hole, argK, ... argN-1 | {length:N}
324 : // +------------------------------------+
325 : // +------------------+
326 : // - kRestParameter: | argK, ... argN-1 | {length:N-K}
327 : // +------------------+
328 : //
329 : // Here {K} represents the number for formal parameters of the active function,
330 : // whereas {N} represents the actual number of arguments passed at runtime.
331 : // Note that {N < K} can happen and causes {K} to be capped accordingly.
332 : //
333 : // Also note that it is possible for an arguments object of {kMappedArguments}
334 : // type to carry a backing store of {kUnappedArguments} type when {K == 0}.
335 : typedef CreateArgumentsType ArgumentsStateType;
336 :
337 : ArgumentsStateType ArgumentsStateTypeOf(Operator const*) WARN_UNUSED_RESULT;
338 :
339 : uint32_t ObjectIdOf(Operator const*);
340 :
341 : // Interface for building common operators that can be used at any level of IR,
342 : // including JavaScript, mid-level, and low-level.
343 : class V8_EXPORT_PRIVATE CommonOperatorBuilder final
344 : : public NON_EXPORTED_BASE(ZoneObject) {
345 : public:
346 : explicit CommonOperatorBuilder(Zone* zone);
347 :
348 : const Operator* Dead();
349 : const Operator* End(size_t control_input_count);
350 : const Operator* Branch(BranchHint = BranchHint::kNone);
351 : const Operator* IfTrue();
352 : const Operator* IfFalse();
353 : const Operator* IfSuccess();
354 : const Operator* IfException();
355 : const Operator* Switch(size_t control_output_count);
356 : const Operator* IfValue(int32_t value);
357 : const Operator* IfDefault();
358 : const Operator* Throw();
359 : const Operator* Deoptimize(DeoptimizeKind kind, DeoptimizeReason reason);
360 : const Operator* DeoptimizeIf(DeoptimizeKind kind, DeoptimizeReason reason);
361 : const Operator* DeoptimizeUnless(DeoptimizeKind kind,
362 : DeoptimizeReason reason);
363 : const Operator* TrapIf(int32_t trap_id);
364 : const Operator* TrapUnless(int32_t trap_id);
365 : const Operator* Return(int value_input_count = 1);
366 : const Operator* Terminate();
367 :
368 : const Operator* Start(int value_output_count);
369 : const Operator* Loop(int control_input_count);
370 : const Operator* Merge(int control_input_count);
371 : const Operator* Parameter(int index, const char* debug_name = nullptr);
372 :
373 : const Operator* OsrNormalEntry();
374 : const Operator* OsrLoopEntry();
375 : const Operator* OsrValue(int index);
376 :
377 : const Operator* Int32Constant(int32_t);
378 : const Operator* Int64Constant(int64_t);
379 : const Operator* Float32Constant(volatile float);
380 : const Operator* Float64Constant(volatile double);
381 : const Operator* ExternalConstant(const ExternalReference&);
382 : const Operator* NumberConstant(volatile double);
383 : const Operator* PointerConstant(intptr_t);
384 : const Operator* HeapConstant(const Handle<HeapObject>&);
385 : const Operator* ObjectId(uint32_t);
386 :
387 : const Operator* RelocatableInt32Constant(int32_t value,
388 : RelocInfo::Mode rmode);
389 : const Operator* RelocatableInt64Constant(int64_t value,
390 : RelocInfo::Mode rmode);
391 :
392 : const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone);
393 : const Operator* Phi(MachineRepresentation representation,
394 : int value_input_count);
395 : const Operator* EffectPhi(int effect_input_count);
396 : const Operator* InductionVariablePhi(int value_input_count);
397 : const Operator* LoopExit();
398 : const Operator* LoopExitValue();
399 : const Operator* LoopExitEffect();
400 : const Operator* Checkpoint();
401 : const Operator* BeginRegion(RegionObservability);
402 : const Operator* FinishRegion();
403 : const Operator* StateValues(int arguments, SparseInputMask bitmask);
404 : const Operator* TypedStateValues(const ZoneVector<MachineType>* types,
405 : SparseInputMask bitmask);
406 : const Operator* ArgumentsElementsState(ArgumentsStateType type);
407 : const Operator* ArgumentsLengthState(ArgumentsStateType type);
408 : const Operator* ObjectState(uint32_t object_id, int pointer_slots);
409 : const Operator* TypedObjectState(uint32_t object_id,
410 : const ZoneVector<MachineType>* types);
411 : const Operator* FrameState(BailoutId bailout_id,
412 : OutputFrameStateCombine state_combine,
413 : const FrameStateFunctionInfo* function_info);
414 : const Operator* Call(const CallDescriptor* descriptor);
415 : const Operator* CallWithCallerSavedRegisters(
416 : const CallDescriptor* descriptor);
417 : const Operator* TailCall(const CallDescriptor* descriptor);
418 : const Operator* Projection(size_t index);
419 : const Operator* Retain();
420 : const Operator* TypeGuard(Type* type);
421 :
422 : // Constructs a new merge or phi operator with the same opcode as {op}, but
423 : // with {size} inputs.
424 : const Operator* ResizeMergeOrPhi(const Operator* op, int size);
425 :
426 : // Constructs function info for frame state construction.
427 : const FrameStateFunctionInfo* CreateFrameStateFunctionInfo(
428 : FrameStateType type, int parameter_count, int local_count,
429 : Handle<SharedFunctionInfo> shared_info);
430 :
431 : private:
432 : Zone* zone() const { return zone_; }
433 :
434 : const CommonOperatorGlobalCache& cache_;
435 : Zone* const zone_;
436 :
437 : DISALLOW_COPY_AND_ASSIGN(CommonOperatorBuilder);
438 : };
439 :
440 : } // namespace compiler
441 : } // namespace internal
442 : } // namespace v8
443 :
444 : #endif // V8_COMPILER_COMMON_OPERATOR_H_
|