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