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_SIMPLIFIED_OPERATOR_H_
6 #define V8_COMPILER_SIMPLIFIED_OPERATOR_H_
7 
8 #include <iosfwd>
9 
10 #include "src/base/compiler-specific.h"
11 #include "src/compiler/operator.h"
12 #include "src/compiler/types.h"
13 #include "src/globals.h"
14 #include "src/handles.h"
15 #include "src/machine-type.h"
16 #include "src/objects.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 // Forward declarations.
22 class Zone;
23 
24 namespace compiler {
25 
26 // Forward declarations.
27 class Operator;
28 struct SimplifiedOperatorGlobalCache;
29 
30 enum BaseTaggedness : uint8_t { kUntaggedBase, kTaggedBase };
31 
32 size_t hash_value(BaseTaggedness);
33 
34 std::ostream& operator<<(std::ostream&, BaseTaggedness);
35 
36 
37 // An access descriptor for loads/stores of array buffers.
38 class BufferAccess final {
39  public:
BufferAccess(ExternalArrayType external_array_type)40   explicit BufferAccess(ExternalArrayType external_array_type)
41       : external_array_type_(external_array_type) {}
42 
external_array_type()43   ExternalArrayType external_array_type() const { return external_array_type_; }
44   MachineType machine_type() const;
45 
46  private:
47   ExternalArrayType const external_array_type_;
48 };
49 
50 V8_EXPORT_PRIVATE bool operator==(BufferAccess, BufferAccess);
51 bool operator!=(BufferAccess, BufferAccess);
52 
53 size_t hash_value(BufferAccess);
54 
55 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BufferAccess);
56 
57 V8_EXPORT_PRIVATE BufferAccess const BufferAccessOf(const Operator* op)
58     WARN_UNUSED_RESULT;
59 
60 // An access descriptor for loads/stores of fixed structures like field
61 // accesses of heap objects. Accesses from either tagged or untagged base
62 // pointers are supported; untagging is done automatically during lowering.
63 struct FieldAccess {
64   BaseTaggedness base_is_tagged;  // specifies if the base pointer is tagged.
65   int offset;                     // offset of the field, without tag.
66   MaybeHandle<Name> name;         // debugging only.
67   Type* type;                     // type of the field.
68   MachineType machine_type;       // machine type of the field.
69   WriteBarrierKind write_barrier_kind;  // write barrier hint.
70 
tagFieldAccess71   int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
72 };
73 
74 V8_EXPORT_PRIVATE bool operator==(FieldAccess const&, FieldAccess const&);
75 bool operator!=(FieldAccess const&, FieldAccess const&);
76 
77 size_t hash_value(FieldAccess const&);
78 
79 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, FieldAccess const&);
80 
81 FieldAccess const& FieldAccessOf(const Operator* op) WARN_UNUSED_RESULT;
82 
83 template <>
84 void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
85                                             PrintVerbosity verbose) const;
86 
87 // An access descriptor for loads/stores of indexed structures like characters
88 // in strings or off-heap backing stores. Accesses from either tagged or
89 // untagged base pointers are supported; untagging is done automatically during
90 // lowering.
91 struct ElementAccess {
92   BaseTaggedness base_is_tagged;  // specifies if the base pointer is tagged.
93   int header_size;                // size of the header, without tag.
94   Type* type;                     // type of the element.
95   MachineType machine_type;       // machine type of the element.
96   WriteBarrierKind write_barrier_kind;  // write barrier hint.
97 
tagElementAccess98   int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
99 };
100 
101 V8_EXPORT_PRIVATE bool operator==(ElementAccess const&, ElementAccess const&);
102 bool operator!=(ElementAccess const&, ElementAccess const&);
103 
104 size_t hash_value(ElementAccess const&);
105 
106 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ElementAccess const&);
107 
108 V8_EXPORT_PRIVATE ElementAccess const& ElementAccessOf(const Operator* op)
109     WARN_UNUSED_RESULT;
110 
111 ExternalArrayType ExternalArrayTypeOf(const Operator* op) WARN_UNUSED_RESULT;
112 
113 enum class CheckFloat64HoleMode : uint8_t {
114   kNeverReturnHole,  // Never return the hole (deoptimize instead).
115   kAllowReturnHole   // Allow to return the hole (signaling NaN).
116 };
117 
118 size_t hash_value(CheckFloat64HoleMode);
119 
120 std::ostream& operator<<(std::ostream&, CheckFloat64HoleMode);
121 
122 CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator*) WARN_UNUSED_RESULT;
123 
124 enum class CheckTaggedInputMode : uint8_t {
125   kNumber,
126   kNumberOrOddball,
127 };
128 
129 size_t hash_value(CheckTaggedInputMode);
130 
131 std::ostream& operator<<(std::ostream&, CheckTaggedInputMode);
132 
133 CheckTaggedInputMode CheckTaggedInputModeOf(const Operator*) WARN_UNUSED_RESULT;
134 
135 enum class CheckForMinusZeroMode : uint8_t {
136   kCheckForMinusZero,
137   kDontCheckForMinusZero,
138 };
139 
140 size_t hash_value(CheckForMinusZeroMode);
141 
142 std::ostream& operator<<(std::ostream&, CheckForMinusZeroMode);
143 
144 CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator*) WARN_UNUSED_RESULT;
145 
146 // A descriptor for growing elements backing stores.
147 enum class GrowFastElementsFlag : uint8_t {
148   kNone = 0u,
149   kArrayObject = 1u << 0,     // Update JSArray::length field.
150   kHoleyElements = 1u << 1,   // Backing store is holey.
151   kDoubleElements = 1u << 2,  // Backing store contains doubles.
152 };
153 typedef base::Flags<GrowFastElementsFlag> GrowFastElementsFlags;
154 
155 DEFINE_OPERATORS_FOR_FLAGS(GrowFastElementsFlags)
156 
157 std::ostream& operator<<(std::ostream&, GrowFastElementsFlags);
158 
159 GrowFastElementsFlags GrowFastElementsFlagsOf(const Operator*)
160     WARN_UNUSED_RESULT;
161 
162 // A descriptor for elements kind transitions.
163 enum class ElementsTransition : uint8_t {
164   kFastTransition,  // simple transition, just updating the map.
165   kSlowTransition   // full transition, round-trip to the runtime.
166 };
167 
168 size_t hash_value(ElementsTransition);
169 
170 std::ostream& operator<<(std::ostream&, ElementsTransition);
171 
172 ElementsTransition ElementsTransitionOf(const Operator* op) WARN_UNUSED_RESULT;
173 
174 // A hint for speculative number operations.
175 enum class NumberOperationHint : uint8_t {
176   kSignedSmall,      // Inputs were always Smi so far, output was in Smi range.
177   kSigned32,         // Inputs and output were Signed32 so far.
178   kNumber,           // Inputs were Number, output was Number.
179   kNumberOrOddball,  // Inputs were Number or Oddball, output was Number.
180 };
181 
182 size_t hash_value(NumberOperationHint);
183 
184 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, NumberOperationHint);
185 
186 NumberOperationHint NumberOperationHintOf(const Operator* op)
187     WARN_UNUSED_RESULT;
188 
189 PretenureFlag PretenureFlagOf(const Operator* op) WARN_UNUSED_RESULT;
190 
191 UnicodeEncoding UnicodeEncodingOf(const Operator*) WARN_UNUSED_RESULT;
192 
193 // Interface for building simplified operators, which represent the
194 // medium-level operations of V8, including adding numbers, allocating objects,
195 // indexing into objects and arrays, etc.
196 // All operators are typed but many are representation independent.
197 
198 // Number values from JS can be in one of these representations:
199 //   - Tagged: word-sized integer that is either
200 //     - a signed small integer (31 or 32 bits plus a tag)
201 //     - a tagged pointer to a HeapNumber object that has a float64 field
202 //   - Int32: an untagged signed 32-bit integer
203 //   - Uint32: an untagged unsigned 32-bit integer
204 //   - Float64: an untagged float64
205 
206 // Additional representations for intermediate code or non-JS code:
207 //   - Int64: an untagged signed 64-bit integer
208 //   - Uint64: an untagged unsigned 64-bit integer
209 //   - Float32: an untagged float32
210 
211 // Boolean values can be:
212 //   - Bool: a tagged pointer to either the canonical JS #false or
213 //           the canonical JS #true object
214 //   - Bit: an untagged integer 0 or 1, but word-sized
215 class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
NON_EXPORTED_BASE(ZoneObject)216     : public NON_EXPORTED_BASE(ZoneObject) {
217  public:
218   explicit SimplifiedOperatorBuilder(Zone* zone);
219 
220   const Operator* BooleanNot();
221 
222   const Operator* NumberEqual();
223   const Operator* NumberLessThan();
224   const Operator* NumberLessThanOrEqual();
225   const Operator* NumberAdd();
226   const Operator* NumberSubtract();
227   const Operator* NumberMultiply();
228   const Operator* NumberDivide();
229   const Operator* NumberModulus();
230   const Operator* NumberBitwiseOr();
231   const Operator* NumberBitwiseXor();
232   const Operator* NumberBitwiseAnd();
233   const Operator* NumberShiftLeft();
234   const Operator* NumberShiftRight();
235   const Operator* NumberShiftRightLogical();
236   const Operator* NumberImul();
237   const Operator* NumberAbs();
238   const Operator* NumberClz32();
239   const Operator* NumberCeil();
240   const Operator* NumberFloor();
241   const Operator* NumberFround();
242   const Operator* NumberAcos();
243   const Operator* NumberAcosh();
244   const Operator* NumberAsin();
245   const Operator* NumberAsinh();
246   const Operator* NumberAtan();
247   const Operator* NumberAtan2();
248   const Operator* NumberAtanh();
249   const Operator* NumberCbrt();
250   const Operator* NumberCos();
251   const Operator* NumberCosh();
252   const Operator* NumberExp();
253   const Operator* NumberExpm1();
254   const Operator* NumberLog();
255   const Operator* NumberLog1p();
256   const Operator* NumberLog10();
257   const Operator* NumberLog2();
258   const Operator* NumberMax();
259   const Operator* NumberMin();
260   const Operator* NumberPow();
261   const Operator* NumberRound();
262   const Operator* NumberSign();
263   const Operator* NumberSin();
264   const Operator* NumberSinh();
265   const Operator* NumberSqrt();
266   const Operator* NumberTan();
267   const Operator* NumberTanh();
268   const Operator* NumberTrunc();
269   const Operator* NumberToBoolean();
270   const Operator* NumberToInt32();
271   const Operator* NumberToUint32();
272   const Operator* NumberToUint8Clamped();
273 
274   const Operator* NumberSilenceNaN();
275 
276   const Operator* SpeculativeNumberAdd(NumberOperationHint hint);
277   const Operator* SpeculativeNumberSubtract(NumberOperationHint hint);
278   const Operator* SpeculativeNumberMultiply(NumberOperationHint hint);
279   const Operator* SpeculativeNumberDivide(NumberOperationHint hint);
280   const Operator* SpeculativeNumberModulus(NumberOperationHint hint);
281   const Operator* SpeculativeNumberShiftLeft(NumberOperationHint hint);
282   const Operator* SpeculativeNumberShiftRight(NumberOperationHint hint);
283   const Operator* SpeculativeNumberShiftRightLogical(NumberOperationHint hint);
284   const Operator* SpeculativeNumberBitwiseAnd(NumberOperationHint hint);
285   const Operator* SpeculativeNumberBitwiseOr(NumberOperationHint hint);
286   const Operator* SpeculativeNumberBitwiseXor(NumberOperationHint hint);
287 
288   const Operator* SpeculativeNumberLessThan(NumberOperationHint hint);
289   const Operator* SpeculativeNumberLessThanOrEqual(NumberOperationHint hint);
290   const Operator* SpeculativeNumberEqual(NumberOperationHint hint);
291 
292   const Operator* ReferenceEqual();
293 
294   const Operator* StringEqual();
295   const Operator* StringLessThan();
296   const Operator* StringLessThanOrEqual();
297   const Operator* StringCharCodeAt();
298   const Operator* StringFromCharCode();
299   const Operator* StringFromCodePoint(UnicodeEncoding encoding);
300 
301   const Operator* PlainPrimitiveToNumber();
302   const Operator* PlainPrimitiveToWord32();
303   const Operator* PlainPrimitiveToFloat64();
304 
305   const Operator* ChangeTaggedSignedToInt32();
306   const Operator* ChangeTaggedToInt32();
307   const Operator* ChangeTaggedToUint32();
308   const Operator* ChangeTaggedToFloat64();
309   const Operator* ChangeInt31ToTaggedSigned();
310   const Operator* ChangeInt32ToTagged();
311   const Operator* ChangeUint32ToTagged();
312   const Operator* ChangeFloat64ToTagged();
313   const Operator* ChangeFloat64ToTaggedPointer();
314   const Operator* ChangeTaggedToBit();
315   const Operator* ChangeBitToTagged();
316   const Operator* TruncateTaggedToWord32();
317   const Operator* TruncateTaggedToFloat64();
318   const Operator* TruncateTaggedToBit();
319 
320   const Operator* CheckIf();
321   const Operator* CheckBounds();
322   const Operator* CheckMaps(int map_input_count);
323 
324   const Operator* CheckHeapObject();
325   const Operator* CheckNumber();
326   const Operator* CheckSmi();
327   const Operator* CheckString();
328 
329   const Operator* CheckedInt32Add();
330   const Operator* CheckedInt32Sub();
331   const Operator* CheckedInt32Div();
332   const Operator* CheckedInt32Mod();
333   const Operator* CheckedUint32Div();
334   const Operator* CheckedUint32Mod();
335   const Operator* CheckedInt32Mul(CheckForMinusZeroMode);
336   const Operator* CheckedInt32ToTaggedSigned();
337   const Operator* CheckedUint32ToInt32();
338   const Operator* CheckedUint32ToTaggedSigned();
339   const Operator* CheckedFloat64ToInt32(CheckForMinusZeroMode);
340   const Operator* CheckedTaggedSignedToInt32();
341   const Operator* CheckedTaggedToInt32(CheckForMinusZeroMode);
342   const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode);
343   const Operator* CheckedTaggedToTaggedSigned();
344   const Operator* CheckedTaggedToTaggedPointer();
345   const Operator* CheckedTruncateTaggedToWord32();
346 
347   const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
348   const Operator* CheckTaggedHole();
349   const Operator* ConvertTaggedHoleToUndefined();
350 
351   const Operator* ObjectIsCallable();
352   const Operator* ObjectIsNumber();
353   const Operator* ObjectIsReceiver();
354   const Operator* ObjectIsSmi();
355   const Operator* ObjectIsString();
356   const Operator* ObjectIsUndetectable();
357 
358   // array-buffer-was-neutered buffer
359   const Operator* ArrayBufferWasNeutered();
360 
361   // ensure-writable-fast-elements object, elements
362   const Operator* EnsureWritableFastElements();
363 
364   // maybe-grow-fast-elements object, elements, index, length
365   const Operator* MaybeGrowFastElements(GrowFastElementsFlags flags);
366 
367   // transition-elements-kind object, from-map, to-map
368   const Operator* TransitionElementsKind(ElementsTransition transition);
369 
370   const Operator* Allocate(PretenureFlag pretenure = NOT_TENURED);
371 
372   const Operator* LoadField(FieldAccess const&);
373   const Operator* StoreField(FieldAccess const&);
374 
375   // load-buffer buffer, offset, length
376   const Operator* LoadBuffer(BufferAccess);
377 
378   // store-buffer buffer, offset, length, value
379   const Operator* StoreBuffer(BufferAccess);
380 
381   // load-element [base + index]
382   const Operator* LoadElement(ElementAccess const&);
383 
384   // store-element [base + index], value
385   const Operator* StoreElement(ElementAccess const&);
386 
387   // load-typed-element buffer, [base + external + index]
388   const Operator* LoadTypedElement(ExternalArrayType const&);
389 
390   // store-typed-element buffer, [base + external + index], value
391   const Operator* StoreTypedElement(ExternalArrayType const&);
392 
393  private:
394   Zone* zone() const { return zone_; }
395 
396   const SimplifiedOperatorGlobalCache& cache_;
397   Zone* const zone_;
398 
399   DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorBuilder);
400 };
401 
402 }  // namespace compiler
403 }  // namespace internal
404 }  // namespace v8
405 
406 #endif  // V8_COMPILER_SIMPLIFIED_OPERATOR_H_
407