• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 #include "src/compiler/simplified-operator.h"
6 
7 #include "src/base/lazy-instance.h"
8 #include "src/compiler/opcodes.h"
9 #include "src/compiler/operator.h"
10 #include "src/compiler/types.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
hash_value(BaseTaggedness base_taggedness)16 size_t hash_value(BaseTaggedness base_taggedness) {
17   return static_cast<uint8_t>(base_taggedness);
18 }
19 
operator <<(std::ostream & os,BaseTaggedness base_taggedness)20 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
21   switch (base_taggedness) {
22     case kUntaggedBase:
23       return os << "untagged base";
24     case kTaggedBase:
25       return os << "tagged base";
26   }
27   UNREACHABLE();
28   return os;
29 }
30 
31 
machine_type() const32 MachineType BufferAccess::machine_type() const {
33   switch (external_array_type_) {
34     case kExternalUint8Array:
35     case kExternalUint8ClampedArray:
36       return MachineType::Uint8();
37     case kExternalInt8Array:
38       return MachineType::Int8();
39     case kExternalUint16Array:
40       return MachineType::Uint16();
41     case kExternalInt16Array:
42       return MachineType::Int16();
43     case kExternalUint32Array:
44       return MachineType::Uint32();
45     case kExternalInt32Array:
46       return MachineType::Int32();
47     case kExternalFloat32Array:
48       return MachineType::Float32();
49     case kExternalFloat64Array:
50       return MachineType::Float64();
51   }
52   UNREACHABLE();
53   return MachineType::None();
54 }
55 
56 
operator ==(BufferAccess lhs,BufferAccess rhs)57 bool operator==(BufferAccess lhs, BufferAccess rhs) {
58   return lhs.external_array_type() == rhs.external_array_type();
59 }
60 
61 
operator !=(BufferAccess lhs,BufferAccess rhs)62 bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); }
63 
64 
hash_value(BufferAccess access)65 size_t hash_value(BufferAccess access) {
66   return base::hash<ExternalArrayType>()(access.external_array_type());
67 }
68 
69 
operator <<(std::ostream & os,BufferAccess access)70 std::ostream& operator<<(std::ostream& os, BufferAccess access) {
71   switch (access.external_array_type()) {
72 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
73   case kExternal##Type##Array:                          \
74     return os << #Type;
75     TYPED_ARRAYS(TYPED_ARRAY_CASE)
76 #undef TYPED_ARRAY_CASE
77   }
78   UNREACHABLE();
79   return os;
80 }
81 
82 
BufferAccessOf(const Operator * op)83 BufferAccess const BufferAccessOf(const Operator* op) {
84   DCHECK(op->opcode() == IrOpcode::kLoadBuffer ||
85          op->opcode() == IrOpcode::kStoreBuffer);
86   return OpParameter<BufferAccess>(op);
87 }
88 
89 
operator ==(FieldAccess const & lhs,FieldAccess const & rhs)90 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
91   // On purpose we don't include the write barrier kind here, as this method is
92   // really only relevant for eliminating loads and they don't care about the
93   // write barrier mode.
94   return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
95          lhs.map.address() == rhs.map.address() &&
96          lhs.machine_type == rhs.machine_type;
97 }
98 
99 
operator !=(FieldAccess const & lhs,FieldAccess const & rhs)100 bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) {
101   return !(lhs == rhs);
102 }
103 
104 
hash_value(FieldAccess const & access)105 size_t hash_value(FieldAccess const& access) {
106   // On purpose we don't include the write barrier kind here, as this method is
107   // really only relevant for eliminating loads and they don't care about the
108   // write barrier mode.
109   return base::hash_combine(access.base_is_tagged, access.offset,
110                             access.machine_type);
111 }
112 
113 
operator <<(std::ostream & os,FieldAccess const & access)114 std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
115   os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
116 #ifdef OBJECT_PRINT
117   Handle<Name> name;
118   if (access.name.ToHandle(&name)) {
119     name->Print(os);
120     os << ", ";
121   }
122   Handle<Map> map;
123   if (access.map.ToHandle(&map)) {
124     os << Brief(*map) << ", ";
125   }
126 #endif
127   access.type->PrintTo(os);
128   os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]";
129   return os;
130 }
131 
132 template <>
PrintParameter(std::ostream & os,PrintVerbosity verbose) const133 void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
134                                             PrintVerbosity verbose) const {
135   if (verbose == PrintVerbosity::kVerbose) {
136     os << parameter();
137   } else {
138     os << "[+" << parameter().offset << "]";
139   }
140 }
141 
operator ==(ElementAccess const & lhs,ElementAccess const & rhs)142 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
143   // On purpose we don't include the write barrier kind here, as this method is
144   // really only relevant for eliminating loads and they don't care about the
145   // write barrier mode.
146   return lhs.base_is_tagged == rhs.base_is_tagged &&
147          lhs.header_size == rhs.header_size &&
148          lhs.machine_type == rhs.machine_type;
149 }
150 
151 
operator !=(ElementAccess const & lhs,ElementAccess const & rhs)152 bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) {
153   return !(lhs == rhs);
154 }
155 
156 
hash_value(ElementAccess const & access)157 size_t hash_value(ElementAccess const& access) {
158   // On purpose we don't include the write barrier kind here, as this method is
159   // really only relevant for eliminating loads and they don't care about the
160   // write barrier mode.
161   return base::hash_combine(access.base_is_tagged, access.header_size,
162                             access.machine_type);
163 }
164 
165 
operator <<(std::ostream & os,ElementAccess const & access)166 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
167   os << access.base_is_tagged << ", " << access.header_size << ", ";
168   access.type->PrintTo(os);
169   os << ", " << access.machine_type << ", " << access.write_barrier_kind;
170   return os;
171 }
172 
173 
FieldAccessOf(const Operator * op)174 const FieldAccess& FieldAccessOf(const Operator* op) {
175   DCHECK_NOT_NULL(op);
176   DCHECK(op->opcode() == IrOpcode::kLoadField ||
177          op->opcode() == IrOpcode::kStoreField);
178   return OpParameter<FieldAccess>(op);
179 }
180 
181 
ElementAccessOf(const Operator * op)182 const ElementAccess& ElementAccessOf(const Operator* op) {
183   DCHECK_NOT_NULL(op);
184   DCHECK(op->opcode() == IrOpcode::kLoadElement ||
185          op->opcode() == IrOpcode::kStoreElement);
186   return OpParameter<ElementAccess>(op);
187 }
188 
ExternalArrayTypeOf(const Operator * op)189 ExternalArrayType ExternalArrayTypeOf(const Operator* op) {
190   DCHECK(op->opcode() == IrOpcode::kLoadTypedElement ||
191          op->opcode() == IrOpcode::kStoreTypedElement);
192   return OpParameter<ExternalArrayType>(op);
193 }
194 
hash_value(CheckFloat64HoleMode mode)195 size_t hash_value(CheckFloat64HoleMode mode) {
196   return static_cast<size_t>(mode);
197 }
198 
operator <<(std::ostream & os,CheckFloat64HoleMode mode)199 std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
200   switch (mode) {
201     case CheckFloat64HoleMode::kAllowReturnHole:
202       return os << "allow-return-hole";
203     case CheckFloat64HoleMode::kNeverReturnHole:
204       return os << "never-return-hole";
205   }
206   UNREACHABLE();
207   return os;
208 }
209 
CheckFloat64HoleModeOf(const Operator * op)210 CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) {
211   DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
212   return OpParameter<CheckFloat64HoleMode>(op);
213 }
214 
CheckMinusZeroModeOf(const Operator * op)215 CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
216   DCHECK(op->opcode() == IrOpcode::kCheckedInt32Mul ||
217          op->opcode() == IrOpcode::kCheckedFloat64ToInt32 ||
218          op->opcode() == IrOpcode::kCheckedTaggedToInt32);
219   return OpParameter<CheckForMinusZeroMode>(op);
220 }
221 
hash_value(CheckForMinusZeroMode mode)222 size_t hash_value(CheckForMinusZeroMode mode) {
223   return static_cast<size_t>(mode);
224 }
225 
operator <<(std::ostream & os,CheckForMinusZeroMode mode)226 std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
227   switch (mode) {
228     case CheckForMinusZeroMode::kCheckForMinusZero:
229       return os << "check-for-minus-zero";
230     case CheckForMinusZeroMode::kDontCheckForMinusZero:
231       return os << "dont-check-for-minus-zero";
232   }
233   UNREACHABLE();
234   return os;
235 }
236 
operator <<(std::ostream & os,CheckMapsFlags flags)237 std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
238   bool empty = true;
239   if (flags & CheckMapsFlag::kTryMigrateInstance) {
240     os << "TryMigrateInstance";
241     empty = false;
242   }
243   if (empty) os << "None";
244   return os;
245 }
246 
operator ==(CheckMapsParameters const & lhs,CheckMapsParameters const & rhs)247 bool operator==(CheckMapsParameters const& lhs,
248                 CheckMapsParameters const& rhs) {
249   return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps();
250 }
251 
operator !=(CheckMapsParameters const & lhs,CheckMapsParameters const & rhs)252 bool operator!=(CheckMapsParameters const& lhs,
253                 CheckMapsParameters const& rhs) {
254   return !(lhs == rhs);
255 }
256 
hash_value(CheckMapsParameters const & p)257 size_t hash_value(CheckMapsParameters const& p) {
258   return base::hash_combine(p.flags(), p.maps());
259 }
260 
operator <<(std::ostream & os,CheckMapsParameters const & p)261 std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
262   ZoneHandleSet<Map> const& maps = p.maps();
263   os << p.flags();
264   for (size_t i = 0; i < maps.size(); ++i) {
265     os << ", " << Brief(*maps[i]);
266   }
267   return os;
268 }
269 
CheckMapsParametersOf(Operator const * op)270 CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
271   DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode());
272   return OpParameter<CheckMapsParameters>(op);
273 }
274 
hash_value(CheckTaggedInputMode mode)275 size_t hash_value(CheckTaggedInputMode mode) {
276   return static_cast<size_t>(mode);
277 }
278 
operator <<(std::ostream & os,CheckTaggedInputMode mode)279 std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
280   switch (mode) {
281     case CheckTaggedInputMode::kNumber:
282       return os << "Number";
283     case CheckTaggedInputMode::kNumberOrOddball:
284       return os << "NumberOrOddball";
285   }
286   UNREACHABLE();
287   return os;
288 }
289 
CheckTaggedInputModeOf(const Operator * op)290 CheckTaggedInputMode CheckTaggedInputModeOf(const Operator* op) {
291   DCHECK_EQ(IrOpcode::kCheckedTaggedToFloat64, op->opcode());
292   return OpParameter<CheckTaggedInputMode>(op);
293 }
294 
operator <<(std::ostream & os,GrowFastElementsFlags flags)295 std::ostream& operator<<(std::ostream& os, GrowFastElementsFlags flags) {
296   bool empty = true;
297   if (flags & GrowFastElementsFlag::kArrayObject) {
298     os << "ArrayObject";
299     empty = false;
300   }
301   if (flags & GrowFastElementsFlag::kDoubleElements) {
302     if (!empty) os << "|";
303     os << "DoubleElements";
304     empty = false;
305   }
306   if (flags & GrowFastElementsFlag::kHoleyElements) {
307     if (!empty) os << "|";
308     os << "HoleyElements";
309     empty = false;
310   }
311   if (empty) os << "None";
312   return os;
313 }
314 
GrowFastElementsFlagsOf(const Operator * op)315 GrowFastElementsFlags GrowFastElementsFlagsOf(const Operator* op) {
316   DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode());
317   return OpParameter<GrowFastElementsFlags>(op);
318 }
319 
operator ==(ElementsTransition const & lhs,ElementsTransition const & rhs)320 bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) {
321   return lhs.mode() == rhs.mode() &&
322          lhs.source().address() == rhs.source().address() &&
323          lhs.target().address() == rhs.target().address();
324 }
325 
operator !=(ElementsTransition const & lhs,ElementsTransition const & rhs)326 bool operator!=(ElementsTransition const& lhs, ElementsTransition const& rhs) {
327   return !(lhs == rhs);
328 }
329 
hash_value(ElementsTransition transition)330 size_t hash_value(ElementsTransition transition) {
331   return base::hash_combine(static_cast<uint8_t>(transition.mode()),
332                             transition.source().address(),
333                             transition.target().address());
334 }
335 
operator <<(std::ostream & os,ElementsTransition transition)336 std::ostream& operator<<(std::ostream& os, ElementsTransition transition) {
337   switch (transition.mode()) {
338     case ElementsTransition::kFastTransition:
339       return os << "fast-transition from " << Brief(*transition.source())
340                 << " to " << Brief(*transition.target());
341     case ElementsTransition::kSlowTransition:
342       return os << "slow-transition from " << Brief(*transition.source())
343                 << " to " << Brief(*transition.target());
344   }
345   UNREACHABLE();
346   return os;
347 }
348 
ElementsTransitionOf(const Operator * op)349 ElementsTransition const& ElementsTransitionOf(const Operator* op) {
350   DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode());
351   return OpParameter<ElementsTransition>(op);
352 }
353 
operator <<(std::ostream & os,NumberOperationHint hint)354 std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) {
355   switch (hint) {
356     case NumberOperationHint::kSignedSmall:
357       return os << "SignedSmall";
358     case NumberOperationHint::kSigned32:
359       return os << "Signed32";
360     case NumberOperationHint::kNumber:
361       return os << "Number";
362     case NumberOperationHint::kNumberOrOddball:
363       return os << "NumberOrOddball";
364   }
365   UNREACHABLE();
366   return os;
367 }
368 
hash_value(NumberOperationHint hint)369 size_t hash_value(NumberOperationHint hint) {
370   return static_cast<uint8_t>(hint);
371 }
372 
NumberOperationHintOf(const Operator * op)373 NumberOperationHint NumberOperationHintOf(const Operator* op) {
374   DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
375          op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
376          op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
377          op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
378          op->opcode() == IrOpcode::kSpeculativeNumberModulus ||
379          op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft ||
380          op->opcode() == IrOpcode::kSpeculativeNumberShiftRight ||
381          op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical ||
382          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseAnd ||
383          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseOr ||
384          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseXor ||
385          op->opcode() == IrOpcode::kSpeculativeNumberEqual ||
386          op->opcode() == IrOpcode::kSpeculativeNumberLessThan ||
387          op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual);
388   return OpParameter<NumberOperationHint>(op);
389 }
390 
ParameterCountOf(const Operator * op)391 int ParameterCountOf(const Operator* op) {
392   DCHECK(op->opcode() == IrOpcode::kNewUnmappedArgumentsElements ||
393          op->opcode() == IrOpcode::kNewRestParameterElements);
394   return OpParameter<int>(op);
395 }
396 
PretenureFlagOf(const Operator * op)397 PretenureFlag PretenureFlagOf(const Operator* op) {
398   DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
399   return OpParameter<PretenureFlag>(op);
400 }
401 
UnicodeEncodingOf(const Operator * op)402 UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
403   DCHECK(op->opcode() == IrOpcode::kStringFromCodePoint);
404   return OpParameter<UnicodeEncoding>(op);
405 }
406 
407 #define PURE_OP_LIST(V)                                          \
408   V(BooleanNot, Operator::kNoProperties, 1, 0)                   \
409   V(NumberEqual, Operator::kCommutative, 2, 0)                   \
410   V(NumberLessThan, Operator::kNoProperties, 2, 0)               \
411   V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
412   V(NumberAdd, Operator::kCommutative, 2, 0)                     \
413   V(NumberSubtract, Operator::kNoProperties, 2, 0)               \
414   V(NumberMultiply, Operator::kCommutative, 2, 0)                \
415   V(NumberDivide, Operator::kNoProperties, 2, 0)                 \
416   V(NumberModulus, Operator::kNoProperties, 2, 0)                \
417   V(NumberBitwiseOr, Operator::kCommutative, 2, 0)               \
418   V(NumberBitwiseXor, Operator::kCommutative, 2, 0)              \
419   V(NumberBitwiseAnd, Operator::kCommutative, 2, 0)              \
420   V(NumberShiftLeft, Operator::kNoProperties, 2, 0)              \
421   V(NumberShiftRight, Operator::kNoProperties, 2, 0)             \
422   V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0)      \
423   V(NumberImul, Operator::kCommutative, 2, 0)                    \
424   V(NumberAbs, Operator::kNoProperties, 1, 0)                    \
425   V(NumberClz32, Operator::kNoProperties, 1, 0)                  \
426   V(NumberCeil, Operator::kNoProperties, 1, 0)                   \
427   V(NumberFloor, Operator::kNoProperties, 1, 0)                  \
428   V(NumberFround, Operator::kNoProperties, 1, 0)                 \
429   V(NumberAcos, Operator::kNoProperties, 1, 0)                   \
430   V(NumberAcosh, Operator::kNoProperties, 1, 0)                  \
431   V(NumberAsin, Operator::kNoProperties, 1, 0)                   \
432   V(NumberAsinh, Operator::kNoProperties, 1, 0)                  \
433   V(NumberAtan, Operator::kNoProperties, 1, 0)                   \
434   V(NumberAtan2, Operator::kNoProperties, 2, 0)                  \
435   V(NumberAtanh, Operator::kNoProperties, 1, 0)                  \
436   V(NumberCbrt, Operator::kNoProperties, 1, 0)                   \
437   V(NumberCos, Operator::kNoProperties, 1, 0)                    \
438   V(NumberCosh, Operator::kNoProperties, 1, 0)                   \
439   V(NumberExp, Operator::kNoProperties, 1, 0)                    \
440   V(NumberExpm1, Operator::kNoProperties, 1, 0)                  \
441   V(NumberLog, Operator::kNoProperties, 1, 0)                    \
442   V(NumberLog1p, Operator::kNoProperties, 1, 0)                  \
443   V(NumberLog10, Operator::kNoProperties, 1, 0)                  \
444   V(NumberLog2, Operator::kNoProperties, 1, 0)                   \
445   V(NumberMax, Operator::kNoProperties, 2, 0)                    \
446   V(NumberMin, Operator::kNoProperties, 2, 0)                    \
447   V(NumberPow, Operator::kNoProperties, 2, 0)                    \
448   V(NumberRound, Operator::kNoProperties, 1, 0)                  \
449   V(NumberSign, Operator::kNoProperties, 1, 0)                   \
450   V(NumberSin, Operator::kNoProperties, 1, 0)                    \
451   V(NumberSinh, Operator::kNoProperties, 1, 0)                   \
452   V(NumberSqrt, Operator::kNoProperties, 1, 0)                   \
453   V(NumberTan, Operator::kNoProperties, 1, 0)                    \
454   V(NumberTanh, Operator::kNoProperties, 1, 0)                   \
455   V(NumberTrunc, Operator::kNoProperties, 1, 0)                  \
456   V(NumberToBoolean, Operator::kNoProperties, 1, 0)              \
457   V(NumberToInt32, Operator::kNoProperties, 1, 0)                \
458   V(NumberToUint32, Operator::kNoProperties, 1, 0)               \
459   V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0)         \
460   V(NumberSilenceNaN, Operator::kNoProperties, 1, 0)             \
461   V(StringCharAt, Operator::kNoProperties, 2, 1)                 \
462   V(StringCharCodeAt, Operator::kNoProperties, 2, 1)             \
463   V(StringFromCharCode, Operator::kNoProperties, 1, 0)           \
464   V(StringIndexOf, Operator::kNoProperties, 3, 0)                \
465   V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0)       \
466   V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0)       \
467   V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0)      \
468   V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0)    \
469   V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0)          \
470   V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0)         \
471   V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0)        \
472   V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0)   \
473   V(ChangeFloat64ToTagged, Operator::kNoProperties, 1, 0)        \
474   V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \
475   V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0)    \
476   V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0)          \
477   V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0)         \
478   V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0)            \
479   V(ChangeBitToTagged, Operator::kNoProperties, 1, 0)            \
480   V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0)          \
481   V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0)       \
482   V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0)      \
483   V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0)   \
484   V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0)          \
485   V(ObjectIsNumber, Operator::kNoProperties, 1, 0)               \
486   V(ObjectIsReceiver, Operator::kNoProperties, 1, 0)             \
487   V(ObjectIsSmi, Operator::kNoProperties, 1, 0)                  \
488   V(ObjectIsString, Operator::kNoProperties, 1, 0)               \
489   V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0)         \
490   V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
491   V(ReferenceEqual, Operator::kCommutative, 2, 0)                \
492   V(StringEqual, Operator::kCommutative, 2, 0)                   \
493   V(StringLessThan, Operator::kNoProperties, 2, 0)               \
494   V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0)
495 
496 #define SPECULATIVE_NUMBER_BINOP_LIST(V)      \
497   SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
498   V(SpeculativeNumberEqual)                   \
499   V(SpeculativeNumberLessThan)                \
500   V(SpeculativeNumberLessThanOrEqual)
501 
502 #define CHECKED_OP_LIST(V)              \
503   V(CheckBounds, 2, 1)                  \
504   V(CheckHeapObject, 1, 1)              \
505   V(CheckIf, 1, 0)                      \
506   V(CheckInternalizedString, 1, 1)      \
507   V(CheckNumber, 1, 1)                  \
508   V(CheckReceiver, 1, 1)                \
509   V(CheckSmi, 1, 1)                     \
510   V(CheckString, 1, 1)                  \
511   V(CheckTaggedHole, 1, 1)              \
512   V(CheckedInt32Add, 2, 1)              \
513   V(CheckedInt32Sub, 2, 1)              \
514   V(CheckedInt32Div, 2, 1)              \
515   V(CheckedInt32Mod, 2, 1)              \
516   V(CheckedUint32Div, 2, 1)             \
517   V(CheckedUint32Mod, 2, 1)             \
518   V(CheckedUint32ToInt32, 1, 1)         \
519   V(CheckedUint32ToTaggedSigned, 1, 1)  \
520   V(CheckedInt32ToTaggedSigned, 1, 1)   \
521   V(CheckedTaggedSignedToInt32, 1, 1)   \
522   V(CheckedTaggedToTaggedSigned, 1, 1)  \
523   V(CheckedTaggedToTaggedPointer, 1, 1) \
524   V(CheckedTruncateTaggedToWord32, 1, 1)
525 
526 struct SimplifiedOperatorGlobalCache final {
527 #define PURE(Name, properties, value_input_count, control_input_count)     \
528   struct Name##Operator final : public Operator {                          \
529     Name##Operator()                                                       \
530         : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
531                    value_input_count, 0, control_input_count, 1, 0, 0) {}  \
532   };                                                                       \
533   Name##Operator k##Name;
534   PURE_OP_LIST(PURE)
535 #undef PURE
536 
537 #define CHECKED(Name, value_input_count, value_output_count)             \
538   struct Name##Operator final : public Operator {                        \
539     Name##Operator()                                                     \
540         : Operator(IrOpcode::k##Name,                                    \
541                    Operator::kFoldable | Operator::kNoThrow, #Name,      \
542                    value_input_count, 1, 1, value_output_count, 1, 0) {} \
543   };                                                                     \
544   Name##Operator k##Name;
545   CHECKED_OP_LIST(CHECKED)
546 #undef CHECKED
547 
548   template <UnicodeEncoding kEncoding>
549   struct StringFromCodePointOperator final : public Operator1<UnicodeEncoding> {
StringFromCodePointOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::StringFromCodePointOperator550     StringFromCodePointOperator()
551         : Operator1<UnicodeEncoding>(IrOpcode::kStringFromCodePoint,
552                                      Operator::kPure, "StringFromCodePoint", 1,
553                                      0, 0, 1, 0, 0, kEncoding) {}
554   };
555   StringFromCodePointOperator<UnicodeEncoding::UTF16>
556       kStringFromCodePointOperatorUTF16;
557   StringFromCodePointOperator<UnicodeEncoding::UTF32>
558       kStringFromCodePointOperatorUTF32;
559 
560   struct ArrayBufferWasNeuteredOperator final : public Operator {
ArrayBufferWasNeuteredOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::ArrayBufferWasNeuteredOperator561     ArrayBufferWasNeuteredOperator()
562         : Operator(IrOpcode::kArrayBufferWasNeutered, Operator::kEliminatable,
563                    "ArrayBufferWasNeutered", 1, 1, 1, 1, 1, 0) {}
564   };
565   ArrayBufferWasNeuteredOperator kArrayBufferWasNeutered;
566 
567   template <CheckForMinusZeroMode kMode>
568   struct CheckedInt32MulOperator final
569       : public Operator1<CheckForMinusZeroMode> {
CheckedInt32MulOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedInt32MulOperator570     CheckedInt32MulOperator()
571         : Operator1<CheckForMinusZeroMode>(
572               IrOpcode::kCheckedInt32Mul,
573               Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1,
574               1, 1, 1, 0, kMode) {}
575   };
576   CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero>
577       kCheckedInt32MulCheckForMinusZeroOperator;
578   CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
579       kCheckedInt32MulDontCheckForMinusZeroOperator;
580 
581   template <CheckForMinusZeroMode kMode>
582   struct CheckedFloat64ToInt32Operator final
583       : public Operator1<CheckForMinusZeroMode> {
CheckedFloat64ToInt32Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedFloat64ToInt32Operator584     CheckedFloat64ToInt32Operator()
585         : Operator1<CheckForMinusZeroMode>(
586               IrOpcode::kCheckedFloat64ToInt32,
587               Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32",
588               1, 1, 1, 1, 1, 0, kMode) {}
589   };
590   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
591       kCheckedFloat64ToInt32CheckForMinusZeroOperator;
592   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
593       kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
594 
595   template <CheckForMinusZeroMode kMode>
596   struct CheckedTaggedToInt32Operator final
597       : public Operator1<CheckForMinusZeroMode> {
CheckedTaggedToInt32Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedTaggedToInt32Operator598     CheckedTaggedToInt32Operator()
599         : Operator1<CheckForMinusZeroMode>(
600               IrOpcode::kCheckedTaggedToInt32,
601               Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32",
602               1, 1, 1, 1, 1, 0, kMode) {}
603   };
604   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
605       kCheckedTaggedToInt32CheckForMinusZeroOperator;
606   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
607       kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
608 
609   template <CheckTaggedInputMode kMode>
610   struct CheckedTaggedToFloat64Operator final
611       : public Operator1<CheckTaggedInputMode> {
CheckedTaggedToFloat64Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedTaggedToFloat64Operator612     CheckedTaggedToFloat64Operator()
613         : Operator1<CheckTaggedInputMode>(
614               IrOpcode::kCheckedTaggedToFloat64,
615               Operator::kFoldable | Operator::kNoThrow,
616               "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0, kMode) {}
617   };
618   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
619       kCheckedTaggedToFloat64NumberOperator;
620   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
621       kCheckedTaggedToFloat64NumberOrOddballOperator;
622 
623   template <CheckFloat64HoleMode kMode>
624   struct CheckFloat64HoleNaNOperator final
625       : public Operator1<CheckFloat64HoleMode> {
CheckFloat64HoleNaNOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckFloat64HoleNaNOperator626     CheckFloat64HoleNaNOperator()
627         : Operator1<CheckFloat64HoleMode>(
628               IrOpcode::kCheckFloat64Hole,
629               Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
630               1, 1, 1, 1, 0, kMode) {}
631   };
632   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
633       kCheckFloat64HoleAllowReturnHoleOperator;
634   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
635       kCheckFloat64HoleNeverReturnHoleOperator;
636 
637   template <PretenureFlag kPretenure>
638   struct AllocateOperator final : public Operator1<PretenureFlag> {
AllocateOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::AllocateOperator639     AllocateOperator()
640         : Operator1<PretenureFlag>(
641               IrOpcode::kAllocate,
642               Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
643               "Allocate", 1, 1, 1, 1, 1, 0, kPretenure) {}
644   };
645   AllocateOperator<NOT_TENURED> kAllocateNotTenuredOperator;
646   AllocateOperator<TENURED> kAllocateTenuredOperator;
647 
648   struct EnsureWritableFastElementsOperator final : public Operator {
EnsureWritableFastElementsOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::EnsureWritableFastElementsOperator649     EnsureWritableFastElementsOperator()
650         : Operator(                                     // --
651               IrOpcode::kEnsureWritableFastElements,    // opcode
652               Operator::kNoDeopt | Operator::kNoThrow,  // flags
653               "EnsureWritableFastElements",             // name
654               2, 1, 1, 1, 1, 0) {}                      // counts
655   };
656   EnsureWritableFastElementsOperator kEnsureWritableFastElements;
657 
658 #define SPECULATIVE_NUMBER_BINOP(Name)                                      \
659   template <NumberOperationHint kHint>                                      \
660   struct Name##Operator final : public Operator1<NumberOperationHint> {     \
661     Name##Operator()                                                        \
662         : Operator1<NumberOperationHint>(                                   \
663               IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow,  \
664               #Name, 2, 1, 1, 1, 1, 0, kHint) {}                            \
665   };                                                                        \
666   Name##Operator<NumberOperationHint::kSignedSmall>                         \
667       k##Name##SignedSmallOperator;                                         \
668   Name##Operator<NumberOperationHint::kSigned32> k##Name##Signed32Operator; \
669   Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator;     \
670   Name##Operator<NumberOperationHint::kNumberOrOddball>                     \
671       k##Name##NumberOrOddballOperator;
672   SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
673 #undef SPECULATIVE_NUMBER_BINOP
674 
675 #define BUFFER_ACCESS(Type, type, TYPE, ctype, size)                          \
676   struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> {  \
677     LoadBuffer##Type##Operator()                                              \
678         : Operator1<BufferAccess>(                                            \
679               IrOpcode::kLoadBuffer,                                          \
680               Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,   \
681               "LoadBuffer", 3, 1, 1, 1, 1, 0,                                 \
682               BufferAccess(kExternal##Type##Array)) {}                        \
683   };                                                                          \
684   struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \
685     StoreBuffer##Type##Operator()                                             \
686         : Operator1<BufferAccess>(                                            \
687               IrOpcode::kStoreBuffer,                                         \
688               Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,    \
689               "StoreBuffer", 4, 1, 1, 0, 1, 0,                                \
690               BufferAccess(kExternal##Type##Array)) {}                        \
691   };                                                                          \
692   LoadBuffer##Type##Operator kLoadBuffer##Type;                               \
693   StoreBuffer##Type##Operator kStoreBuffer##Type;
694   TYPED_ARRAYS(BUFFER_ACCESS)
695 #undef BUFFER_ACCESS
696 };
697 
698 
699 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
700     LAZY_INSTANCE_INITIALIZER;
701 
702 
SimplifiedOperatorBuilder(Zone * zone)703 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
704     : cache_(kCache.Get()), zone_(zone) {}
705 
706 #define GET_FROM_CACHE(Name, ...) \
707   const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
708 PURE_OP_LIST(GET_FROM_CACHE)
CHECKED_OP_LIST(GET_FROM_CACHE)709 CHECKED_OP_LIST(GET_FROM_CACHE)
710 GET_FROM_CACHE(ArrayBufferWasNeutered)
711 #undef GET_FROM_CACHE
712 
713 const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
714     CheckForMinusZeroMode mode) {
715   switch (mode) {
716     case CheckForMinusZeroMode::kCheckForMinusZero:
717       return &cache_.kCheckedInt32MulCheckForMinusZeroOperator;
718     case CheckForMinusZeroMode::kDontCheckForMinusZero:
719       return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator;
720   }
721   UNREACHABLE();
722   return nullptr;
723 }
724 
CheckedFloat64ToInt32(CheckForMinusZeroMode mode)725 const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32(
726     CheckForMinusZeroMode mode) {
727   switch (mode) {
728     case CheckForMinusZeroMode::kCheckForMinusZero:
729       return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator;
730     case CheckForMinusZeroMode::kDontCheckForMinusZero:
731       return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
732   }
733   UNREACHABLE();
734   return nullptr;
735 }
736 
CheckedTaggedToInt32(CheckForMinusZeroMode mode)737 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
738     CheckForMinusZeroMode mode) {
739   switch (mode) {
740     case CheckForMinusZeroMode::kCheckForMinusZero:
741       return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator;
742     case CheckForMinusZeroMode::kDontCheckForMinusZero:
743       return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
744   }
745   UNREACHABLE();
746   return nullptr;
747 }
748 
CheckedTaggedToFloat64(CheckTaggedInputMode mode)749 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
750     CheckTaggedInputMode mode) {
751   switch (mode) {
752     case CheckTaggedInputMode::kNumber:
753       return &cache_.kCheckedTaggedToFloat64NumberOperator;
754     case CheckTaggedInputMode::kNumberOrOddball:
755       return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
756   }
757   UNREACHABLE();
758   return nullptr;
759 }
760 
CheckMaps(CheckMapsFlags flags,ZoneHandleSet<Map> maps)761 const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags,
762                                                      ZoneHandleSet<Map> maps) {
763   CheckMapsParameters const parameters(flags, maps);
764   return new (zone()) Operator1<CheckMapsParameters>(  // --
765       IrOpcode::kCheckMaps,                            // opcode
766       Operator::kNoThrow | Operator::kNoWrite,         // flags
767       "CheckMaps",                                     // name
768       1, 1, 1, 0, 1, 0,                                // counts
769       parameters);                                     // parameter
770 }
771 
CheckFloat64Hole(CheckFloat64HoleMode mode)772 const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
773     CheckFloat64HoleMode mode) {
774   switch (mode) {
775     case CheckFloat64HoleMode::kAllowReturnHole:
776       return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
777     case CheckFloat64HoleMode::kNeverReturnHole:
778       return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
779   }
780   UNREACHABLE();
781   return nullptr;
782 }
783 
EnsureWritableFastElements()784 const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
785   return &cache_.kEnsureWritableFastElements;
786 }
787 
MaybeGrowFastElements(GrowFastElementsFlags flags)788 const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements(
789     GrowFastElementsFlags flags) {
790   return new (zone()) Operator1<GrowFastElementsFlags>(  // --
791       IrOpcode::kMaybeGrowFastElements,                  // opcode
792       Operator::kNoThrow,                                // flags
793       "MaybeGrowFastElements",                           // name
794       4, 1, 1, 1, 1, 0,                                  // counts
795       flags);                                            // parameter
796 }
797 
TransitionElementsKind(ElementsTransition transition)798 const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
799     ElementsTransition transition) {
800   return new (zone()) Operator1<ElementsTransition>(  // --
801       IrOpcode::kTransitionElementsKind,              // opcode
802       Operator::kNoDeopt | Operator::kNoThrow,        // flags
803       "TransitionElementsKind",                       // name
804       1, 1, 1, 0, 1, 0,                               // counts
805       transition);                                    // parameter
806 }
807 
NewUnmappedArgumentsElements(int parameter_count)808 const Operator* SimplifiedOperatorBuilder::NewUnmappedArgumentsElements(
809     int parameter_count) {
810   return new (zone()) Operator1<int>(           // --
811       IrOpcode::kNewUnmappedArgumentsElements,  // opcode
812       Operator::kEliminatable,                  // flags
813       "NewUnmappedArgumentsElements",           // name
814       0, 1, 0, 1, 1, 0,                         // counts
815       parameter_count);                         // parameter
816 }
817 
NewRestParameterElements(int parameter_count)818 const Operator* SimplifiedOperatorBuilder::NewRestParameterElements(
819     int parameter_count) {
820   return new (zone()) Operator1<int>(       // --
821       IrOpcode::kNewRestParameterElements,  // opcode
822       Operator::kEliminatable,              // flags
823       "NewRestParameterElements",           // name
824       0, 1, 0, 1, 1, 0,                     // counts
825       parameter_count);                     // parameter
826 }
827 
Allocate(PretenureFlag pretenure)828 const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) {
829   switch (pretenure) {
830     case NOT_TENURED:
831       return &cache_.kAllocateNotTenuredOperator;
832     case TENURED:
833       return &cache_.kAllocateTenuredOperator;
834   }
835   UNREACHABLE();
836   return nullptr;
837 }
838 
839 
LoadBuffer(BufferAccess access)840 const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) {
841   switch (access.external_array_type()) {
842 #define LOAD_BUFFER(Type, type, TYPE, ctype, size) \
843   case kExternal##Type##Array:                     \
844     return &cache_.kLoadBuffer##Type;
845     TYPED_ARRAYS(LOAD_BUFFER)
846 #undef LOAD_BUFFER
847   }
848   UNREACHABLE();
849   return nullptr;
850 }
851 
852 
StoreBuffer(BufferAccess access)853 const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) {
854   switch (access.external_array_type()) {
855 #define STORE_BUFFER(Type, type, TYPE, ctype, size) \
856   case kExternal##Type##Array:                      \
857     return &cache_.kStoreBuffer##Type;
858     TYPED_ARRAYS(STORE_BUFFER)
859 #undef STORE_BUFFER
860   }
861   UNREACHABLE();
862   return nullptr;
863 }
864 
StringFromCodePoint(UnicodeEncoding encoding)865 const Operator* SimplifiedOperatorBuilder::StringFromCodePoint(
866     UnicodeEncoding encoding) {
867   switch (encoding) {
868     case UnicodeEncoding::UTF16:
869       return &cache_.kStringFromCodePointOperatorUTF16;
870     case UnicodeEncoding::UTF32:
871       return &cache_.kStringFromCodePointOperatorUTF32;
872   }
873   UNREACHABLE();
874   return nullptr;
875 }
876 
877 #define SPECULATIVE_NUMBER_BINOP(Name)                                        \
878   const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \
879     switch (hint) {                                                           \
880       case NumberOperationHint::kSignedSmall:                                 \
881         return &cache_.k##Name##SignedSmallOperator;                          \
882       case NumberOperationHint::kSigned32:                                    \
883         return &cache_.k##Name##Signed32Operator;                             \
884       case NumberOperationHint::kNumber:                                      \
885         return &cache_.k##Name##NumberOperator;                               \
886       case NumberOperationHint::kNumberOrOddball:                             \
887         return &cache_.k##Name##NumberOrOddballOperator;                      \
888     }                                                                         \
889     UNREACHABLE();                                                            \
890     return nullptr;                                                           \
891   }
892 SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
893 #undef SPECULATIVE_NUMBER_BINOP
894 
895 #define ACCESS_OP_LIST(V)                                             \
896   V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)              \
897   V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)              \
898   V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1)          \
899   V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)          \
900   V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \
901   V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)
902 
903 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
904                output_count)                                                   \
905   const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
906     return new (zone())                                                        \
907         Operator1<Type>(IrOpcode::k##Name,                                     \
908                         Operator::kNoDeopt | Operator::kNoThrow | properties,  \
909                         #Name, value_input_count, 1, control_input_count,      \
910                         output_count, 1, 0, access);                           \
911   }
912 ACCESS_OP_LIST(ACCESS)
913 #undef ACCESS
914 
915 }  // namespace compiler
916 }  // namespace internal
917 }  // namespace v8
918