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 #include "src/compiler/js-operator.h"
6 
7 #include <limits>
8 
9 #include "src/base/lazy-instance.h"
10 #include "src/compiler/opcodes.h"
11 #include "src/compiler/operator.h"
12 #include "src/handles-inl.h"
13 #include "src/type-feedback-vector.h"
14 
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18 
VectorSlotPair()19 VectorSlotPair::VectorSlotPair() {}
20 
21 
index() const22 int VectorSlotPair::index() const {
23   return vector_.is_null() ? -1 : vector_->GetIndex(slot_);
24 }
25 
26 
operator ==(VectorSlotPair const & lhs,VectorSlotPair const & rhs)27 bool operator==(VectorSlotPair const& lhs, VectorSlotPair const& rhs) {
28   return lhs.slot() == rhs.slot() &&
29          lhs.vector().location() == rhs.vector().location();
30 }
31 
32 
operator !=(VectorSlotPair const & lhs,VectorSlotPair const & rhs)33 bool operator!=(VectorSlotPair const& lhs, VectorSlotPair const& rhs) {
34   return !(lhs == rhs);
35 }
36 
37 
hash_value(VectorSlotPair const & p)38 size_t hash_value(VectorSlotPair const& p) {
39   return base::hash_combine(p.slot(), p.vector().location());
40 }
41 
42 
ConvertReceiverModeOf(Operator const * op)43 ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) {
44   DCHECK_EQ(IrOpcode::kJSConvertReceiver, op->opcode());
45   return OpParameter<ConvertReceiverMode>(op);
46 }
47 
48 
ToBooleanHintsOf(Operator const * op)49 ToBooleanHints ToBooleanHintsOf(Operator const* op) {
50   DCHECK_EQ(IrOpcode::kJSToBoolean, op->opcode());
51   return OpParameter<ToBooleanHints>(op);
52 }
53 
54 
operator ==(CallConstructParameters const & lhs,CallConstructParameters const & rhs)55 bool operator==(CallConstructParameters const& lhs,
56                 CallConstructParameters const& rhs) {
57   return lhs.arity() == rhs.arity() && lhs.frequency() == rhs.frequency() &&
58          lhs.feedback() == rhs.feedback();
59 }
60 
61 
operator !=(CallConstructParameters const & lhs,CallConstructParameters const & rhs)62 bool operator!=(CallConstructParameters const& lhs,
63                 CallConstructParameters const& rhs) {
64   return !(lhs == rhs);
65 }
66 
67 
hash_value(CallConstructParameters const & p)68 size_t hash_value(CallConstructParameters const& p) {
69   return base::hash_combine(p.arity(), p.frequency(), p.feedback());
70 }
71 
72 
operator <<(std::ostream & os,CallConstructParameters const & p)73 std::ostream& operator<<(std::ostream& os, CallConstructParameters const& p) {
74   return os << p.arity() << ", " << p.frequency();
75 }
76 
77 
CallConstructParametersOf(Operator const * op)78 CallConstructParameters const& CallConstructParametersOf(Operator const* op) {
79   DCHECK_EQ(IrOpcode::kJSCallConstruct, op->opcode());
80   return OpParameter<CallConstructParameters>(op);
81 }
82 
83 
operator <<(std::ostream & os,CallFunctionParameters const & p)84 std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) {
85   os << p.arity() << ", " << p.frequency() << ", " << p.convert_mode() << ", "
86      << p.tail_call_mode();
87   return os;
88 }
89 
90 
CallFunctionParametersOf(const Operator * op)91 const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) {
92   DCHECK_EQ(IrOpcode::kJSCallFunction, op->opcode());
93   return OpParameter<CallFunctionParameters>(op);
94 }
95 
96 
operator ==(CallRuntimeParameters const & lhs,CallRuntimeParameters const & rhs)97 bool operator==(CallRuntimeParameters const& lhs,
98                 CallRuntimeParameters const& rhs) {
99   return lhs.id() == rhs.id() && lhs.arity() == rhs.arity();
100 }
101 
102 
operator !=(CallRuntimeParameters const & lhs,CallRuntimeParameters const & rhs)103 bool operator!=(CallRuntimeParameters const& lhs,
104                 CallRuntimeParameters const& rhs) {
105   return !(lhs == rhs);
106 }
107 
108 
hash_value(CallRuntimeParameters const & p)109 size_t hash_value(CallRuntimeParameters const& p) {
110   return base::hash_combine(p.id(), p.arity());
111 }
112 
113 
operator <<(std::ostream & os,CallRuntimeParameters const & p)114 std::ostream& operator<<(std::ostream& os, CallRuntimeParameters const& p) {
115   return os << p.id() << ", " << p.arity();
116 }
117 
118 
CallRuntimeParametersOf(const Operator * op)119 const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) {
120   DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode());
121   return OpParameter<CallRuntimeParameters>(op);
122 }
123 
124 
ContextAccess(size_t depth,size_t index,bool immutable)125 ContextAccess::ContextAccess(size_t depth, size_t index, bool immutable)
126     : immutable_(immutable),
127       depth_(static_cast<uint16_t>(depth)),
128       index_(static_cast<uint32_t>(index)) {
129   DCHECK(depth <= std::numeric_limits<uint16_t>::max());
130   DCHECK(index <= std::numeric_limits<uint32_t>::max());
131 }
132 
133 
operator ==(ContextAccess const & lhs,ContextAccess const & rhs)134 bool operator==(ContextAccess const& lhs, ContextAccess const& rhs) {
135   return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() &&
136          lhs.immutable() == rhs.immutable();
137 }
138 
139 
operator !=(ContextAccess const & lhs,ContextAccess const & rhs)140 bool operator!=(ContextAccess const& lhs, ContextAccess const& rhs) {
141   return !(lhs == rhs);
142 }
143 
144 
hash_value(ContextAccess const & access)145 size_t hash_value(ContextAccess const& access) {
146   return base::hash_combine(access.depth(), access.index(), access.immutable());
147 }
148 
149 
operator <<(std::ostream & os,ContextAccess const & access)150 std::ostream& operator<<(std::ostream& os, ContextAccess const& access) {
151   return os << access.depth() << ", " << access.index() << ", "
152             << access.immutable();
153 }
154 
155 
ContextAccessOf(Operator const * op)156 ContextAccess const& ContextAccessOf(Operator const* op) {
157   DCHECK(op->opcode() == IrOpcode::kJSLoadContext ||
158          op->opcode() == IrOpcode::kJSStoreContext);
159   return OpParameter<ContextAccess>(op);
160 }
161 
CreateCatchContextParameters(Handle<String> catch_name,Handle<ScopeInfo> scope_info)162 CreateCatchContextParameters::CreateCatchContextParameters(
163     Handle<String> catch_name, Handle<ScopeInfo> scope_info)
164     : catch_name_(catch_name), scope_info_(scope_info) {}
165 
operator ==(CreateCatchContextParameters const & lhs,CreateCatchContextParameters const & rhs)166 bool operator==(CreateCatchContextParameters const& lhs,
167                 CreateCatchContextParameters const& rhs) {
168   return lhs.catch_name().location() == rhs.catch_name().location() &&
169          lhs.scope_info().location() == rhs.scope_info().location();
170 }
171 
operator !=(CreateCatchContextParameters const & lhs,CreateCatchContextParameters const & rhs)172 bool operator!=(CreateCatchContextParameters const& lhs,
173                 CreateCatchContextParameters const& rhs) {
174   return !(lhs == rhs);
175 }
176 
hash_value(CreateCatchContextParameters const & parameters)177 size_t hash_value(CreateCatchContextParameters const& parameters) {
178   return base::hash_combine(parameters.catch_name().location(),
179                             parameters.scope_info().location());
180 }
181 
operator <<(std::ostream & os,CreateCatchContextParameters const & parameters)182 std::ostream& operator<<(std::ostream& os,
183                          CreateCatchContextParameters const& parameters) {
184   return os << Brief(*parameters.catch_name()) << ", "
185             << Brief(*parameters.scope_info());
186 }
187 
CreateCatchContextParametersOf(Operator const * op)188 CreateCatchContextParameters const& CreateCatchContextParametersOf(
189     Operator const* op) {
190   DCHECK_EQ(IrOpcode::kJSCreateCatchContext, op->opcode());
191   return OpParameter<CreateCatchContextParameters>(op);
192 }
193 
operator ==(NamedAccess const & lhs,NamedAccess const & rhs)194 bool operator==(NamedAccess const& lhs, NamedAccess const& rhs) {
195   return lhs.name().location() == rhs.name().location() &&
196          lhs.language_mode() == rhs.language_mode() &&
197          lhs.feedback() == rhs.feedback();
198 }
199 
200 
operator !=(NamedAccess const & lhs,NamedAccess const & rhs)201 bool operator!=(NamedAccess const& lhs, NamedAccess const& rhs) {
202   return !(lhs == rhs);
203 }
204 
205 
hash_value(NamedAccess const & p)206 size_t hash_value(NamedAccess const& p) {
207   return base::hash_combine(p.name().location(), p.language_mode(),
208                             p.feedback());
209 }
210 
211 
operator <<(std::ostream & os,NamedAccess const & p)212 std::ostream& operator<<(std::ostream& os, NamedAccess const& p) {
213   return os << Brief(*p.name()) << ", " << p.language_mode();
214 }
215 
216 
NamedAccessOf(const Operator * op)217 NamedAccess const& NamedAccessOf(const Operator* op) {
218   DCHECK(op->opcode() == IrOpcode::kJSLoadNamed ||
219          op->opcode() == IrOpcode::kJSStoreNamed);
220   return OpParameter<NamedAccess>(op);
221 }
222 
223 
operator <<(std::ostream & os,PropertyAccess const & p)224 std::ostream& operator<<(std::ostream& os, PropertyAccess const& p) {
225   return os << p.language_mode();
226 }
227 
228 
operator ==(PropertyAccess const & lhs,PropertyAccess const & rhs)229 bool operator==(PropertyAccess const& lhs, PropertyAccess const& rhs) {
230   return lhs.language_mode() == rhs.language_mode() &&
231          lhs.feedback() == rhs.feedback();
232 }
233 
234 
operator !=(PropertyAccess const & lhs,PropertyAccess const & rhs)235 bool operator!=(PropertyAccess const& lhs, PropertyAccess const& rhs) {
236   return !(lhs == rhs);
237 }
238 
239 
PropertyAccessOf(const Operator * op)240 PropertyAccess const& PropertyAccessOf(const Operator* op) {
241   DCHECK(op->opcode() == IrOpcode::kJSLoadProperty ||
242          op->opcode() == IrOpcode::kJSStoreProperty);
243   return OpParameter<PropertyAccess>(op);
244 }
245 
246 
hash_value(PropertyAccess const & p)247 size_t hash_value(PropertyAccess const& p) {
248   return base::hash_combine(p.language_mode(), p.feedback());
249 }
250 
251 
operator ==(LoadGlobalParameters const & lhs,LoadGlobalParameters const & rhs)252 bool operator==(LoadGlobalParameters const& lhs,
253                 LoadGlobalParameters const& rhs) {
254   return lhs.name().location() == rhs.name().location() &&
255          lhs.feedback() == rhs.feedback() &&
256          lhs.typeof_mode() == rhs.typeof_mode();
257 }
258 
259 
operator !=(LoadGlobalParameters const & lhs,LoadGlobalParameters const & rhs)260 bool operator!=(LoadGlobalParameters const& lhs,
261                 LoadGlobalParameters const& rhs) {
262   return !(lhs == rhs);
263 }
264 
265 
hash_value(LoadGlobalParameters const & p)266 size_t hash_value(LoadGlobalParameters const& p) {
267   return base::hash_combine(p.name().location(), p.typeof_mode());
268 }
269 
270 
operator <<(std::ostream & os,LoadGlobalParameters const & p)271 std::ostream& operator<<(std::ostream& os, LoadGlobalParameters const& p) {
272   return os << Brief(*p.name()) << ", " << p.typeof_mode();
273 }
274 
275 
LoadGlobalParametersOf(const Operator * op)276 const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op) {
277   DCHECK_EQ(IrOpcode::kJSLoadGlobal, op->opcode());
278   return OpParameter<LoadGlobalParameters>(op);
279 }
280 
281 
operator ==(StoreGlobalParameters const & lhs,StoreGlobalParameters const & rhs)282 bool operator==(StoreGlobalParameters const& lhs,
283                 StoreGlobalParameters const& rhs) {
284   return lhs.language_mode() == rhs.language_mode() &&
285          lhs.name().location() == rhs.name().location() &&
286          lhs.feedback() == rhs.feedback();
287 }
288 
289 
operator !=(StoreGlobalParameters const & lhs,StoreGlobalParameters const & rhs)290 bool operator!=(StoreGlobalParameters const& lhs,
291                 StoreGlobalParameters const& rhs) {
292   return !(lhs == rhs);
293 }
294 
295 
hash_value(StoreGlobalParameters const & p)296 size_t hash_value(StoreGlobalParameters const& p) {
297   return base::hash_combine(p.language_mode(), p.name().location(),
298                             p.feedback());
299 }
300 
301 
operator <<(std::ostream & os,StoreGlobalParameters const & p)302 std::ostream& operator<<(std::ostream& os, StoreGlobalParameters const& p) {
303   return os << p.language_mode() << ", " << Brief(*p.name());
304 }
305 
306 
StoreGlobalParametersOf(const Operator * op)307 const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op) {
308   DCHECK_EQ(IrOpcode::kJSStoreGlobal, op->opcode());
309   return OpParameter<StoreGlobalParameters>(op);
310 }
311 
312 
CreateArgumentsTypeOf(const Operator * op)313 CreateArgumentsType const& CreateArgumentsTypeOf(const Operator* op) {
314   DCHECK_EQ(IrOpcode::kJSCreateArguments, op->opcode());
315   return OpParameter<CreateArgumentsType>(op);
316 }
317 
318 
operator ==(CreateArrayParameters const & lhs,CreateArrayParameters const & rhs)319 bool operator==(CreateArrayParameters const& lhs,
320                 CreateArrayParameters const& rhs) {
321   return lhs.arity() == rhs.arity() &&
322          lhs.site().location() == rhs.site().location();
323 }
324 
325 
operator !=(CreateArrayParameters const & lhs,CreateArrayParameters const & rhs)326 bool operator!=(CreateArrayParameters const& lhs,
327                 CreateArrayParameters const& rhs) {
328   return !(lhs == rhs);
329 }
330 
331 
hash_value(CreateArrayParameters const & p)332 size_t hash_value(CreateArrayParameters const& p) {
333   return base::hash_combine(p.arity(), p.site().location());
334 }
335 
336 
operator <<(std::ostream & os,CreateArrayParameters const & p)337 std::ostream& operator<<(std::ostream& os, CreateArrayParameters const& p) {
338   os << p.arity();
339   if (!p.site().is_null()) os << ", " << Brief(*p.site());
340   return os;
341 }
342 
343 
CreateArrayParametersOf(const Operator * op)344 const CreateArrayParameters& CreateArrayParametersOf(const Operator* op) {
345   DCHECK_EQ(IrOpcode::kJSCreateArray, op->opcode());
346   return OpParameter<CreateArrayParameters>(op);
347 }
348 
349 
operator ==(CreateClosureParameters const & lhs,CreateClosureParameters const & rhs)350 bool operator==(CreateClosureParameters const& lhs,
351                 CreateClosureParameters const& rhs) {
352   return lhs.pretenure() == rhs.pretenure() &&
353          lhs.shared_info().location() == rhs.shared_info().location();
354 }
355 
356 
operator !=(CreateClosureParameters const & lhs,CreateClosureParameters const & rhs)357 bool operator!=(CreateClosureParameters const& lhs,
358                 CreateClosureParameters const& rhs) {
359   return !(lhs == rhs);
360 }
361 
362 
hash_value(CreateClosureParameters const & p)363 size_t hash_value(CreateClosureParameters const& p) {
364   return base::hash_combine(p.pretenure(), p.shared_info().location());
365 }
366 
367 
operator <<(std::ostream & os,CreateClosureParameters const & p)368 std::ostream& operator<<(std::ostream& os, CreateClosureParameters const& p) {
369   return os << p.pretenure() << ", " << Brief(*p.shared_info());
370 }
371 
372 
CreateClosureParametersOf(const Operator * op)373 const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
374   DCHECK_EQ(IrOpcode::kJSCreateClosure, op->opcode());
375   return OpParameter<CreateClosureParameters>(op);
376 }
377 
378 
operator ==(CreateLiteralParameters const & lhs,CreateLiteralParameters const & rhs)379 bool operator==(CreateLiteralParameters const& lhs,
380                 CreateLiteralParameters const& rhs) {
381   return lhs.constant().location() == rhs.constant().location() &&
382          lhs.length() == rhs.length() && lhs.flags() == rhs.flags() &&
383          lhs.index() == rhs.index();
384 }
385 
386 
operator !=(CreateLiteralParameters const & lhs,CreateLiteralParameters const & rhs)387 bool operator!=(CreateLiteralParameters const& lhs,
388                 CreateLiteralParameters const& rhs) {
389   return !(lhs == rhs);
390 }
391 
392 
hash_value(CreateLiteralParameters const & p)393 size_t hash_value(CreateLiteralParameters const& p) {
394   return base::hash_combine(p.constant().location(), p.length(), p.flags(),
395                             p.index());
396 }
397 
398 
operator <<(std::ostream & os,CreateLiteralParameters const & p)399 std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) {
400   return os << Brief(*p.constant()) << ", " << p.length() << ", " << p.flags()
401             << ", " << p.index();
402 }
403 
404 
CreateLiteralParametersOf(const Operator * op)405 const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
406   DCHECK(op->opcode() == IrOpcode::kJSCreateLiteralArray ||
407          op->opcode() == IrOpcode::kJSCreateLiteralObject ||
408          op->opcode() == IrOpcode::kJSCreateLiteralRegExp);
409   return OpParameter<CreateLiteralParameters>(op);
410 }
411 
BinaryOperationHintOf(const Operator * op)412 BinaryOperationHint BinaryOperationHintOf(const Operator* op) {
413   DCHECK(op->opcode() == IrOpcode::kJSBitwiseOr ||
414          op->opcode() == IrOpcode::kJSBitwiseXor ||
415          op->opcode() == IrOpcode::kJSBitwiseAnd ||
416          op->opcode() == IrOpcode::kJSShiftLeft ||
417          op->opcode() == IrOpcode::kJSShiftRight ||
418          op->opcode() == IrOpcode::kJSShiftRightLogical ||
419          op->opcode() == IrOpcode::kJSAdd ||
420          op->opcode() == IrOpcode::kJSSubtract ||
421          op->opcode() == IrOpcode::kJSMultiply ||
422          op->opcode() == IrOpcode::kJSDivide ||
423          op->opcode() == IrOpcode::kJSModulus);
424   return OpParameter<BinaryOperationHint>(op);
425 }
426 
CompareOperationHintOf(const Operator * op)427 CompareOperationHint CompareOperationHintOf(const Operator* op) {
428   DCHECK(op->opcode() == IrOpcode::kJSEqual ||
429          op->opcode() == IrOpcode::kJSNotEqual ||
430          op->opcode() == IrOpcode::kJSStrictEqual ||
431          op->opcode() == IrOpcode::kJSStrictNotEqual ||
432          op->opcode() == IrOpcode::kJSLessThan ||
433          op->opcode() == IrOpcode::kJSGreaterThan ||
434          op->opcode() == IrOpcode::kJSLessThanOrEqual ||
435          op->opcode() == IrOpcode::kJSGreaterThanOrEqual);
436   return OpParameter<CompareOperationHint>(op);
437 }
438 
439 #define CACHED_OP_LIST(V)                                   \
440   V(ToInteger, Operator::kNoProperties, 1, 1)               \
441   V(ToLength, Operator::kNoProperties, 1, 1)                \
442   V(ToName, Operator::kNoProperties, 1, 1)                  \
443   V(ToNumber, Operator::kNoProperties, 1, 1)                \
444   V(ToObject, Operator::kFoldable, 1, 1)                    \
445   V(ToString, Operator::kNoProperties, 1, 1)                \
446   V(Create, Operator::kEliminatable, 2, 1)                  \
447   V(CreateIterResultObject, Operator::kEliminatable, 2, 1)  \
448   V(CreateKeyValueArray, Operator::kEliminatable, 2, 1)     \
449   V(HasProperty, Operator::kNoProperties, 2, 1)             \
450   V(TypeOf, Operator::kPure, 1, 1)                          \
451   V(InstanceOf, Operator::kNoProperties, 2, 1)              \
452   V(OrdinaryHasInstance, Operator::kNoProperties, 2, 1)     \
453   V(ForInNext, Operator::kNoProperties, 4, 1)               \
454   V(ForInPrepare, Operator::kNoProperties, 1, 3)            \
455   V(LoadMessage, Operator::kNoThrow, 0, 1)                  \
456   V(StoreMessage, Operator::kNoThrow, 1, 0)                 \
457   V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \
458   V(StackCheck, Operator::kNoWrite, 0, 0)
459 
460 #define BINARY_OP_LIST(V) \
461   V(BitwiseOr)            \
462   V(BitwiseXor)           \
463   V(BitwiseAnd)           \
464   V(ShiftLeft)            \
465   V(ShiftRight)           \
466   V(ShiftRightLogical)    \
467   V(Add)                  \
468   V(Subtract)             \
469   V(Multiply)             \
470   V(Divide)               \
471   V(Modulus)
472 
473 #define COMPARE_OP_LIST(V)                    \
474   V(Equal, Operator::kNoProperties)           \
475   V(NotEqual, Operator::kNoProperties)        \
476   V(StrictEqual, Operator::kPure)             \
477   V(StrictNotEqual, Operator::kPure)          \
478   V(LessThan, Operator::kNoProperties)        \
479   V(GreaterThan, Operator::kNoProperties)     \
480   V(LessThanOrEqual, Operator::kNoProperties) \
481   V(GreaterThanOrEqual, Operator::kNoProperties)
482 
483 struct JSOperatorGlobalCache final {
484 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \
485   struct Name##Operator final : public Operator {                          \
486     Name##Operator()                                                       \
487         : Operator(IrOpcode::kJS##Name, properties, "JS" #Name,            \
488                    value_input_count, Operator::ZeroIfPure(properties),    \
489                    Operator::ZeroIfEliminatable(properties),               \
490                    value_output_count, Operator::ZeroIfPure(properties),   \
491                    Operator::ZeroIfNoThrow(properties)) {}                 \
492   };                                                                       \
493   Name##Operator k##Name##Operator;
494   CACHED_OP_LIST(CACHED_OP)
495 #undef CACHED_OP
496 
497 #define BINARY_OP(Name)                                                       \
498   template <BinaryOperationHint kHint>                                        \
499   struct Name##Operator final : public Operator1<BinaryOperationHint> {       \
500     Name##Operator()                                                          \
501         : Operator1<BinaryOperationHint>(IrOpcode::kJS##Name,                 \
502                                          Operator::kNoProperties, "JS" #Name, \
503                                          2, 1, 1, 1, 1, 2, kHint) {}          \
504   };                                                                          \
505   Name##Operator<BinaryOperationHint::kNone> k##Name##NoneOperator;           \
506   Name##Operator<BinaryOperationHint::kSignedSmall>                           \
507       k##Name##SignedSmallOperator;                                           \
508   Name##Operator<BinaryOperationHint::kSigned32> k##Name##Signed32Operator;   \
509   Name##Operator<BinaryOperationHint::kNumberOrOddball>                       \
510       k##Name##NumberOrOddballOperator;                                       \
511   Name##Operator<BinaryOperationHint::kString> k##Name##StringOperator;       \
512   Name##Operator<BinaryOperationHint::kAny> k##Name##AnyOperator;
513   BINARY_OP_LIST(BINARY_OP)
514 #undef BINARY_OP
515 
516 #define COMPARE_OP(Name, properties)                                      \
517   template <CompareOperationHint kHint>                                   \
518   struct Name##Operator final : public Operator1<CompareOperationHint> {  \
519     Name##Operator()                                                      \
520         : Operator1<CompareOperationHint>(                                \
521               IrOpcode::kJS##Name, properties, "JS" #Name, 2, 1, 1, 1, 1, \
522               Operator::ZeroIfNoThrow(properties), kHint) {}              \
523   };                                                                      \
524   Name##Operator<CompareOperationHint::kNone> k##Name##NoneOperator;      \
525   Name##Operator<CompareOperationHint::kSignedSmall>                      \
526       k##Name##SignedSmallOperator;                                       \
527   Name##Operator<CompareOperationHint::kNumber> k##Name##NumberOperator;  \
528   Name##Operator<CompareOperationHint::kNumberOrOddball>                  \
529       k##Name##NumberOrOddballOperator;                                   \
530   Name##Operator<CompareOperationHint::kAny> k##Name##AnyOperator;
531   COMPARE_OP_LIST(COMPARE_OP)
532 #undef COMPARE_OP
533 };
534 
535 static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
536     LAZY_INSTANCE_INITIALIZER;
537 
JSOperatorBuilder(Zone * zone)538 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
539     : cache_(kCache.Get()), zone_(zone) {}
540 
541 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \
542   const Operator* JSOperatorBuilder::Name() {                              \
543     return &cache_.k##Name##Operator;                                      \
544   }
545 CACHED_OP_LIST(CACHED_OP)
546 #undef CACHED_OP
547 
548 #define BINARY_OP(Name)                                               \
549   const Operator* JSOperatorBuilder::Name(BinaryOperationHint hint) { \
550     switch (hint) {                                                   \
551       case BinaryOperationHint::kNone:                                \
552         return &cache_.k##Name##NoneOperator;                         \
553       case BinaryOperationHint::kSignedSmall:                         \
554         return &cache_.k##Name##SignedSmallOperator;                  \
555       case BinaryOperationHint::kSigned32:                            \
556         return &cache_.k##Name##Signed32Operator;                     \
557       case BinaryOperationHint::kNumberOrOddball:                     \
558         return &cache_.k##Name##NumberOrOddballOperator;              \
559       case BinaryOperationHint::kString:                              \
560         return &cache_.k##Name##StringOperator;                       \
561       case BinaryOperationHint::kAny:                                 \
562         return &cache_.k##Name##AnyOperator;                          \
563     }                                                                 \
564     UNREACHABLE();                                                    \
565     return nullptr;                                                   \
566   }
BINARY_OP_LIST(BINARY_OP)567 BINARY_OP_LIST(BINARY_OP)
568 #undef BINARY_OP
569 
570 #define COMPARE_OP(Name, ...)                                          \
571   const Operator* JSOperatorBuilder::Name(CompareOperationHint hint) { \
572     switch (hint) {                                                    \
573       case CompareOperationHint::kNone:                                \
574         return &cache_.k##Name##NoneOperator;                          \
575       case CompareOperationHint::kSignedSmall:                         \
576         return &cache_.k##Name##SignedSmallOperator;                   \
577       case CompareOperationHint::kNumber:                              \
578         return &cache_.k##Name##NumberOperator;                        \
579       case CompareOperationHint::kNumberOrOddball:                     \
580         return &cache_.k##Name##NumberOrOddballOperator;               \
581       case CompareOperationHint::kAny:                                 \
582         return &cache_.k##Name##AnyOperator;                           \
583     }                                                                  \
584     UNREACHABLE();                                                     \
585     return nullptr;                                                    \
586   }
587 COMPARE_OP_LIST(COMPARE_OP)
588 #undef COMPARE_OP
589 
590 const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) {
591   // TODO(turbofan): Cache most important versions of this operator.
592   return new (zone()) Operator1<ToBooleanHints>(  //--
593       IrOpcode::kJSToBoolean, Operator::kPure,    // opcode
594       "JSToBoolean",                              // name
595       1, 0, 0, 1, 0, 0,                           // inputs/outputs
596       hints);                                     // parameter
597 }
598 
CallFunction(size_t arity,float frequency,VectorSlotPair const & feedback,ConvertReceiverMode convert_mode,TailCallMode tail_call_mode)599 const Operator* JSOperatorBuilder::CallFunction(
600     size_t arity, float frequency, VectorSlotPair const& feedback,
601     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) {
602   CallFunctionParameters parameters(arity, frequency, feedback, tail_call_mode,
603                                     convert_mode);
604   return new (zone()) Operator1<CallFunctionParameters>(   // --
605       IrOpcode::kJSCallFunction, Operator::kNoProperties,  // opcode
606       "JSCallFunction",                                    // name
607       parameters.arity(), 1, 1, 1, 1, 2,                   // inputs/outputs
608       parameters);                                         // parameter
609 }
610 
611 
CallRuntime(Runtime::FunctionId id)612 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id) {
613   const Runtime::Function* f = Runtime::FunctionForId(id);
614   return CallRuntime(f, f->nargs);
615 }
616 
617 
CallRuntime(Runtime::FunctionId id,size_t arity)618 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
619                                                size_t arity) {
620   const Runtime::Function* f = Runtime::FunctionForId(id);
621   return CallRuntime(f, arity);
622 }
623 
624 
CallRuntime(const Runtime::Function * f,size_t arity)625 const Operator* JSOperatorBuilder::CallRuntime(const Runtime::Function* f,
626                                                size_t arity) {
627   CallRuntimeParameters parameters(f->function_id, arity);
628   DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity()));
629   return new (zone()) Operator1<CallRuntimeParameters>(   // --
630       IrOpcode::kJSCallRuntime, Operator::kNoProperties,  // opcode
631       "JSCallRuntime",                                    // name
632       parameters.arity(), 1, 1, f->result_size, 1, 2,     // inputs/outputs
633       parameters);                                        // parameter
634 }
635 
CallConstruct(uint32_t arity,float frequency,VectorSlotPair const & feedback)636 const Operator* JSOperatorBuilder::CallConstruct(
637     uint32_t arity, float frequency, VectorSlotPair const& feedback) {
638   CallConstructParameters parameters(arity, frequency, feedback);
639   return new (zone()) Operator1<CallConstructParameters>(   // --
640       IrOpcode::kJSCallConstruct, Operator::kNoProperties,  // opcode
641       "JSCallConstruct",                                    // name
642       parameters.arity(), 1, 1, 1, 1, 2,                    // counts
643       parameters);                                          // parameter
644 }
645 
646 
ConvertReceiver(ConvertReceiverMode convert_mode)647 const Operator* JSOperatorBuilder::ConvertReceiver(
648     ConvertReceiverMode convert_mode) {
649   return new (zone()) Operator1<ConvertReceiverMode>(         // --
650       IrOpcode::kJSConvertReceiver, Operator::kEliminatable,  // opcode
651       "JSConvertReceiver",                                    // name
652       1, 1, 1, 1, 1, 0,                                       // counts
653       convert_mode);                                          // parameter
654 }
655 
LoadNamed(Handle<Name> name,const VectorSlotPair & feedback)656 const Operator* JSOperatorBuilder::LoadNamed(Handle<Name> name,
657                                              const VectorSlotPair& feedback) {
658   NamedAccess access(SLOPPY, name, feedback);
659   return new (zone()) Operator1<NamedAccess>(           // --
660       IrOpcode::kJSLoadNamed, Operator::kNoProperties,  // opcode
661       "JSLoadNamed",                                    // name
662       2, 1, 1, 1, 1, 2,                                 // counts
663       access);                                          // parameter
664 }
665 
LoadProperty(VectorSlotPair const & feedback)666 const Operator* JSOperatorBuilder::LoadProperty(
667     VectorSlotPair const& feedback) {
668   PropertyAccess access(SLOPPY, feedback);
669   return new (zone()) Operator1<PropertyAccess>(           // --
670       IrOpcode::kJSLoadProperty, Operator::kNoProperties,  // opcode
671       "JSLoadProperty",                                    // name
672       3, 1, 1, 1, 1, 2,                                    // counts
673       access);                                             // parameter
674 }
675 
GeneratorStore(int register_count)676 const Operator* JSOperatorBuilder::GeneratorStore(int register_count) {
677   return new (zone()) Operator1<int>(                   // --
678       IrOpcode::kJSGeneratorStore, Operator::kNoThrow,  // opcode
679       "JSGeneratorStore",                               // name
680       3 + register_count, 1, 1, 0, 1, 0,                // counts
681       register_count);                                  // parameter
682 }
683 
GeneratorRestoreRegister(int index)684 const Operator* JSOperatorBuilder::GeneratorRestoreRegister(int index) {
685   return new (zone()) Operator1<int>(                             // --
686       IrOpcode::kJSGeneratorRestoreRegister, Operator::kNoThrow,  // opcode
687       "JSGeneratorRestoreRegister",                               // name
688       1, 1, 1, 1, 1, 0,                                           // counts
689       index);                                                     // parameter
690 }
691 
StoreNamed(LanguageMode language_mode,Handle<Name> name,VectorSlotPair const & feedback)692 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
693                                               Handle<Name> name,
694                                               VectorSlotPair const& feedback) {
695   NamedAccess access(language_mode, name, feedback);
696   return new (zone()) Operator1<NamedAccess>(            // --
697       IrOpcode::kJSStoreNamed, Operator::kNoProperties,  // opcode
698       "JSStoreNamed",                                    // name
699       3, 1, 1, 0, 1, 2,                                  // counts
700       access);                                           // parameter
701 }
702 
703 
StoreProperty(LanguageMode language_mode,VectorSlotPair const & feedback)704 const Operator* JSOperatorBuilder::StoreProperty(
705     LanguageMode language_mode, VectorSlotPair const& feedback) {
706   PropertyAccess access(language_mode, feedback);
707   return new (zone()) Operator1<PropertyAccess>(            // --
708       IrOpcode::kJSStoreProperty, Operator::kNoProperties,  // opcode
709       "JSStoreProperty",                                    // name
710       4, 1, 1, 0, 1, 2,                                     // counts
711       access);                                              // parameter
712 }
713 
714 
DeleteProperty(LanguageMode language_mode)715 const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
716   return new (zone()) Operator1<LanguageMode>(               // --
717       IrOpcode::kJSDeleteProperty, Operator::kNoProperties,  // opcode
718       "JSDeleteProperty",                                    // name
719       2, 1, 1, 1, 1, 2,                                      // counts
720       language_mode);                                        // parameter
721 }
722 
723 
LoadGlobal(const Handle<Name> & name,const VectorSlotPair & feedback,TypeofMode typeof_mode)724 const Operator* JSOperatorBuilder::LoadGlobal(const Handle<Name>& name,
725                                               const VectorSlotPair& feedback,
726                                               TypeofMode typeof_mode) {
727   LoadGlobalParameters parameters(name, feedback, typeof_mode);
728   return new (zone()) Operator1<LoadGlobalParameters>(   // --
729       IrOpcode::kJSLoadGlobal, Operator::kNoProperties,  // opcode
730       "JSLoadGlobal",                                    // name
731       1, 1, 1, 1, 1, 2,                                  // counts
732       parameters);                                       // parameter
733 }
734 
735 
StoreGlobal(LanguageMode language_mode,const Handle<Name> & name,const VectorSlotPair & feedback)736 const Operator* JSOperatorBuilder::StoreGlobal(LanguageMode language_mode,
737                                                const Handle<Name>& name,
738                                                const VectorSlotPair& feedback) {
739   StoreGlobalParameters parameters(language_mode, feedback, name);
740   return new (zone()) Operator1<StoreGlobalParameters>(   // --
741       IrOpcode::kJSStoreGlobal, Operator::kNoProperties,  // opcode
742       "JSStoreGlobal",                                    // name
743       2, 1, 1, 0, 1, 2,                                   // counts
744       parameters);                                        // parameter
745 }
746 
747 
LoadContext(size_t depth,size_t index,bool immutable)748 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
749                                                bool immutable) {
750   ContextAccess access(depth, index, immutable);
751   return new (zone()) Operator1<ContextAccess>(  // --
752       IrOpcode::kJSLoadContext,                  // opcode
753       Operator::kNoWrite | Operator::kNoThrow,   // flags
754       "JSLoadContext",                           // name
755       1, 1, 0, 1, 1, 0,                          // counts
756       access);                                   // parameter
757 }
758 
759 
StoreContext(size_t depth,size_t index)760 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
761   ContextAccess access(depth, index, false);
762   return new (zone()) Operator1<ContextAccess>(  // --
763       IrOpcode::kJSStoreContext,                 // opcode
764       Operator::kNoRead | Operator::kNoThrow,    // flags
765       "JSStoreContext",                          // name
766       2, 1, 1, 0, 1, 0,                          // counts
767       access);                                   // parameter
768 }
769 
LoadModule(int32_t cell_index)770 const Operator* JSOperatorBuilder::LoadModule(int32_t cell_index) {
771   return new (zone()) Operator1<int32_t>(       // --
772       IrOpcode::kJSLoadModule,                  // opcode
773       Operator::kNoWrite | Operator::kNoThrow,  // flags
774       "JSLoadModule",                           // name
775       1, 1, 1, 1, 1, 0,                         // counts
776       cell_index);                              // parameter
777 }
778 
StoreModule(int32_t cell_index)779 const Operator* JSOperatorBuilder::StoreModule(int32_t cell_index) {
780   return new (zone()) Operator1<int32_t>(      // --
781       IrOpcode::kJSStoreModule,                // opcode
782       Operator::kNoRead | Operator::kNoThrow,  // flags
783       "JSStoreModule",                         // name
784       2, 1, 1, 0, 1, 0,                        // counts
785       cell_index);                             // parameter
786 }
787 
CreateArguments(CreateArgumentsType type)788 const Operator* JSOperatorBuilder::CreateArguments(CreateArgumentsType type) {
789   return new (zone()) Operator1<CreateArgumentsType>(         // --
790       IrOpcode::kJSCreateArguments, Operator::kEliminatable,  // opcode
791       "JSCreateArguments",                                    // name
792       1, 1, 0, 1, 1, 0,                                       // counts
793       type);                                                  // parameter
794 }
795 
796 
CreateArray(size_t arity,Handle<AllocationSite> site)797 const Operator* JSOperatorBuilder::CreateArray(size_t arity,
798                                                Handle<AllocationSite> site) {
799   // constructor, new_target, arg1, ..., argN
800   int const value_input_count = static_cast<int>(arity) + 2;
801   CreateArrayParameters parameters(arity, site);
802   return new (zone()) Operator1<CreateArrayParameters>(   // --
803       IrOpcode::kJSCreateArray, Operator::kNoProperties,  // opcode
804       "JSCreateArray",                                    // name
805       value_input_count, 1, 1, 1, 1, 2,                   // counts
806       parameters);                                        // parameter
807 }
808 
809 
CreateClosure(Handle<SharedFunctionInfo> shared_info,PretenureFlag pretenure)810 const Operator* JSOperatorBuilder::CreateClosure(
811     Handle<SharedFunctionInfo> shared_info, PretenureFlag pretenure) {
812   CreateClosureParameters parameters(shared_info, pretenure);
813   return new (zone()) Operator1<CreateClosureParameters>(  // --
814       IrOpcode::kJSCreateClosure, Operator::kNoThrow,      // opcode
815       "JSCreateClosure",                                   // name
816       0, 1, 1, 1, 1, 0,                                    // counts
817       parameters);                                         // parameter
818 }
819 
CreateLiteralArray(Handle<FixedArray> constant_elements,int literal_flags,int literal_index,int number_of_elements)820 const Operator* JSOperatorBuilder::CreateLiteralArray(
821     Handle<FixedArray> constant_elements, int literal_flags, int literal_index,
822     int number_of_elements) {
823   CreateLiteralParameters parameters(constant_elements, number_of_elements,
824                                      literal_flags, literal_index);
825   return new (zone()) Operator1<CreateLiteralParameters>(        // --
826       IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties,  // opcode
827       "JSCreateLiteralArray",                                    // name
828       1, 1, 1, 1, 1, 2,                                          // counts
829       parameters);                                               // parameter
830 }
831 
CreateLiteralObject(Handle<FixedArray> constant_properties,int literal_flags,int literal_index,int number_of_properties)832 const Operator* JSOperatorBuilder::CreateLiteralObject(
833     Handle<FixedArray> constant_properties, int literal_flags,
834     int literal_index, int number_of_properties) {
835   CreateLiteralParameters parameters(constant_properties, number_of_properties,
836                                      literal_flags, literal_index);
837   return new (zone()) Operator1<CreateLiteralParameters>(         // --
838       IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties,  // opcode
839       "JSCreateLiteralObject",                                    // name
840       1, 1, 1, 1, 1, 2,                                           // counts
841       parameters);                                                // parameter
842 }
843 
844 
CreateLiteralRegExp(Handle<String> constant_pattern,int literal_flags,int literal_index)845 const Operator* JSOperatorBuilder::CreateLiteralRegExp(
846     Handle<String> constant_pattern, int literal_flags, int literal_index) {
847   CreateLiteralParameters parameters(constant_pattern, -1, literal_flags,
848                                      literal_index);
849   return new (zone()) Operator1<CreateLiteralParameters>(         // --
850       IrOpcode::kJSCreateLiteralRegExp, Operator::kNoProperties,  // opcode
851       "JSCreateLiteralRegExp",                                    // name
852       1, 1, 1, 1, 1, 2,                                           // counts
853       parameters);                                                // parameter
854 }
855 
856 
CreateFunctionContext(int slot_count)857 const Operator* JSOperatorBuilder::CreateFunctionContext(int slot_count) {
858   return new (zone()) Operator1<int>(                               // --
859       IrOpcode::kJSCreateFunctionContext, Operator::kNoProperties,  // opcode
860       "JSCreateFunctionContext",                                    // name
861       1, 1, 1, 1, 1, 2,                                             // counts
862       slot_count);                                                  // parameter
863 }
864 
CreateCatchContext(const Handle<String> & name,const Handle<ScopeInfo> & scope_info)865 const Operator* JSOperatorBuilder::CreateCatchContext(
866     const Handle<String>& name, const Handle<ScopeInfo>& scope_info) {
867   CreateCatchContextParameters parameters(name, scope_info);
868   return new (zone()) Operator1<CreateCatchContextParameters>(
869       IrOpcode::kJSCreateCatchContext, Operator::kNoProperties,  // opcode
870       "JSCreateCatchContext",                                    // name
871       2, 1, 1, 1, 1, 2,                                          // counts
872       parameters);                                               // parameter
873 }
874 
CreateWithContext(const Handle<ScopeInfo> & scope_info)875 const Operator* JSOperatorBuilder::CreateWithContext(
876     const Handle<ScopeInfo>& scope_info) {
877   return new (zone()) Operator1<Handle<ScopeInfo>>(
878       IrOpcode::kJSCreateWithContext, Operator::kNoProperties,  // opcode
879       "JSCreateWithContext",                                    // name
880       2, 1, 1, 1, 1, 2,                                         // counts
881       scope_info);                                              // parameter
882 }
883 
CreateBlockContext(const Handle<ScopeInfo> & scpope_info)884 const Operator* JSOperatorBuilder::CreateBlockContext(
885     const Handle<ScopeInfo>& scpope_info) {
886   return new (zone()) Operator1<Handle<ScopeInfo>>(              // --
887       IrOpcode::kJSCreateBlockContext, Operator::kNoProperties,  // opcode
888       "JSCreateBlockContext",                                    // name
889       1, 1, 1, 1, 1, 2,                                          // counts
890       scpope_info);                                              // parameter
891 }
892 
893 
CreateScriptContext(const Handle<ScopeInfo> & scpope_info)894 const Operator* JSOperatorBuilder::CreateScriptContext(
895     const Handle<ScopeInfo>& scpope_info) {
896   return new (zone()) Operator1<Handle<ScopeInfo>>(               // --
897       IrOpcode::kJSCreateScriptContext, Operator::kNoProperties,  // opcode
898       "JSCreateScriptContext",                                    // name
899       1, 1, 1, 1, 1, 2,                                           // counts
900       scpope_info);                                               // parameter
901 }
902 
903 }  // namespace compiler
904 }  // namespace internal
905 }  // namespace v8
906