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/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
13 #include "src/type-feedback-vector-inl.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
hash_value(TailCallMode mode)55 size_t hash_value(TailCallMode mode) {
56 return base::hash_value(static_cast<unsigned>(mode));
57 }
58
59
operator <<(std::ostream & os,TailCallMode mode)60 std::ostream& operator<<(std::ostream& os, TailCallMode mode) {
61 switch (mode) {
62 case TailCallMode::kAllow:
63 return os << "ALLOW_TAIL_CALLS";
64 case TailCallMode::kDisallow:
65 return os << "DISALLOW_TAIL_CALLS";
66 }
67 UNREACHABLE();
68 return os;
69 }
70
71
operator ==(BinaryOperationParameters const & lhs,BinaryOperationParameters const & rhs)72 bool operator==(BinaryOperationParameters const& lhs,
73 BinaryOperationParameters const& rhs) {
74 return lhs.language_mode() == rhs.language_mode() &&
75 lhs.hints() == rhs.hints();
76 }
77
78
operator !=(BinaryOperationParameters const & lhs,BinaryOperationParameters const & rhs)79 bool operator!=(BinaryOperationParameters const& lhs,
80 BinaryOperationParameters const& rhs) {
81 return !(lhs == rhs);
82 }
83
84
hash_value(BinaryOperationParameters const & p)85 size_t hash_value(BinaryOperationParameters const& p) {
86 return base::hash_combine(p.language_mode(), p.hints());
87 }
88
89
operator <<(std::ostream & os,BinaryOperationParameters const & p)90 std::ostream& operator<<(std::ostream& os, BinaryOperationParameters const& p) {
91 return os << p.language_mode() << ", " << p.hints();
92 }
93
94
BinaryOperationParametersOf(Operator const * op)95 BinaryOperationParameters const& BinaryOperationParametersOf(
96 Operator const* op) {
97 DCHECK(op->opcode() == IrOpcode::kJSBitwiseOr ||
98 op->opcode() == IrOpcode::kJSBitwiseXor ||
99 op->opcode() == IrOpcode::kJSBitwiseAnd ||
100 op->opcode() == IrOpcode::kJSShiftLeft ||
101 op->opcode() == IrOpcode::kJSShiftRight ||
102 op->opcode() == IrOpcode::kJSShiftRightLogical ||
103 op->opcode() == IrOpcode::kJSAdd ||
104 op->opcode() == IrOpcode::kJSSubtract ||
105 op->opcode() == IrOpcode::kJSMultiply ||
106 op->opcode() == IrOpcode::kJSDivide ||
107 op->opcode() == IrOpcode::kJSModulus);
108 return OpParameter<BinaryOperationParameters>(op);
109 }
110
111
operator ==(CallConstructParameters const & lhs,CallConstructParameters const & rhs)112 bool operator==(CallConstructParameters const& lhs,
113 CallConstructParameters const& rhs) {
114 return lhs.arity() == rhs.arity() && lhs.feedback() == rhs.feedback();
115 }
116
117
operator !=(CallConstructParameters const & lhs,CallConstructParameters const & rhs)118 bool operator!=(CallConstructParameters const& lhs,
119 CallConstructParameters const& rhs) {
120 return !(lhs == rhs);
121 }
122
123
hash_value(CallConstructParameters const & p)124 size_t hash_value(CallConstructParameters const& p) {
125 return base::hash_combine(p.arity(), p.feedback());
126 }
127
128
operator <<(std::ostream & os,CallConstructParameters const & p)129 std::ostream& operator<<(std::ostream& os, CallConstructParameters const& p) {
130 return os << p.arity();
131 }
132
133
CallConstructParametersOf(Operator const * op)134 CallConstructParameters const& CallConstructParametersOf(Operator const* op) {
135 DCHECK_EQ(IrOpcode::kJSCallConstruct, op->opcode());
136 return OpParameter<CallConstructParameters>(op);
137 }
138
139
operator <<(std::ostream & os,CallFunctionParameters const & p)140 std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) {
141 os << p.arity() << ", " << p.language_mode() << ", " << p.convert_mode()
142 << ", " << p.tail_call_mode();
143 return os;
144 }
145
146
CallFunctionParametersOf(const Operator * op)147 const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) {
148 DCHECK_EQ(IrOpcode::kJSCallFunction, op->opcode());
149 return OpParameter<CallFunctionParameters>(op);
150 }
151
152
operator ==(CallRuntimeParameters const & lhs,CallRuntimeParameters const & rhs)153 bool operator==(CallRuntimeParameters const& lhs,
154 CallRuntimeParameters const& rhs) {
155 return lhs.id() == rhs.id() && lhs.arity() == rhs.arity();
156 }
157
158
operator !=(CallRuntimeParameters const & lhs,CallRuntimeParameters const & rhs)159 bool operator!=(CallRuntimeParameters const& lhs,
160 CallRuntimeParameters const& rhs) {
161 return !(lhs == rhs);
162 }
163
164
hash_value(CallRuntimeParameters const & p)165 size_t hash_value(CallRuntimeParameters const& p) {
166 return base::hash_combine(p.id(), p.arity());
167 }
168
169
operator <<(std::ostream & os,CallRuntimeParameters const & p)170 std::ostream& operator<<(std::ostream& os, CallRuntimeParameters const& p) {
171 return os << p.id() << ", " << p.arity();
172 }
173
174
CallRuntimeParametersOf(const Operator * op)175 const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) {
176 DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode());
177 return OpParameter<CallRuntimeParameters>(op);
178 }
179
180
ContextAccess(size_t depth,size_t index,bool immutable)181 ContextAccess::ContextAccess(size_t depth, size_t index, bool immutable)
182 : immutable_(immutable),
183 depth_(static_cast<uint16_t>(depth)),
184 index_(static_cast<uint32_t>(index)) {
185 DCHECK(depth <= std::numeric_limits<uint16_t>::max());
186 DCHECK(index <= std::numeric_limits<uint32_t>::max());
187 }
188
189
operator ==(ContextAccess const & lhs,ContextAccess const & rhs)190 bool operator==(ContextAccess const& lhs, ContextAccess const& rhs) {
191 return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() &&
192 lhs.immutable() == rhs.immutable();
193 }
194
195
operator !=(ContextAccess const & lhs,ContextAccess const & rhs)196 bool operator!=(ContextAccess const& lhs, ContextAccess const& rhs) {
197 return !(lhs == rhs);
198 }
199
200
hash_value(ContextAccess const & access)201 size_t hash_value(ContextAccess const& access) {
202 return base::hash_combine(access.depth(), access.index(), access.immutable());
203 }
204
205
operator <<(std::ostream & os,ContextAccess const & access)206 std::ostream& operator<<(std::ostream& os, ContextAccess const& access) {
207 return os << access.depth() << ", " << access.index() << ", "
208 << access.immutable();
209 }
210
211
ContextAccessOf(Operator const * op)212 ContextAccess const& ContextAccessOf(Operator const* op) {
213 DCHECK(op->opcode() == IrOpcode::kJSLoadContext ||
214 op->opcode() == IrOpcode::kJSStoreContext);
215 return OpParameter<ContextAccess>(op);
216 }
217
218
DynamicAccess(const Handle<String> & name,TypeofMode typeof_mode)219 DynamicAccess::DynamicAccess(const Handle<String>& name, TypeofMode typeof_mode)
220 : name_(name), typeof_mode_(typeof_mode) {}
221
222
operator ==(DynamicAccess const & lhs,DynamicAccess const & rhs)223 bool operator==(DynamicAccess const& lhs, DynamicAccess const& rhs) {
224 UNIMPLEMENTED();
225 return true;
226 }
227
228
operator !=(DynamicAccess const & lhs,DynamicAccess const & rhs)229 bool operator!=(DynamicAccess const& lhs, DynamicAccess const& rhs) {
230 return !(lhs == rhs);
231 }
232
233
hash_value(DynamicAccess const & access)234 size_t hash_value(DynamicAccess const& access) {
235 UNIMPLEMENTED();
236 return 0;
237 }
238
239
operator <<(std::ostream & os,DynamicAccess const & access)240 std::ostream& operator<<(std::ostream& os, DynamicAccess const& access) {
241 return os << Brief(*access.name()) << ", " << access.typeof_mode();
242 }
243
244
DynamicAccessOf(Operator const * op)245 DynamicAccess const& DynamicAccessOf(Operator const* op) {
246 DCHECK_EQ(IrOpcode::kJSLoadDynamic, op->opcode());
247 return OpParameter<DynamicAccess>(op);
248 }
249
250
operator ==(NamedAccess const & lhs,NamedAccess const & rhs)251 bool operator==(NamedAccess const& lhs, NamedAccess const& rhs) {
252 return lhs.name().location() == rhs.name().location() &&
253 lhs.language_mode() == rhs.language_mode() &&
254 lhs.feedback() == rhs.feedback();
255 }
256
257
operator !=(NamedAccess const & lhs,NamedAccess const & rhs)258 bool operator!=(NamedAccess const& lhs, NamedAccess const& rhs) {
259 return !(lhs == rhs);
260 }
261
262
hash_value(NamedAccess const & p)263 size_t hash_value(NamedAccess const& p) {
264 return base::hash_combine(p.name().location(), p.language_mode(),
265 p.feedback());
266 }
267
268
operator <<(std::ostream & os,NamedAccess const & p)269 std::ostream& operator<<(std::ostream& os, NamedAccess const& p) {
270 return os << Brief(*p.name()) << ", " << p.language_mode();
271 }
272
273
NamedAccessOf(const Operator * op)274 NamedAccess const& NamedAccessOf(const Operator* op) {
275 DCHECK(op->opcode() == IrOpcode::kJSLoadNamed ||
276 op->opcode() == IrOpcode::kJSStoreNamed);
277 return OpParameter<NamedAccess>(op);
278 }
279
280
operator <<(std::ostream & os,PropertyAccess const & p)281 std::ostream& operator<<(std::ostream& os, PropertyAccess const& p) {
282 return os << p.language_mode();
283 }
284
285
operator ==(PropertyAccess const & lhs,PropertyAccess const & rhs)286 bool operator==(PropertyAccess const& lhs, PropertyAccess const& rhs) {
287 return lhs.language_mode() == rhs.language_mode() &&
288 lhs.feedback() == rhs.feedback();
289 }
290
291
operator !=(PropertyAccess const & lhs,PropertyAccess const & rhs)292 bool operator!=(PropertyAccess const& lhs, PropertyAccess const& rhs) {
293 return !(lhs == rhs);
294 }
295
296
PropertyAccessOf(const Operator * op)297 PropertyAccess const& PropertyAccessOf(const Operator* op) {
298 DCHECK(op->opcode() == IrOpcode::kJSLoadProperty ||
299 op->opcode() == IrOpcode::kJSStoreProperty);
300 return OpParameter<PropertyAccess>(op);
301 }
302
303
hash_value(PropertyAccess const & p)304 size_t hash_value(PropertyAccess const& p) {
305 return base::hash_combine(p.language_mode(), p.feedback());
306 }
307
308
operator ==(LoadGlobalParameters const & lhs,LoadGlobalParameters const & rhs)309 bool operator==(LoadGlobalParameters const& lhs,
310 LoadGlobalParameters const& rhs) {
311 return lhs.name().location() == rhs.name().location() &&
312 lhs.feedback() == rhs.feedback() &&
313 lhs.typeof_mode() == rhs.typeof_mode();
314 }
315
316
operator !=(LoadGlobalParameters const & lhs,LoadGlobalParameters const & rhs)317 bool operator!=(LoadGlobalParameters const& lhs,
318 LoadGlobalParameters const& rhs) {
319 return !(lhs == rhs);
320 }
321
322
hash_value(LoadGlobalParameters const & p)323 size_t hash_value(LoadGlobalParameters const& p) {
324 return base::hash_combine(p.name().location(), p.typeof_mode());
325 }
326
327
operator <<(std::ostream & os,LoadGlobalParameters const & p)328 std::ostream& operator<<(std::ostream& os, LoadGlobalParameters const& p) {
329 return os << Brief(*p.name()) << ", " << p.typeof_mode();
330 }
331
332
LoadGlobalParametersOf(const Operator * op)333 const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op) {
334 DCHECK_EQ(IrOpcode::kJSLoadGlobal, op->opcode());
335 return OpParameter<LoadGlobalParameters>(op);
336 }
337
338
operator ==(StoreGlobalParameters const & lhs,StoreGlobalParameters const & rhs)339 bool operator==(StoreGlobalParameters const& lhs,
340 StoreGlobalParameters const& rhs) {
341 return lhs.language_mode() == rhs.language_mode() &&
342 lhs.name().location() == rhs.name().location() &&
343 lhs.feedback() == rhs.feedback();
344 }
345
346
operator !=(StoreGlobalParameters const & lhs,StoreGlobalParameters const & rhs)347 bool operator!=(StoreGlobalParameters const& lhs,
348 StoreGlobalParameters const& rhs) {
349 return !(lhs == rhs);
350 }
351
352
hash_value(StoreGlobalParameters const & p)353 size_t hash_value(StoreGlobalParameters const& p) {
354 return base::hash_combine(p.language_mode(), p.name().location(),
355 p.feedback());
356 }
357
358
operator <<(std::ostream & os,StoreGlobalParameters const & p)359 std::ostream& operator<<(std::ostream& os, StoreGlobalParameters const& p) {
360 return os << p.language_mode() << ", " << Brief(*p.name());
361 }
362
363
StoreGlobalParametersOf(const Operator * op)364 const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op) {
365 DCHECK_EQ(IrOpcode::kJSStoreGlobal, op->opcode());
366 return OpParameter<StoreGlobalParameters>(op);
367 }
368
369
operator ==(CreateArgumentsParameters const & lhs,CreateArgumentsParameters const & rhs)370 bool operator==(CreateArgumentsParameters const& lhs,
371 CreateArgumentsParameters const& rhs) {
372 return lhs.type() == rhs.type() && lhs.start_index() == rhs.start_index();
373 }
374
375
operator !=(CreateArgumentsParameters const & lhs,CreateArgumentsParameters const & rhs)376 bool operator!=(CreateArgumentsParameters const& lhs,
377 CreateArgumentsParameters const& rhs) {
378 return !(lhs == rhs);
379 }
380
381
hash_value(CreateArgumentsParameters const & p)382 size_t hash_value(CreateArgumentsParameters const& p) {
383 return base::hash_combine(p.type(), p.start_index());
384 }
385
386
operator <<(std::ostream & os,CreateArgumentsParameters const & p)387 std::ostream& operator<<(std::ostream& os, CreateArgumentsParameters const& p) {
388 return os << p.type() << ", " << p.start_index();
389 }
390
391
CreateArgumentsParametersOf(const Operator * op)392 const CreateArgumentsParameters& CreateArgumentsParametersOf(
393 const Operator* op) {
394 DCHECK_EQ(IrOpcode::kJSCreateArguments, op->opcode());
395 return OpParameter<CreateArgumentsParameters>(op);
396 }
397
398
operator ==(CreateArrayParameters const & lhs,CreateArrayParameters const & rhs)399 bool operator==(CreateArrayParameters const& lhs,
400 CreateArrayParameters const& rhs) {
401 return lhs.arity() == rhs.arity() &&
402 lhs.site().location() == rhs.site().location();
403 }
404
405
operator !=(CreateArrayParameters const & lhs,CreateArrayParameters const & rhs)406 bool operator!=(CreateArrayParameters const& lhs,
407 CreateArrayParameters const& rhs) {
408 return !(lhs == rhs);
409 }
410
411
hash_value(CreateArrayParameters const & p)412 size_t hash_value(CreateArrayParameters const& p) {
413 return base::hash_combine(p.arity(), p.site().location());
414 }
415
416
operator <<(std::ostream & os,CreateArrayParameters const & p)417 std::ostream& operator<<(std::ostream& os, CreateArrayParameters const& p) {
418 os << p.arity();
419 if (!p.site().is_null()) os << ", " << Brief(*p.site());
420 return os;
421 }
422
423
CreateArrayParametersOf(const Operator * op)424 const CreateArrayParameters& CreateArrayParametersOf(const Operator* op) {
425 DCHECK_EQ(IrOpcode::kJSCreateArray, op->opcode());
426 return OpParameter<CreateArrayParameters>(op);
427 }
428
429
operator ==(CreateClosureParameters const & lhs,CreateClosureParameters const & rhs)430 bool operator==(CreateClosureParameters const& lhs,
431 CreateClosureParameters const& rhs) {
432 return lhs.pretenure() == rhs.pretenure() &&
433 lhs.shared_info().location() == rhs.shared_info().location();
434 }
435
436
operator !=(CreateClosureParameters const & lhs,CreateClosureParameters const & rhs)437 bool operator!=(CreateClosureParameters const& lhs,
438 CreateClosureParameters const& rhs) {
439 return !(lhs == rhs);
440 }
441
442
hash_value(CreateClosureParameters const & p)443 size_t hash_value(CreateClosureParameters const& p) {
444 return base::hash_combine(p.pretenure(), p.shared_info().location());
445 }
446
447
operator <<(std::ostream & os,CreateClosureParameters const & p)448 std::ostream& operator<<(std::ostream& os, CreateClosureParameters const& p) {
449 return os << p.pretenure() << ", " << Brief(*p.shared_info());
450 }
451
452
CreateClosureParametersOf(const Operator * op)453 const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
454 DCHECK_EQ(IrOpcode::kJSCreateClosure, op->opcode());
455 return OpParameter<CreateClosureParameters>(op);
456 }
457
458
operator ==(CreateLiteralParameters const & lhs,CreateLiteralParameters const & rhs)459 bool operator==(CreateLiteralParameters const& lhs,
460 CreateLiteralParameters const& rhs) {
461 return lhs.constant().location() == rhs.constant().location() &&
462 lhs.flags() == rhs.flags() && lhs.index() == rhs.index();
463 }
464
465
operator !=(CreateLiteralParameters const & lhs,CreateLiteralParameters const & rhs)466 bool operator!=(CreateLiteralParameters const& lhs,
467 CreateLiteralParameters const& rhs) {
468 return !(lhs == rhs);
469 }
470
471
hash_value(CreateLiteralParameters const & p)472 size_t hash_value(CreateLiteralParameters const& p) {
473 return base::hash_combine(p.constant().location(), p.flags(), p.index());
474 }
475
476
operator <<(std::ostream & os,CreateLiteralParameters const & p)477 std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) {
478 return os << Brief(*p.constant()) << ", " << p.flags() << ", " << p.index();
479 }
480
481
CreateLiteralParametersOf(const Operator * op)482 const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
483 DCHECK(op->opcode() == IrOpcode::kJSCreateLiteralArray ||
484 op->opcode() == IrOpcode::kJSCreateLiteralObject ||
485 op->opcode() == IrOpcode::kJSCreateLiteralRegExp);
486 return OpParameter<CreateLiteralParameters>(op);
487 }
488
489
490 #define CACHED_OP_LIST(V) \
491 V(Equal, Operator::kNoProperties, 2, 1) \
492 V(NotEqual, Operator::kNoProperties, 2, 1) \
493 V(StrictEqual, Operator::kNoThrow, 2, 1) \
494 V(StrictNotEqual, Operator::kNoThrow, 2, 1) \
495 V(ToNumber, Operator::kNoProperties, 1, 1) \
496 V(ToString, Operator::kNoProperties, 1, 1) \
497 V(ToName, Operator::kNoProperties, 1, 1) \
498 V(ToObject, Operator::kNoProperties, 1, 1) \
499 V(Yield, Operator::kNoProperties, 1, 1) \
500 V(Create, Operator::kEliminatable, 2, 1) \
501 V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
502 V(HasProperty, Operator::kNoProperties, 2, 1) \
503 V(TypeOf, Operator::kEliminatable, 1, 1) \
504 V(InstanceOf, Operator::kNoProperties, 2, 1) \
505 V(ForInDone, Operator::kPure, 2, 1) \
506 V(ForInNext, Operator::kNoProperties, 4, 1) \
507 V(ForInPrepare, Operator::kNoProperties, 1, 3) \
508 V(ForInStep, Operator::kPure, 1, 1) \
509 V(LoadMessage, Operator::kNoThrow, 0, 1) \
510 V(StoreMessage, Operator::kNoThrow, 1, 0) \
511 V(StackCheck, Operator::kNoProperties, 0, 0) \
512 V(CreateWithContext, Operator::kNoProperties, 2, 1) \
513 V(CreateModuleContext, Operator::kNoProperties, 2, 1)
514
515
516 #define CACHED_OP_LIST_WITH_LANGUAGE_MODE(V) \
517 V(LessThan, Operator::kNoProperties, 2, 1) \
518 V(GreaterThan, Operator::kNoProperties, 2, 1) \
519 V(LessThanOrEqual, Operator::kNoProperties, 2, 1) \
520 V(GreaterThanOrEqual, Operator::kNoProperties, 2, 1)
521
522
523 struct JSOperatorGlobalCache final {
524 #define CACHED(Name, properties, value_input_count, value_output_count) \
525 struct Name##Operator final : public Operator { \
526 Name##Operator() \
527 : Operator(IrOpcode::kJS##Name, properties, "JS" #Name, \
528 value_input_count, Operator::ZeroIfPure(properties), \
529 Operator::ZeroIfEliminatable(properties), \
530 value_output_count, Operator::ZeroIfPure(properties), \
531 Operator::ZeroIfNoThrow(properties)) {} \
532 }; \
533 Name##Operator k##Name##Operator;
534 CACHED_OP_LIST(CACHED)
535 #undef CACHED
536
537
538 #define CACHED_WITH_LANGUAGE_MODE(Name, properties, value_input_count, \
539 value_output_count) \
540 template <LanguageMode kLanguageMode> \
541 struct Name##Operator final : public Operator1<LanguageMode> { \
542 Name##Operator() \
543 : Operator1<LanguageMode>( \
544 IrOpcode::kJS##Name, properties, "JS" #Name, value_input_count, \
545 Operator::ZeroIfPure(properties), \
546 Operator::ZeroIfEliminatable(properties), value_output_count, \
547 Operator::ZeroIfPure(properties), \
548 Operator::ZeroIfNoThrow(properties), kLanguageMode) {} \
549 }; \
550 Name##Operator<SLOPPY> k##Name##SloppyOperator; \
551 Name##Operator<STRICT> k##Name##StrictOperator; \
552 Name##Operator<STRONG> k##Name##StrongOperator;
553 CACHED_OP_LIST_WITH_LANGUAGE_MODE(CACHED_WITH_LANGUAGE_MODE)
554 #undef CACHED_WITH_LANGUAGE_MODE
555 };
556
557
558 static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
559 LAZY_INSTANCE_INITIALIZER;
560
561
JSOperatorBuilder(Zone * zone)562 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
563 : cache_(kCache.Get()), zone_(zone) {}
564
565
566 #define CACHED(Name, properties, value_input_count, value_output_count) \
567 const Operator* JSOperatorBuilder::Name() { \
568 return &cache_.k##Name##Operator; \
569 }
570 CACHED_OP_LIST(CACHED)
571 #undef CACHED
572
573
574 #define CACHED_WITH_LANGUAGE_MODE(Name, properties, value_input_count, \
575 value_output_count) \
576 const Operator* JSOperatorBuilder::Name(LanguageMode language_mode) { \
577 switch (language_mode) { \
578 case SLOPPY: \
579 return &cache_.k##Name##SloppyOperator; \
580 case STRICT: \
581 return &cache_.k##Name##StrictOperator; \
582 case STRONG: \
583 return &cache_.k##Name##StrongOperator; \
584 default: \
585 break; /* %*!%^$#@ */ \
586 } \
587 UNREACHABLE(); \
588 return nullptr; \
589 }
CACHED_OP_LIST_WITH_LANGUAGE_MODE(CACHED_WITH_LANGUAGE_MODE) const590 CACHED_OP_LIST_WITH_LANGUAGE_MODE(CACHED_WITH_LANGUAGE_MODE)
591 #undef CACHED_WITH_LANGUAGE_MODE
592
593
594 const Operator* JSOperatorBuilder::BitwiseOr(LanguageMode language_mode,
595 BinaryOperationHints hints) {
596 // TODO(turbofan): Cache most important versions of this operator.
597 BinaryOperationParameters parameters(language_mode, hints);
598 return new (zone()) Operator1<BinaryOperationParameters>( //--
599 IrOpcode::kJSBitwiseOr, Operator::kNoProperties, // opcode
600 "JSBitwiseOr", // name
601 2, 1, 1, 1, 1, 2, // inputs/outputs
602 parameters); // parameter
603 }
604
605
BitwiseXor(LanguageMode language_mode,BinaryOperationHints hints)606 const Operator* JSOperatorBuilder::BitwiseXor(LanguageMode language_mode,
607 BinaryOperationHints hints) {
608 // TODO(turbofan): Cache most important versions of this operator.
609 BinaryOperationParameters parameters(language_mode, hints);
610 return new (zone()) Operator1<BinaryOperationParameters>( //--
611 IrOpcode::kJSBitwiseXor, Operator::kNoProperties, // opcode
612 "JSBitwiseXor", // name
613 2, 1, 1, 1, 1, 2, // inputs/outputs
614 parameters); // parameter
615 }
616
617
BitwiseAnd(LanguageMode language_mode,BinaryOperationHints hints)618 const Operator* JSOperatorBuilder::BitwiseAnd(LanguageMode language_mode,
619 BinaryOperationHints hints) {
620 // TODO(turbofan): Cache most important versions of this operator.
621 BinaryOperationParameters parameters(language_mode, hints);
622 return new (zone()) Operator1<BinaryOperationParameters>( //--
623 IrOpcode::kJSBitwiseAnd, Operator::kNoProperties, // opcode
624 "JSBitwiseAnd", // name
625 2, 1, 1, 1, 1, 2, // inputs/outputs
626 parameters); // parameter
627 }
628
629
ShiftLeft(LanguageMode language_mode,BinaryOperationHints hints)630 const Operator* JSOperatorBuilder::ShiftLeft(LanguageMode language_mode,
631 BinaryOperationHints hints) {
632 // TODO(turbofan): Cache most important versions of this operator.
633 BinaryOperationParameters parameters(language_mode, hints);
634 return new (zone()) Operator1<BinaryOperationParameters>( //--
635 IrOpcode::kJSShiftLeft, Operator::kNoProperties, // opcode
636 "JSShiftLeft", // name
637 2, 1, 1, 1, 1, 2, // inputs/outputs
638 parameters); // parameter
639 }
640
641
ShiftRight(LanguageMode language_mode,BinaryOperationHints hints)642 const Operator* JSOperatorBuilder::ShiftRight(LanguageMode language_mode,
643 BinaryOperationHints hints) {
644 // TODO(turbofan): Cache most important versions of this operator.
645 BinaryOperationParameters parameters(language_mode, hints);
646 return new (zone()) Operator1<BinaryOperationParameters>( //--
647 IrOpcode::kJSShiftRight, Operator::kNoProperties, // opcode
648 "JSShiftRight", // name
649 2, 1, 1, 1, 1, 2, // inputs/outputs
650 parameters); // parameter
651 }
652
653
ShiftRightLogical(LanguageMode language_mode,BinaryOperationHints hints)654 const Operator* JSOperatorBuilder::ShiftRightLogical(
655 LanguageMode language_mode, BinaryOperationHints hints) {
656 // TODO(turbofan): Cache most important versions of this operator.
657 BinaryOperationParameters parameters(language_mode, hints);
658 return new (zone()) Operator1<BinaryOperationParameters>( //--
659 IrOpcode::kJSShiftRightLogical, Operator::kNoProperties, // opcode
660 "JSShiftRightLogical", // name
661 2, 1, 1, 1, 1, 2, // inputs/outputs
662 parameters); // parameter
663 }
664
665
Add(LanguageMode language_mode,BinaryOperationHints hints)666 const Operator* JSOperatorBuilder::Add(LanguageMode language_mode,
667 BinaryOperationHints hints) {
668 // TODO(turbofan): Cache most important versions of this operator.
669 BinaryOperationParameters parameters(language_mode, hints);
670 return new (zone()) Operator1<BinaryOperationParameters>( //--
671 IrOpcode::kJSAdd, Operator::kNoProperties, // opcode
672 "JSAdd", // name
673 2, 1, 1, 1, 1, 2, // inputs/outputs
674 parameters); // parameter
675 }
676
677
Subtract(LanguageMode language_mode,BinaryOperationHints hints)678 const Operator* JSOperatorBuilder::Subtract(LanguageMode language_mode,
679 BinaryOperationHints hints) {
680 // TODO(turbofan): Cache most important versions of this operator.
681 BinaryOperationParameters parameters(language_mode, hints);
682 return new (zone()) Operator1<BinaryOperationParameters>( //--
683 IrOpcode::kJSSubtract, Operator::kNoProperties, // opcode
684 "JSSubtract", // name
685 2, 1, 1, 1, 1, 2, // inputs/outputs
686 parameters); // parameter
687 }
688
689
Multiply(LanguageMode language_mode,BinaryOperationHints hints)690 const Operator* JSOperatorBuilder::Multiply(LanguageMode language_mode,
691 BinaryOperationHints hints) {
692 // TODO(turbofan): Cache most important versions of this operator.
693 BinaryOperationParameters parameters(language_mode, hints);
694 return new (zone()) Operator1<BinaryOperationParameters>( //--
695 IrOpcode::kJSMultiply, Operator::kNoProperties, // opcode
696 "JSMultiply", // name
697 2, 1, 1, 1, 1, 2, // inputs/outputs
698 parameters); // parameter
699 }
700
701
Divide(LanguageMode language_mode,BinaryOperationHints hints)702 const Operator* JSOperatorBuilder::Divide(LanguageMode language_mode,
703 BinaryOperationHints hints) {
704 // TODO(turbofan): Cache most important versions of this operator.
705 BinaryOperationParameters parameters(language_mode, hints);
706 return new (zone()) Operator1<BinaryOperationParameters>( //--
707 IrOpcode::kJSDivide, Operator::kNoProperties, // opcode
708 "JSDivide", // name
709 2, 1, 1, 1, 1, 2, // inputs/outputs
710 parameters); // parameter
711 }
712
713
Modulus(LanguageMode language_mode,BinaryOperationHints hints)714 const Operator* JSOperatorBuilder::Modulus(LanguageMode language_mode,
715 BinaryOperationHints hints) {
716 // TODO(turbofan): Cache most important versions of this operator.
717 BinaryOperationParameters parameters(language_mode, hints);
718 return new (zone()) Operator1<BinaryOperationParameters>( //--
719 IrOpcode::kJSModulus, Operator::kNoProperties, // opcode
720 "JSModulus", // name
721 2, 1, 1, 1, 1, 2, // inputs/outputs
722 parameters); // parameter
723 }
724
725
ToBoolean(ToBooleanHints hints)726 const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) {
727 // TODO(turbofan): Cache most important versions of this operator.
728 return new (zone()) Operator1<ToBooleanHints>( //--
729 IrOpcode::kJSToBoolean, Operator::kEliminatable, // opcode
730 "JSToBoolean", // name
731 1, 1, 0, 1, 1, 0, // inputs/outputs
732 hints); // parameter
733 }
734
735
CallFunction(size_t arity,LanguageMode language_mode,VectorSlotPair const & feedback,ConvertReceiverMode convert_mode,TailCallMode tail_call_mode)736 const Operator* JSOperatorBuilder::CallFunction(
737 size_t arity, LanguageMode language_mode, VectorSlotPair const& feedback,
738 ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) {
739 CallFunctionParameters parameters(arity, language_mode, feedback,
740 tail_call_mode, convert_mode);
741 return new (zone()) Operator1<CallFunctionParameters>( // --
742 IrOpcode::kJSCallFunction, Operator::kNoProperties, // opcode
743 "JSCallFunction", // name
744 parameters.arity(), 1, 1, 1, 1, 2, // inputs/outputs
745 parameters); // parameter
746 }
747
748
CallRuntime(Runtime::FunctionId id,size_t arity)749 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
750 size_t arity) {
751 CallRuntimeParameters parameters(id, arity);
752 const Runtime::Function* f = Runtime::FunctionForId(parameters.id());
753 DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity()));
754 return new (zone()) Operator1<CallRuntimeParameters>( // --
755 IrOpcode::kJSCallRuntime, Operator::kNoProperties, // opcode
756 "JSCallRuntime", // name
757 parameters.arity(), 1, 1, f->result_size, 1, 2, // inputs/outputs
758 parameters); // parameter
759 }
760
761
CallConstruct(size_t arity,VectorSlotPair const & feedback)762 const Operator* JSOperatorBuilder::CallConstruct(
763 size_t arity, VectorSlotPair const& feedback) {
764 CallConstructParameters parameters(arity, feedback);
765 return new (zone()) Operator1<CallConstructParameters>( // --
766 IrOpcode::kJSCallConstruct, Operator::kNoProperties, // opcode
767 "JSCallConstruct", // name
768 parameters.arity(), 1, 1, 1, 1, 2, // counts
769 parameters); // parameter
770 }
771
772
ConvertReceiver(ConvertReceiverMode convert_mode)773 const Operator* JSOperatorBuilder::ConvertReceiver(
774 ConvertReceiverMode convert_mode) {
775 return new (zone()) Operator1<ConvertReceiverMode>( // --
776 IrOpcode::kJSConvertReceiver, Operator::kNoThrow, // opcode
777 "JSConvertReceiver", // name
778 1, 1, 1, 1, 1, 0, // counts
779 convert_mode); // parameter
780 }
781
782
LoadNamed(LanguageMode language_mode,Handle<Name> name,const VectorSlotPair & feedback)783 const Operator* JSOperatorBuilder::LoadNamed(LanguageMode language_mode,
784 Handle<Name> name,
785 const VectorSlotPair& feedback) {
786 NamedAccess access(language_mode, name, feedback);
787 return new (zone()) Operator1<NamedAccess>( // --
788 IrOpcode::kJSLoadNamed, Operator::kNoProperties, // opcode
789 "JSLoadNamed", // name
790 2, 1, 1, 1, 1, 2, // counts
791 access); // parameter
792 }
793
794
LoadProperty(LanguageMode language_mode,VectorSlotPair const & feedback)795 const Operator* JSOperatorBuilder::LoadProperty(
796 LanguageMode language_mode, VectorSlotPair const& feedback) {
797 PropertyAccess access(language_mode, feedback);
798 return new (zone()) Operator1<PropertyAccess>( // --
799 IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode
800 "JSLoadProperty", // name
801 3, 1, 1, 1, 1, 2, // counts
802 access); // parameter
803 }
804
805
StoreNamed(LanguageMode language_mode,Handle<Name> name,VectorSlotPair const & feedback)806 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
807 Handle<Name> name,
808 VectorSlotPair const& feedback) {
809 NamedAccess access(language_mode, name, feedback);
810 return new (zone()) Operator1<NamedAccess>( // --
811 IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode
812 "JSStoreNamed", // name
813 3, 1, 1, 0, 1, 2, // counts
814 access); // parameter
815 }
816
817
StoreProperty(LanguageMode language_mode,VectorSlotPair const & feedback)818 const Operator* JSOperatorBuilder::StoreProperty(
819 LanguageMode language_mode, VectorSlotPair const& feedback) {
820 PropertyAccess access(language_mode, feedback);
821 return new (zone()) Operator1<PropertyAccess>( // --
822 IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode
823 "JSStoreProperty", // name
824 4, 1, 1, 0, 1, 2, // counts
825 access); // parameter
826 }
827
828
DeleteProperty(LanguageMode language_mode)829 const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
830 return new (zone()) Operator1<LanguageMode>( // --
831 IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode
832 "JSDeleteProperty", // name
833 2, 1, 1, 1, 1, 2, // counts
834 language_mode); // parameter
835 }
836
837
LoadGlobal(const Handle<Name> & name,const VectorSlotPair & feedback,TypeofMode typeof_mode)838 const Operator* JSOperatorBuilder::LoadGlobal(const Handle<Name>& name,
839 const VectorSlotPair& feedback,
840 TypeofMode typeof_mode) {
841 LoadGlobalParameters parameters(name, feedback, typeof_mode);
842 return new (zone()) Operator1<LoadGlobalParameters>( // --
843 IrOpcode::kJSLoadGlobal, Operator::kNoProperties, // opcode
844 "JSLoadGlobal", // name
845 1, 1, 1, 1, 1, 2, // counts
846 parameters); // parameter
847 }
848
849
StoreGlobal(LanguageMode language_mode,const Handle<Name> & name,const VectorSlotPair & feedback)850 const Operator* JSOperatorBuilder::StoreGlobal(LanguageMode language_mode,
851 const Handle<Name>& name,
852 const VectorSlotPair& feedback) {
853 StoreGlobalParameters parameters(language_mode, feedback, name);
854 return new (zone()) Operator1<StoreGlobalParameters>( // --
855 IrOpcode::kJSStoreGlobal, Operator::kNoProperties, // opcode
856 "JSStoreGlobal", // name
857 2, 1, 1, 0, 1, 2, // counts
858 parameters); // parameter
859 }
860
861
LoadContext(size_t depth,size_t index,bool immutable)862 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
863 bool immutable) {
864 ContextAccess access(depth, index, immutable);
865 return new (zone()) Operator1<ContextAccess>( // --
866 IrOpcode::kJSLoadContext, // opcode
867 Operator::kNoWrite | Operator::kNoThrow, // flags
868 "JSLoadContext", // name
869 1, 1, 0, 1, 1, 0, // counts
870 access); // parameter
871 }
872
873
StoreContext(size_t depth,size_t index)874 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
875 ContextAccess access(depth, index, false);
876 return new (zone()) Operator1<ContextAccess>( // --
877 IrOpcode::kJSStoreContext, // opcode
878 Operator::kNoRead | Operator::kNoThrow, // flags
879 "JSStoreContext", // name
880 2, 1, 1, 0, 1, 0, // counts
881 access); // parameter
882 }
883
884
LoadDynamic(const Handle<String> & name,TypeofMode typeof_mode)885 const Operator* JSOperatorBuilder::LoadDynamic(const Handle<String>& name,
886 TypeofMode typeof_mode) {
887 DynamicAccess access(name, typeof_mode);
888 return new (zone()) Operator1<DynamicAccess>( // --
889 IrOpcode::kJSLoadDynamic, Operator::kNoProperties, // opcode
890 "JSLoadDynamic", // name
891 2, 1, 1, 1, 1, 2, // counts
892 access); // parameter
893 }
894
895
CreateArguments(CreateArgumentsParameters::Type type,int start_index)896 const Operator* JSOperatorBuilder::CreateArguments(
897 CreateArgumentsParameters::Type type, int start_index) {
898 DCHECK_IMPLIES(start_index, type == CreateArgumentsParameters::kRestArray);
899 CreateArgumentsParameters parameters(type, start_index);
900 return new (zone()) Operator1<CreateArgumentsParameters>( // --
901 IrOpcode::kJSCreateArguments, Operator::kNoThrow, // opcode
902 "JSCreateArguments", // name
903 1, 1, 1, 1, 1, 0, // counts
904 parameters); // parameter
905 }
906
907
CreateArray(size_t arity,Handle<AllocationSite> site)908 const Operator* JSOperatorBuilder::CreateArray(size_t arity,
909 Handle<AllocationSite> site) {
910 // constructor, new_target, arg1, ..., argN
911 int const value_input_count = static_cast<int>(arity) + 2;
912 CreateArrayParameters parameters(arity, site);
913 return new (zone()) Operator1<CreateArrayParameters>( // --
914 IrOpcode::kJSCreateArray, Operator::kNoProperties, // opcode
915 "JSCreateArray", // name
916 value_input_count, 1, 1, 1, 1, 2, // counts
917 parameters); // parameter
918 }
919
920
CreateClosure(Handle<SharedFunctionInfo> shared_info,PretenureFlag pretenure)921 const Operator* JSOperatorBuilder::CreateClosure(
922 Handle<SharedFunctionInfo> shared_info, PretenureFlag pretenure) {
923 CreateClosureParameters parameters(shared_info, pretenure);
924 return new (zone()) Operator1<CreateClosureParameters>( // --
925 IrOpcode::kJSCreateClosure, Operator::kNoThrow, // opcode
926 "JSCreateClosure", // name
927 0, 1, 1, 1, 1, 0, // counts
928 parameters); // parameter
929 }
930
931
CreateLiteralArray(Handle<FixedArray> constant_elements,int literal_flags,int literal_index)932 const Operator* JSOperatorBuilder::CreateLiteralArray(
933 Handle<FixedArray> constant_elements, int literal_flags,
934 int literal_index) {
935 CreateLiteralParameters parameters(constant_elements, literal_flags,
936 literal_index);
937 return new (zone()) Operator1<CreateLiteralParameters>( // --
938 IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties, // opcode
939 "JSCreateLiteralArray", // name
940 1, 1, 1, 1, 1, 2, // counts
941 parameters); // parameter
942 }
943
944
CreateLiteralObject(Handle<FixedArray> constant_properties,int literal_flags,int literal_index)945 const Operator* JSOperatorBuilder::CreateLiteralObject(
946 Handle<FixedArray> constant_properties, int literal_flags,
947 int literal_index) {
948 CreateLiteralParameters parameters(constant_properties, literal_flags,
949 literal_index);
950 return new (zone()) Operator1<CreateLiteralParameters>( // --
951 IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties, // opcode
952 "JSCreateLiteralObject", // name
953 1, 1, 1, 1, 1, 2, // counts
954 parameters); // parameter
955 }
956
957
CreateLiteralRegExp(Handle<String> constant_pattern,int literal_flags,int literal_index)958 const Operator* JSOperatorBuilder::CreateLiteralRegExp(
959 Handle<String> constant_pattern, int literal_flags, int literal_index) {
960 CreateLiteralParameters parameters(constant_pattern, literal_flags,
961 literal_index);
962 return new (zone()) Operator1<CreateLiteralParameters>( // --
963 IrOpcode::kJSCreateLiteralRegExp, Operator::kNoProperties, // opcode
964 "JSCreateLiteralRegExp", // name
965 1, 1, 1, 1, 1, 2, // counts
966 parameters); // parameter
967 }
968
969
CreateFunctionContext(int slot_count)970 const Operator* JSOperatorBuilder::CreateFunctionContext(int slot_count) {
971 return new (zone()) Operator1<int>( // --
972 IrOpcode::kJSCreateFunctionContext, Operator::kNoProperties, // opcode
973 "JSCreateFunctionContext", // name
974 1, 1, 1, 1, 1, 2, // counts
975 slot_count); // parameter
976 }
977
978
CreateCatchContext(const Handle<String> & name)979 const Operator* JSOperatorBuilder::CreateCatchContext(
980 const Handle<String>& name) {
981 return new (zone()) Operator1<Handle<String>>( // --
982 IrOpcode::kJSCreateCatchContext, Operator::kNoProperties, // opcode
983 "JSCreateCatchContext", // name
984 2, 1, 1, 1, 1, 2, // counts
985 name); // parameter
986 }
987
988
CreateBlockContext(const Handle<ScopeInfo> & scpope_info)989 const Operator* JSOperatorBuilder::CreateBlockContext(
990 const Handle<ScopeInfo>& scpope_info) {
991 return new (zone()) Operator1<Handle<ScopeInfo>>( // --
992 IrOpcode::kJSCreateBlockContext, Operator::kNoProperties, // opcode
993 "JSCreateBlockContext", // name
994 1, 1, 1, 1, 1, 2, // counts
995 scpope_info); // parameter
996 }
997
998
CreateScriptContext(const Handle<ScopeInfo> & scpope_info)999 const Operator* JSOperatorBuilder::CreateScriptContext(
1000 const Handle<ScopeInfo>& scpope_info) {
1001 return new (zone()) Operator1<Handle<ScopeInfo>>( // --
1002 IrOpcode::kJSCreateScriptContext, Operator::kNoProperties, // opcode
1003 "JSCreateScriptContext", // name
1004 1, 1, 1, 1, 1, 2, // counts
1005 scpope_info); // parameter
1006 }
1007
1008 } // namespace compiler
1009 } // namespace internal
1010 } // namespace v8
1011