simplified-operator.cc 83.4 KB
Newer Older
1 2 3 4 5
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/simplified-operator.h"
6

7
#include "include/v8-fast-api-calls.h"
8
#include "src/base/lazy-instance.h"
9
#include "src/compiler/linkage.h"
10 11
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
12
#include "src/compiler/types.h"
13
#include "src/handles/handles-inl.h"
14
#include "src/objects/feedback-cell.h"
15
#include "src/objects/map.h"
16
#include "src/objects/name.h"
17
#include "src/objects/objects-inl.h"
18 19 20 21 22

namespace v8 {
namespace internal {
namespace compiler {

23 24 25 26
size_t hash_value(BaseTaggedness base_taggedness) {
  return static_cast<uint8_t>(base_taggedness);
}

27
std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
28 29 30 31 32 33 34 35 36
  switch (base_taggedness) {
    case kUntaggedBase:
      return os << "untagged base";
    case kTaggedBase:
      return os << "tagged base";
  }
  UNREACHABLE();
}

37 38 39
std::ostream& operator<<(std::ostream& os,
                         ConstFieldInfo const& const_field_info) {
  if (const_field_info.IsConst()) {
40 41
    return os << "const (field owner: "
              << Brief(*const_field_info.owner_map.ToHandleChecked()) << ")";
42 43 44 45 46 47 48 49 50 51 52
  } else {
    return os << "mutable";
  }
  UNREACHABLE();
}

bool operator==(ConstFieldInfo const& lhs, ConstFieldInfo const& rhs) {
  return lhs.owner_map.address() == rhs.owner_map.address();
}

size_t hash_value(ConstFieldInfo const& const_field_info) {
53
  return static_cast<size_t>(const_field_info.owner_map.address());
54 55
}

56
bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
57 58 59
  // On purpose we don't include the write barrier kind here, as this method is
  // really only relevant for eliminating loads and they don't care about the
  // write barrier mode.
60
  return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
61
         lhs.map.address() == rhs.map.address() &&
62
         lhs.machine_type == rhs.machine_type &&
63 64
         lhs.const_field_info == rhs.const_field_info &&
         lhs.is_store_in_literal == rhs.is_store_in_literal;
65 66
}

67
size_t hash_value(FieldAccess const& access) {
68 69 70
  // On purpose we don't include the write barrier kind here, as this method is
  // really only relevant for eliminating loads and they don't care about the
  // write barrier mode.
71
  return base::hash_combine(access.base_is_tagged, access.offset,
72 73
                            access.machine_type, access.const_field_info,
                            access.is_store_in_literal);
74 75
}

76 77 78 79 80
std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
  os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
#ifdef OBJECT_PRINT
  Handle<Name> name;
  if (access.name.ToHandle(&name)) {
81
    name->NamePrint(os);
82 83
    os << ", ";
  }
84 85 86 87
  Handle<Map> map;
  if (access.map.ToHandle(&map)) {
    os << Brief(*map) << ", ";
  }
88
#endif
89
  os << access.type << ", " << access.machine_type << ", "
90
     << access.write_barrier_kind << ", " << access.const_field_info;
91 92 93
  if (access.is_store_in_literal) {
    os << " (store in literal)";
  }
94
  os << "]";
95 96 97
  return os;
}

98 99 100 101 102 103 104 105 106
template <>
void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
                                            PrintVerbosity verbose) const {
  if (verbose == PrintVerbosity::kVerbose) {
    os << parameter();
  } else {
    os << "[+" << parameter().offset << "]";
  }
}
107

108
bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
109 110 111
  // On purpose we don't include the write barrier kind here, as this method is
  // really only relevant for eliminating loads and they don't care about the
  // write barrier mode.
112
  return lhs.base_is_tagged == rhs.base_is_tagged &&
113
         lhs.header_size == rhs.header_size &&
114 115 116
         lhs.machine_type == rhs.machine_type;
}

117
size_t hash_value(ElementAccess const& access) {
118 119 120
  // On purpose we don't include the write barrier kind here, as this method is
  // really only relevant for eliminating loads and they don't care about the
  // write barrier mode.
121 122 123 124
  return base::hash_combine(access.base_is_tagged, access.header_size,
                            access.machine_type);
}

125
std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
126 127 128
  os << access.base_is_tagged << ", " << access.header_size << ", "
     << access.type << ", " << access.machine_type << ", "
     << access.write_barrier_kind;
129 130 131
  return os;
}

132 133 134 135 136 137 138 139 140 141 142 143 144 145
bool operator==(ObjectAccess const& lhs, ObjectAccess const& rhs) {
  return lhs.machine_type == rhs.machine_type &&
         lhs.write_barrier_kind == rhs.write_barrier_kind;
}

size_t hash_value(ObjectAccess const& access) {
  return base::hash_combine(access.machine_type, access.write_barrier_kind);
}

std::ostream& operator<<(std::ostream& os, ObjectAccess const& access) {
  os << access.machine_type << ", " << access.write_barrier_kind;
  return os;
}

146 147 148 149 150 151 152 153 154 155 156 157
const FieldAccess& FieldAccessOf(const Operator* op) {
  DCHECK_NOT_NULL(op);
  DCHECK(op->opcode() == IrOpcode::kLoadField ||
         op->opcode() == IrOpcode::kStoreField);
  return OpParameter<FieldAccess>(op);
}

const ElementAccess& ElementAccessOf(const Operator* op) {
  DCHECK_NOT_NULL(op);
  DCHECK(op->opcode() == IrOpcode::kLoadElement ||
         op->opcode() == IrOpcode::kStoreElement);
  return OpParameter<ElementAccess>(op);
158 159
}

160 161 162 163 164 165 166
const ObjectAccess& ObjectAccessOf(const Operator* op) {
  DCHECK_NOT_NULL(op);
  DCHECK(op->opcode() == IrOpcode::kLoadFromObject ||
         op->opcode() == IrOpcode::kStoreToObject);
  return OpParameter<ObjectAccess>(op);
}

167 168
ExternalArrayType ExternalArrayTypeOf(const Operator* op) {
  DCHECK(op->opcode() == IrOpcode::kLoadTypedElement ||
169
         op->opcode() == IrOpcode::kLoadDataViewElement ||
170 171
         op->opcode() == IrOpcode::kStoreTypedElement ||
         op->opcode() == IrOpcode::kStoreDataViewElement);
172 173 174
  return OpParameter<ExternalArrayType>(op);
}

175 176 177 178 179
ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) {
  DCHECK_EQ(IrOpcode::kConvertReceiver, op->opcode());
  return OpParameter<ConvertReceiverMode>(op);
}

180 181 182 183 184 185 186 187 188 189 190 191 192 193
size_t hash_value(CheckFloat64HoleMode mode) {
  return static_cast<size_t>(mode);
}

std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
  switch (mode) {
    case CheckFloat64HoleMode::kAllowReturnHole:
      return os << "allow-return-hole";
    case CheckFloat64HoleMode::kNeverReturnHole:
      return os << "never-return-hole";
  }
  UNREACHABLE();
}

194 195
CheckFloat64HoleParameters const& CheckFloat64HoleParametersOf(
    Operator const* op) {
196
  DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
197 198 199 200 201
  return OpParameter<CheckFloat64HoleParameters>(op);
}

std::ostream& operator<<(std::ostream& os,
                         CheckFloat64HoleParameters const& params) {
202
  return os << params.mode() << ", " << params.feedback();
203 204 205
}

size_t hash_value(const CheckFloat64HoleParameters& params) {
206 207
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
208 209 210 211 212 213 214 215 216 217
}

bool operator==(CheckFloat64HoleParameters const& lhs,
                CheckFloat64HoleParameters const& rhs) {
  return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
}

bool operator!=(CheckFloat64HoleParameters const& lhs,
                CheckFloat64HoleParameters const& rhs) {
  return !(lhs == rhs);
218 219
}

220
CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
221
  DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged ||
222
         op->opcode() == IrOpcode::kCheckedInt32Mul);
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
  return OpParameter<CheckForMinusZeroMode>(op);
}

size_t hash_value(CheckForMinusZeroMode mode) {
  return static_cast<size_t>(mode);
}

std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
  switch (mode) {
    case CheckForMinusZeroMode::kCheckForMinusZero:
      return os << "check-for-minus-zero";
    case CheckForMinusZeroMode::kDontCheckForMinusZero:
      return os << "dont-check-for-minus-zero";
  }
  UNREACHABLE();
}

240 241
std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
  if (flags & CheckMapsFlag::kTryMigrateInstance) {
242 243 244
    return os << "TryMigrateInstance";
  } else {
    return os << "None";
245 246 247
  }
}

248 249
bool operator==(CheckMapsParameters const& lhs,
                CheckMapsParameters const& rhs) {
250 251
  return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps() &&
         lhs.feedback() == rhs.feedback();
252 253
}

254
size_t hash_value(CheckMapsParameters const& p) {
255 256
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(p.flags(), p.maps(), feedback_hash(p.feedback()));
257
}
258 259

std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
260
  return os << p.flags() << ", " << p.maps() << ", " << p.feedback();
261 262 263 264 265 266 267
}

CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
  DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode());
  return OpParameter<CheckMapsParameters>(op);
}

268 269
bool operator==(DynamicCheckMapsParameters const& lhs,
                DynamicCheckMapsParameters const& rhs) {
270 271 272 273 274
  // FeedbackSource is sufficient as an equality check. FeedbackSource uniquely
  // determines all other properties (handler, flags and the monomorphic map
  DCHECK_IMPLIES(lhs.feedback() == rhs.feedback(),
                 lhs.flags() == rhs.flags() && lhs.state() == rhs.state() &&
                     lhs.handler().address() == rhs.handler().address() &&
275
                     lhs.maps() == rhs.maps());
276
  return lhs.feedback() == rhs.feedback();
277 278 279 280
}

size_t hash_value(DynamicCheckMapsParameters const& p) {
  FeedbackSource::Hash feedback_hash;
281 282 283
  // FeedbackSource is sufficient for hashing. FeedbackSource uniquely
  // determines all other properties (handler, flags and the monomorphic map
  return base::hash_combine(feedback_hash(p.feedback()));
284 285 286 287
}

std::ostream& operator<<(std::ostream& os,
                         DynamicCheckMapsParameters const& p) {
288
  return os << p.handler() << ", " << p.feedback() << "," << p.state() << ","
289
            << p.flags() << "," << p.maps();
290 291 292 293 294 295 296 297
}

DynamicCheckMapsParameters const& DynamicCheckMapsParametersOf(
    Operator const* op) {
  DCHECK_EQ(IrOpcode::kDynamicCheckMaps, op->opcode());
  return OpParameter<DynamicCheckMapsParameters>(op);
}

298
ZoneHandleSet<Map> const& CompareMapsParametersOf(Operator const* op) {
299
  DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode());
300
  return OpParameter<ZoneHandleSet<Map>>(op);
301 302
}

303
ZoneHandleSet<Map> const& MapGuardMapsOf(Operator const* op) {
304
  DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
305
  return OpParameter<ZoneHandleSet<Map>>(op);
306 307
}

308 309 310 311 312 313 314 315
size_t hash_value(CheckTaggedInputMode mode) {
  return static_cast<size_t>(mode);
}

std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
  switch (mode) {
    case CheckTaggedInputMode::kNumber:
      return os << "Number";
316 317
    case CheckTaggedInputMode::kNumberOrBoolean:
      return os << "NumberOrBoolean";
318 319 320 321 322 323
    case CheckTaggedInputMode::kNumberOrOddball:
      return os << "NumberOrOddball";
  }
  UNREACHABLE();
}

324 325 326 327 328 329
std::ostream& operator<<(std::ostream& os, GrowFastElementsMode mode) {
  switch (mode) {
    case GrowFastElementsMode::kDoubleElements:
      return os << "DoubleElements";
    case GrowFastElementsMode::kSmiOrObjectElements:
      return os << "SmiOrObjectElements";
330
  }
331
  UNREACHABLE();
332 333
}

334 335 336 337 338 339
bool operator==(const GrowFastElementsParameters& lhs,
                const GrowFastElementsParameters& rhs) {
  return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
}

inline size_t hash_value(const GrowFastElementsParameters& params) {
340 341
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
342 343 344 345
}

std::ostream& operator<<(std::ostream& os,
                         const GrowFastElementsParameters& params) {
346
  return os << params.mode() << ", " << params.feedback();
347 348 349 350
}

const GrowFastElementsParameters& GrowFastElementsParametersOf(
    const Operator* op) {
351
  DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode());
352
  return OpParameter<GrowFastElementsParameters>(op);
353 354
}

355 356 357 358 359 360
bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) {
  return lhs.mode() == rhs.mode() &&
         lhs.source().address() == rhs.source().address() &&
         lhs.target().address() == rhs.target().address();
}

361
size_t hash_value(ElementsTransition transition) {
362 363 364
  return base::hash_combine(static_cast<uint8_t>(transition.mode()),
                            transition.source().address(),
                            transition.target().address());
365 366 367
}

std::ostream& operator<<(std::ostream& os, ElementsTransition transition) {
368
  switch (transition.mode()) {
369
    case ElementsTransition::kFastTransition:
370 371
      return os << "fast-transition from " << Brief(*transition.source())
                << " to " << Brief(*transition.target());
372
    case ElementsTransition::kSlowTransition:
373 374
      return os << "slow-transition from " << Brief(*transition.source())
                << " to " << Brief(*transition.target());
375 376 377 378
  }
  UNREACHABLE();
}

379
ElementsTransition const& ElementsTransitionOf(const Operator* op) {
380 381 382 383
  DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode());
  return OpParameter<ElementsTransition>(op);
}

384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
namespace {

// Parameters for the TransitionAndStoreElement opcode.
class TransitionAndStoreElementParameters final {
 public:
  TransitionAndStoreElementParameters(Handle<Map> double_map,
                                      Handle<Map> fast_map);

  Handle<Map> double_map() const { return double_map_; }
  Handle<Map> fast_map() const { return fast_map_; }

 private:
  Handle<Map> const double_map_;
  Handle<Map> const fast_map_;
};

TransitionAndStoreElementParameters::TransitionAndStoreElementParameters(
    Handle<Map> double_map, Handle<Map> fast_map)
    : double_map_(double_map), fast_map_(fast_map) {}

bool operator==(TransitionAndStoreElementParameters const& lhs,
                TransitionAndStoreElementParameters const& rhs) {
  return lhs.fast_map().address() == rhs.fast_map().address() &&
         lhs.double_map().address() == rhs.double_map().address();
}

size_t hash_value(TransitionAndStoreElementParameters parameters) {
  return base::hash_combine(parameters.fast_map().address(),
                            parameters.double_map().address());
}

std::ostream& operator<<(std::ostream& os,
                         TransitionAndStoreElementParameters parameters) {
  return os << "fast-map" << Brief(*parameters.fast_map()) << " double-map"
            << Brief(*parameters.double_map());
}

}  // namespace

423 424 425 426 427 428
namespace {

// Parameters for the TransitionAndStoreNonNumberElement opcode.
class TransitionAndStoreNonNumberElementParameters final {
 public:
  TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
429
                                               Type value_type);
430 431

  Handle<Map> fast_map() const { return fast_map_; }
432
  Type value_type() const { return value_type_; }
433 434 435

 private:
  Handle<Map> const fast_map_;
436
  Type value_type_;
437 438 439 440
};

TransitionAndStoreNonNumberElementParameters::
    TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
441
                                                 Type value_type)
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
    : fast_map_(fast_map), value_type_(value_type) {}

bool operator==(TransitionAndStoreNonNumberElementParameters const& lhs,
                TransitionAndStoreNonNumberElementParameters const& rhs) {
  return lhs.fast_map().address() == rhs.fast_map().address() &&
         lhs.value_type() == rhs.value_type();
}

size_t hash_value(TransitionAndStoreNonNumberElementParameters parameters) {
  return base::hash_combine(parameters.fast_map().address(),
                            parameters.value_type());
}

std::ostream& operator<<(
    std::ostream& os, TransitionAndStoreNonNumberElementParameters parameters) {
457 458
  return os << parameters.value_type() << ", fast-map"
            << Brief(*parameters.fast_map());
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
}

}  // namespace

namespace {

// Parameters for the TransitionAndStoreNumberElement opcode.
class TransitionAndStoreNumberElementParameters final {
 public:
  explicit TransitionAndStoreNumberElementParameters(Handle<Map> double_map);

  Handle<Map> double_map() const { return double_map_; }

 private:
  Handle<Map> const double_map_;
};

TransitionAndStoreNumberElementParameters::
    TransitionAndStoreNumberElementParameters(Handle<Map> double_map)
    : double_map_(double_map) {}

bool operator==(TransitionAndStoreNumberElementParameters const& lhs,
                TransitionAndStoreNumberElementParameters const& rhs) {
  return lhs.double_map().address() == rhs.double_map().address();
}

size_t hash_value(TransitionAndStoreNumberElementParameters parameters) {
  return base::hash_combine(parameters.double_map().address());
}

std::ostream& operator<<(std::ostream& os,
                         TransitionAndStoreNumberElementParameters parameters) {
  return os << "double-map" << Brief(*parameters.double_map());
}

}  // namespace

496
Handle<Map> DoubleMapParameterOf(const Operator* op) {
497 498 499 500 501 502 503 504 505
  if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
    return OpParameter<TransitionAndStoreElementParameters>(op).double_map();
  } else if (op->opcode() == IrOpcode::kTransitionAndStoreNumberElement) {
    return OpParameter<TransitionAndStoreNumberElementParameters>(op)
        .double_map();
  }
  UNREACHABLE();
}

506
Type ValueTypeParameterOf(const Operator* op) {
507 508 509
  DCHECK_EQ(IrOpcode::kTransitionAndStoreNonNumberElement, op->opcode());
  return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
      .value_type();
510 511 512
}

Handle<Map> FastMapParameterOf(const Operator* op) {
513 514 515 516 517 518 519
  if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
    return OpParameter<TransitionAndStoreElementParameters>(op).fast_map();
  } else if (op->opcode() == IrOpcode::kTransitionAndStoreNonNumberElement) {
    return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
        .fast_map();
  }
  UNREACHABLE();
520 521
}

522 523 524 525 526 527 528 529 530 531 532 533
std::ostream& operator<<(std::ostream& os, BigIntOperationHint hint) {
  switch (hint) {
    case BigIntOperationHint::kBigInt:
      return os << "BigInt";
  }
  UNREACHABLE();
}

size_t hash_value(BigIntOperationHint hint) {
  return static_cast<uint8_t>(hint);
}

534 535
std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) {
  switch (hint) {
536 537 538 539
    case NumberOperationHint::kSignedSmall:
      return os << "SignedSmall";
    case NumberOperationHint::kSignedSmallInputs:
      return os << "SignedSmallInputs";
540 541
    case NumberOperationHint::kNumber:
      return os << "Number";
542 543
    case NumberOperationHint::kNumberOrBoolean:
      return os << "NumberOrBoolean";
544 545 546 547 548 549 550 551 552 553 554
    case NumberOperationHint::kNumberOrOddball:
      return os << "NumberOrOddball";
  }
  UNREACHABLE();
}

size_t hash_value(NumberOperationHint hint) {
  return static_cast<uint8_t>(hint);
}

NumberOperationHint NumberOperationHintOf(const Operator* op) {
555
  DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
556 557
         op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
         op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
558
         op->opcode() == IrOpcode::kSpeculativeNumberPow ||
559
         op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
560
         op->opcode() == IrOpcode::kSpeculativeNumberModulus ||
561 562
         op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft ||
         op->opcode() == IrOpcode::kSpeculativeNumberShiftRight ||
563 564 565
         op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical ||
         op->opcode() == IrOpcode::kSpeculativeNumberBitwiseAnd ||
         op->opcode() == IrOpcode::kSpeculativeNumberBitwiseOr ||
566 567
         op->opcode() == IrOpcode::kSpeculativeNumberBitwiseXor ||
         op->opcode() == IrOpcode::kSpeculativeNumberEqual ||
568
         op->opcode() == IrOpcode::kSpeculativeNumberLessThan ||
569 570 571
         op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual ||
         op->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd ||
         op->opcode() == IrOpcode::kSpeculativeSafeIntegerSubtract);
572
  return OpParameter<NumberOperationHint>(op);
573 574
}

575 576 577 578 579 580
bool operator==(NumberOperationParameters const& lhs,
                NumberOperationParameters const& rhs) {
  return lhs.hint() == rhs.hint() && lhs.feedback() == rhs.feedback();
}

size_t hash_value(NumberOperationParameters const& p) {
581 582
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(p.hint(), feedback_hash(p.feedback()));
583 584 585
}

std::ostream& operator<<(std::ostream& os, NumberOperationParameters const& p) {
586
  return os << p.hint() << ", " << p.feedback();
587 588 589 590 591 592 593 594
}

NumberOperationParameters const& NumberOperationParametersOf(
    Operator const* op) {
  DCHECK_EQ(IrOpcode::kSpeculativeToNumber, op->opcode());
  return OpParameter<NumberOperationParameters>(op);
}

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
bool operator==(SpeculativeBigIntAsUintNParameters const& lhs,
                SpeculativeBigIntAsUintNParameters const& rhs) {
  return lhs.bits() == rhs.bits() && lhs.feedback() == rhs.feedback();
}

size_t hash_value(SpeculativeBigIntAsUintNParameters const& p) {
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(p.bits(), feedback_hash(p.feedback()));
}

std::ostream& operator<<(std::ostream& os,
                         SpeculativeBigIntAsUintNParameters const& p) {
  return os << p.bits() << ", " << p.feedback();
}

SpeculativeBigIntAsUintNParameters const& SpeculativeBigIntAsUintNParametersOf(
    Operator const* op) {
  DCHECK_EQ(IrOpcode::kSpeculativeBigIntAsUintN, op->opcode());
  return OpParameter<SpeculativeBigIntAsUintNParameters>(op);
}

616
size_t hash_value(AllocateParameters info) {
617 618
  return base::hash_combine(info.type(),
                            static_cast<int>(info.allocation_type()));
619 620 621 622
}

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
                                           AllocateParameters info) {
623
  return os << info.type() << ", " << info.allocation_type();
624 625 626
}

bool operator==(AllocateParameters const& lhs, AllocateParameters const& rhs) {
627 628
  return lhs.allocation_type() == rhs.allocation_type() &&
         lhs.type() == rhs.type();
629 630
}

631 632 633 634 635 636
const AllocateParameters& AllocateParametersOf(const Operator* op) {
  DCHECK(op->opcode() == IrOpcode::kAllocate ||
         op->opcode() == IrOpcode::kAllocateRaw);
  return OpParameter<AllocateParameters>(op);
}

637
AllocationType AllocationTypeOf(const Operator* op) {
638 639
  if (op->opcode() == IrOpcode::kNewDoubleElements ||
      op->opcode() == IrOpcode::kNewSmiOrObjectElements) {
640
    return OpParameter<AllocationType>(op);
641
  }
642
  return AllocateParametersOf(op).allocation_type();
643 644
}

645
Type AllocateTypeOf(const Operator* op) {
646
  DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
647
  return AllocateParametersOf(op).type();
648 649
}

650
AbortReason AbortReasonOf(const Operator* op) {
651
  DCHECK_EQ(IrOpcode::kRuntimeAbort, op->opcode());
652
  return static_cast<AbortReason>(OpParameter<int>(op));
653 654
}

655 656
const CheckTaggedInputParameters& CheckTaggedInputParametersOf(
    const Operator* op) {
657 658
  DCHECK(op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32 ||
         op->opcode() == IrOpcode::kCheckedTaggedToFloat64);
659 660 661 662 663
  return OpParameter<CheckTaggedInputParameters>(op);
}

std::ostream& operator<<(std::ostream& os,
                         const CheckTaggedInputParameters& params) {
664
  return os << params.mode() << ", " << params.feedback();
665 666 667
}

size_t hash_value(const CheckTaggedInputParameters& params) {
668 669
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
670 671 672 673 674 675 676 677
}

bool operator==(CheckTaggedInputParameters const& lhs,
                CheckTaggedInputParameters const& rhs) {
  return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
}

const CheckMinusZeroParameters& CheckMinusZeroParametersOf(const Operator* op) {
678 679 680 681
  DCHECK(op->opcode() == IrOpcode::kCheckedTaggedToInt32 ||
         op->opcode() == IrOpcode::kCheckedTaggedToInt64 ||
         op->opcode() == IrOpcode::kCheckedFloat64ToInt32 ||
         op->opcode() == IrOpcode::kCheckedFloat64ToInt64);
682 683 684 685 686
  return OpParameter<CheckMinusZeroParameters>(op);
}

std::ostream& operator<<(std::ostream& os,
                         const CheckMinusZeroParameters& params) {
687
  return os << params.mode() << ", " << params.feedback();
688 689 690
}

size_t hash_value(const CheckMinusZeroParameters& params) {
691 692
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
693 694 695 696 697 698 699
}

bool operator==(CheckMinusZeroParameters const& lhs,
                CheckMinusZeroParameters const& rhs) {
  return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
}

700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
#define PURE_OP_LIST(V)                                          \
  V(BooleanNot, Operator::kNoProperties, 1, 0)                   \
  V(NumberEqual, Operator::kCommutative, 2, 0)                   \
  V(NumberLessThan, Operator::kNoProperties, 2, 0)               \
  V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
  V(NumberAdd, Operator::kCommutative, 2, 0)                     \
  V(NumberSubtract, Operator::kNoProperties, 2, 0)               \
  V(NumberMultiply, Operator::kCommutative, 2, 0)                \
  V(NumberDivide, Operator::kNoProperties, 2, 0)                 \
  V(NumberModulus, Operator::kNoProperties, 2, 0)                \
  V(NumberBitwiseOr, Operator::kCommutative, 2, 0)               \
  V(NumberBitwiseXor, Operator::kCommutative, 2, 0)              \
  V(NumberBitwiseAnd, Operator::kCommutative, 2, 0)              \
  V(NumberShiftLeft, Operator::kNoProperties, 2, 0)              \
  V(NumberShiftRight, Operator::kNoProperties, 2, 0)             \
  V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0)      \
  V(NumberImul, Operator::kCommutative, 2, 0)                    \
  V(NumberAbs, Operator::kNoProperties, 1, 0)                    \
  V(NumberClz32, Operator::kNoProperties, 1, 0)                  \
  V(NumberCeil, Operator::kNoProperties, 1, 0)                   \
  V(NumberFloor, Operator::kNoProperties, 1, 0)                  \
  V(NumberFround, Operator::kNoProperties, 1, 0)                 \
  V(NumberAcos, Operator::kNoProperties, 1, 0)                   \
  V(NumberAcosh, Operator::kNoProperties, 1, 0)                  \
  V(NumberAsin, Operator::kNoProperties, 1, 0)                   \
  V(NumberAsinh, Operator::kNoProperties, 1, 0)                  \
  V(NumberAtan, Operator::kNoProperties, 1, 0)                   \
  V(NumberAtan2, Operator::kNoProperties, 2, 0)                  \
  V(NumberAtanh, Operator::kNoProperties, 1, 0)                  \
  V(NumberCbrt, Operator::kNoProperties, 1, 0)                   \
  V(NumberCos, Operator::kNoProperties, 1, 0)                    \
  V(NumberCosh, Operator::kNoProperties, 1, 0)                   \
  V(NumberExp, Operator::kNoProperties, 1, 0)                    \
  V(NumberExpm1, Operator::kNoProperties, 1, 0)                  \
  V(NumberLog, Operator::kNoProperties, 1, 0)                    \
  V(NumberLog1p, Operator::kNoProperties, 1, 0)                  \
  V(NumberLog10, Operator::kNoProperties, 1, 0)                  \
  V(NumberLog2, Operator::kNoProperties, 1, 0)                   \
  V(NumberMax, Operator::kNoProperties, 2, 0)                    \
  V(NumberMin, Operator::kNoProperties, 2, 0)                    \
  V(NumberPow, Operator::kNoProperties, 2, 0)                    \
  V(NumberRound, Operator::kNoProperties, 1, 0)                  \
  V(NumberSign, Operator::kNoProperties, 1, 0)                   \
  V(NumberSin, Operator::kNoProperties, 1, 0)                    \
  V(NumberSinh, Operator::kNoProperties, 1, 0)                   \
  V(NumberSqrt, Operator::kNoProperties, 1, 0)                   \
  V(NumberTan, Operator::kNoProperties, 1, 0)                    \
  V(NumberTanh, Operator::kNoProperties, 1, 0)                   \
  V(NumberTrunc, Operator::kNoProperties, 1, 0)                  \
  V(NumberToBoolean, Operator::kNoProperties, 1, 0)              \
  V(NumberToInt32, Operator::kNoProperties, 1, 0)                \
  V(NumberToString, Operator::kNoProperties, 1, 0)               \
  V(NumberToUint32, Operator::kNoProperties, 1, 0)               \
  V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0)         \
  V(NumberSilenceNaN, Operator::kNoProperties, 1, 0)             \
  V(BigIntNegate, Operator::kNoProperties, 1, 0)                 \
  V(StringConcat, Operator::kNoProperties, 3, 0)                 \
  V(StringToNumber, Operator::kNoProperties, 1, 0)               \
  V(StringFromSingleCharCode, Operator::kNoProperties, 1, 0)     \
  V(StringFromSingleCodePoint, Operator::kNoProperties, 1, 0)    \
  V(StringIndexOf, Operator::kNoProperties, 3, 0)                \
  V(StringLength, Operator::kNoProperties, 1, 0)                 \
  V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0)        \
  V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0)        \
  V(TypeOf, Operator::kNoProperties, 1, 1)                       \
  V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0)       \
  V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0)       \
  V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0)      \
  V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0)    \
  V(ChangeTaggedSignedToInt64, Operator::kNoProperties, 1, 0)    \
  V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0)          \
  V(ChangeTaggedToInt64, Operator::kNoProperties, 1, 0)          \
  V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0)         \
  V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0)        \
  V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0)   \
  V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \
  V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0)    \
  V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0)          \
  V(ChangeInt64ToTagged, Operator::kNoProperties, 1, 0)          \
  V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0)         \
  V(ChangeUint64ToTagged, Operator::kNoProperties, 1, 0)         \
  V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0)            \
  V(ChangeBitToTagged, Operator::kNoProperties, 1, 0)            \
  V(TruncateBigIntToUint64, Operator::kNoProperties, 1, 0)       \
  V(ChangeUint64ToBigInt, Operator::kNoProperties, 1, 0)         \
  V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0)          \
  V(TruncateTaggedPointerToBit, Operator::kNoProperties, 1, 0)   \
  V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0)       \
  V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0)      \
  V(ObjectIsArrayBufferView, Operator::kNoProperties, 1, 0)      \
  V(ObjectIsBigInt, Operator::kNoProperties, 1, 0)               \
  V(ObjectIsCallable, Operator::kNoProperties, 1, 0)             \
  V(ObjectIsConstructor, Operator::kNoProperties, 1, 0)          \
  V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0)   \
  V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0)            \
  V(NumberIsMinusZero, Operator::kNoProperties, 1, 0)            \
  V(ObjectIsNaN, Operator::kNoProperties, 1, 0)                  \
  V(NumberIsNaN, Operator::kNoProperties, 1, 0)                  \
  V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0)          \
  V(ObjectIsNumber, Operator::kNoProperties, 1, 0)               \
  V(ObjectIsReceiver, Operator::kNoProperties, 1, 0)             \
  V(ObjectIsSmi, Operator::kNoProperties, 1, 0)                  \
  V(ObjectIsString, Operator::kNoProperties, 1, 0)               \
  V(ObjectIsSymbol, Operator::kNoProperties, 1, 0)               \
  V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0)         \
  V(NumberIsFloat64Hole, Operator::kNoProperties, 1, 0)          \
  V(NumberIsFinite, Operator::kNoProperties, 1, 0)               \
  V(ObjectIsFiniteNumber, Operator::kNoProperties, 1, 0)         \
  V(NumberIsInteger, Operator::kNoProperties, 1, 0)              \
  V(ObjectIsSafeInteger, Operator::kNoProperties, 1, 0)          \
  V(NumberIsSafeInteger, Operator::kNoProperties, 1, 0)          \
  V(ObjectIsInteger, Operator::kNoProperties, 1, 0)              \
  V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
  V(SameValue, Operator::kCommutative, 2, 0)                     \
  V(SameValueNumbersOnly, Operator::kCommutative, 2, 0)          \
  V(NumberSameValue, Operator::kCommutative, 2, 0)               \
  V(ReferenceEqual, Operator::kCommutative, 2, 0)                \
  V(StringEqual, Operator::kCommutative, 2, 0)                   \
  V(StringLessThan, Operator::kNoProperties, 2, 0)               \
  V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
  V(ToBoolean, Operator::kNoProperties, 1, 0)                    \
  V(NewConsString, Operator::kNoProperties, 3, 0)
822

823
#define EFFECT_DEPENDENT_OP_LIST(V)                       \
824
  V(BigIntAdd, Operator::kNoProperties, 2, 1)             \
825
  V(BigIntSubtract, Operator::kNoProperties, 2, 1)        \
826 827 828 829
  V(StringCharCodeAt, Operator::kNoProperties, 2, 1)      \
  V(StringCodePointAt, Operator::kNoProperties, 2, 1)     \
  V(StringFromCodePointAt, Operator::kNoProperties, 2, 1) \
  V(StringSubstring, Operator::kNoProperties, 3, 1)       \
830
  V(DateNow, Operator::kNoProperties, 0, 1)
831

832 833 834 835 836
#define SPECULATIVE_NUMBER_BINOP_LIST(V)      \
  SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
  V(SpeculativeNumberEqual)                   \
  V(SpeculativeNumberLessThan)                \
  V(SpeculativeNumberLessThanOrEqual)
837

838 839 840 841 842 843 844 845 846 847 848 849 850 851
#define CHECKED_OP_LIST(V)                \
  V(CheckEqualsInternalizedString, 2, 0)  \
  V(CheckEqualsSymbol, 2, 0)              \
  V(CheckHeapObject, 1, 1)                \
  V(CheckInternalizedString, 1, 1)        \
  V(CheckNotTaggedHole, 1, 1)             \
  V(CheckReceiver, 1, 1)                  \
  V(CheckReceiverOrNullOrUndefined, 1, 1) \
  V(CheckSymbol, 1, 1)                    \
  V(CheckedInt32Add, 2, 1)                \
  V(CheckedInt32Div, 2, 1)                \
  V(CheckedInt32Mod, 2, 1)                \
  V(CheckedInt32Sub, 2, 1)                \
  V(CheckedUint32Div, 2, 1)               \
852
  V(CheckedUint32Mod, 2, 1)
853

854 855 856 857
#define CHECKED_WITH_FEEDBACK_OP_LIST(V)    \
  V(CheckNumber, 1, 1)                      \
  V(CheckSmi, 1, 1)                         \
  V(CheckString, 1, 1)                      \
858
  V(CheckBigInt, 1, 1)                      \
859 860 861
  V(CheckedInt32ToTaggedSigned, 1, 1)       \
  V(CheckedInt64ToInt32, 1, 1)              \
  V(CheckedInt64ToTaggedSigned, 1, 1)       \
862
  V(CheckedTaggedToArrayIndex, 1, 1)        \
863 864 865 866 867 868
  V(CheckedTaggedSignedToInt32, 1, 1)       \
  V(CheckedTaggedToTaggedPointer, 1, 1)     \
  V(CheckedTaggedToTaggedSigned, 1, 1)      \
  V(CheckedUint32ToInt32, 1, 1)             \
  V(CheckedUint32ToTaggedSigned, 1, 1)      \
  V(CheckedUint64ToInt32, 1, 1)             \
869
  V(CheckedUint64ToTaggedSigned, 1, 1)
870

871
#define CHECKED_BOUNDS_OP_LIST(V) \
872 873
  V(CheckedUint32Bounds)          \
  V(CheckedUint64Bounds)
874

875
struct SimplifiedOperatorGlobalCache final {
876
#define PURE(Name, properties, value_input_count, control_input_count)     \
877
  struct Name##Operator final : public Operator {                          \
878 879
    Name##Operator()                                                       \
        : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
880
                   value_input_count, 0, control_input_count, 1, 0, 0) {}  \
881
  };                                                                       \
882 883 884
  Name##Operator k##Name;
  PURE_OP_LIST(PURE)
#undef PURE
885

886 887 888 889 890 891 892 893
#define EFFECT_DEPENDENT(Name, properties, value_input_count,               \
                         control_input_count)                               \
  struct Name##Operator final : public Operator {                           \
    Name##Operator()                                                        \
        : Operator(IrOpcode::k##Name, Operator::kEliminatable | properties, \
                   #Name, value_input_count, 1, control_input_count, 1, 1,  \
                   0) {}                                                    \
  };                                                                        \
894 895 896 897
  Name##Operator k##Name;
  EFFECT_DEPENDENT_OP_LIST(EFFECT_DEPENDENT)
#undef EFFECT_DEPENDENT

898 899 900 901 902 903 904
#define CHECKED(Name, value_input_count, value_output_count)             \
  struct Name##Operator final : public Operator {                        \
    Name##Operator()                                                     \
        : Operator(IrOpcode::k##Name,                                    \
                   Operator::kFoldable | Operator::kNoThrow, #Name,      \
                   value_input_count, 1, 1, value_output_count, 1, 0) {} \
  };                                                                     \
905 906 907 908
  Name##Operator k##Name;
  CHECKED_OP_LIST(CHECKED)
#undef CHECKED

909 910 911 912 913 914
#define CHECKED_WITH_FEEDBACK(Name, value_input_count, value_output_count) \
  struct Name##Operator final : public Operator1<CheckParameters> {        \
    Name##Operator()                                                       \
        : Operator1<CheckParameters>(                                      \
              IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
              #Name, value_input_count, 1, 1, value_output_count, 1, 0,    \
915
              CheckParameters(FeedbackSource())) {}                        \
916 917 918 919 920
  };                                                                       \
  Name##Operator k##Name;
  CHECKED_WITH_FEEDBACK_OP_LIST(CHECKED_WITH_FEEDBACK)
#undef CHECKED_WITH_FEEDBACK

921 922 923 924 925 926 927 928 929 930 931
#define CHECKED_BOUNDS(Name)                                               \
  struct Name##Operator final : public Operator1<CheckBoundsParameters> {  \
    Name##Operator(FeedbackSource feedback, CheckBoundsFlags flags)        \
        : Operator1<CheckBoundsParameters>(                                \
              IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
              #Name, 2, 1, 1, 1, 1, 0,                                     \
              CheckBoundsParameters(feedback, flags)) {}                   \
  };                                                                       \
  Name##Operator k##Name = {FeedbackSource(), CheckBoundsFlags()};         \
  Name##Operator k##Name##Aborting = {FeedbackSource(),                    \
                                      CheckBoundsFlag::kAbortOnOutOfBounds};
932
  CHECKED_BOUNDS_OP_LIST(CHECKED_BOUNDS)
933 934 935 936 937 938 939 940
  CHECKED_BOUNDS(CheckBounds)
  // For IrOpcode::kCheckBounds, we allow additional flags:
  CheckBoundsOperator kCheckBoundsConverting = {
      FeedbackSource(), CheckBoundsFlag::kConvertStringAndMinusZero};
  CheckBoundsOperator kCheckBoundsAbortingAndConverting = {
      FeedbackSource(),
      CheckBoundsFlags(CheckBoundsFlag::kAbortOnOutOfBounds) |
          CheckBoundsFlags(CheckBoundsFlag::kConvertStringAndMinusZero)};
941 942
#undef CHECKED_BOUNDS

943
  template <DeoptimizeReason kDeoptimizeReason>
944
  struct CheckIfOperator final : public Operator1<CheckIfParameters> {
945
    CheckIfOperator()
946
        : Operator1<CheckIfParameters>(
947
              IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow,
948
              "CheckIf", 1, 1, 1, 0, 1, 0,
949
              CheckIfParameters(kDeoptimizeReason, FeedbackSource())) {}
950 951 952 953 954 955
  };
#define CHECK_IF(Name, message) \
  CheckIfOperator<DeoptimizeReason::k##Name> kCheckIf##Name;
  DEOPTIMIZE_REASON_LIST(CHECK_IF)
#undef CHECK_IF

956 957 958 959
  struct FindOrderedHashMapEntryOperator final : public Operator {
    FindOrderedHashMapEntryOperator()
        : Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable,
                   "FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {}
960
  };
961
  FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry;
962

963 964 965
  struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator {
    FindOrderedHashMapEntryForInt32KeyOperator()
        : Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key,
966
                   Operator::kEliminatable,
967
                   "FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {}
968
  };
969 970
  FindOrderedHashMapEntryForInt32KeyOperator
      kFindOrderedHashMapEntryForInt32Key;
971

972 973 974 975 976 977 978 979 980 981 982 983 984
  template <CheckForMinusZeroMode kMode>
  struct ChangeFloat64ToTaggedOperator final
      : public Operator1<CheckForMinusZeroMode> {
    ChangeFloat64ToTaggedOperator()
        : Operator1<CheckForMinusZeroMode>(
              IrOpcode::kChangeFloat64ToTagged, Operator::kPure,
              "ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {}
  };
  ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero>
      kChangeFloat64ToTaggedCheckForMinusZeroOperator;
  ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
      kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;

985 986 987 988 989 990 991 992 993 994 995 996 997 998
  template <CheckForMinusZeroMode kMode>
  struct CheckedInt32MulOperator final
      : public Operator1<CheckForMinusZeroMode> {
    CheckedInt32MulOperator()
        : Operator1<CheckForMinusZeroMode>(
              IrOpcode::kCheckedInt32Mul,
              Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1,
              1, 1, 1, 0, kMode) {}
  };
  CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero>
      kCheckedInt32MulCheckForMinusZeroOperator;
  CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
      kCheckedInt32MulDontCheckForMinusZeroOperator;

999 1000
  template <CheckForMinusZeroMode kMode>
  struct CheckedFloat64ToInt32Operator final
1001
      : public Operator1<CheckMinusZeroParameters> {
1002
    CheckedFloat64ToInt32Operator()
1003
        : Operator1<CheckMinusZeroParameters>(
1004 1005
              IrOpcode::kCheckedFloat64ToInt32,
              Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32",
1006
              1, 1, 1, 1, 1, 0,
1007
              CheckMinusZeroParameters(kMode, FeedbackSource())) {}
1008 1009 1010 1011 1012 1013
  };
  CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
      kCheckedFloat64ToInt32CheckForMinusZeroOperator;
  CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
      kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;

1014 1015 1016 1017 1018 1019 1020 1021
  template <CheckForMinusZeroMode kMode>
  struct CheckedFloat64ToInt64Operator final
      : public Operator1<CheckMinusZeroParameters> {
    CheckedFloat64ToInt64Operator()
        : Operator1<CheckMinusZeroParameters>(
              IrOpcode::kCheckedFloat64ToInt64,
              Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt64",
              1, 1, 1, 1, 1, 0,
1022
              CheckMinusZeroParameters(kMode, FeedbackSource())) {}
1023 1024 1025 1026 1027 1028
  };
  CheckedFloat64ToInt64Operator<CheckForMinusZeroMode::kCheckForMinusZero>
      kCheckedFloat64ToInt64CheckForMinusZeroOperator;
  CheckedFloat64ToInt64Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
      kCheckedFloat64ToInt64DontCheckForMinusZeroOperator;

1029 1030
  template <CheckForMinusZeroMode kMode>
  struct CheckedTaggedToInt32Operator final
1031
      : public Operator1<CheckMinusZeroParameters> {
1032
    CheckedTaggedToInt32Operator()
1033
        : Operator1<CheckMinusZeroParameters>(
1034 1035
              IrOpcode::kCheckedTaggedToInt32,
              Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32",
1036
              1, 1, 1, 1, 1, 0,
1037
              CheckMinusZeroParameters(kMode, FeedbackSource())) {}
1038 1039 1040 1041 1042 1043
  };
  CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
      kCheckedTaggedToInt32CheckForMinusZeroOperator;
  CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
      kCheckedTaggedToInt32DontCheckForMinusZeroOperator;

1044 1045 1046 1047 1048 1049 1050 1051
  template <CheckForMinusZeroMode kMode>
  struct CheckedTaggedToInt64Operator final
      : public Operator1<CheckMinusZeroParameters> {
    CheckedTaggedToInt64Operator()
        : Operator1<CheckMinusZeroParameters>(
              IrOpcode::kCheckedTaggedToInt64,
              Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt64",
              1, 1, 1, 1, 1, 0,
1052
              CheckMinusZeroParameters(kMode, FeedbackSource())) {}
1053 1054 1055 1056 1057 1058
  };
  CheckedTaggedToInt64Operator<CheckForMinusZeroMode::kCheckForMinusZero>
      kCheckedTaggedToInt64CheckForMinusZeroOperator;
  CheckedTaggedToInt64Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
      kCheckedTaggedToInt64DontCheckForMinusZeroOperator;

1059 1060
  template <CheckTaggedInputMode kMode>
  struct CheckedTaggedToFloat64Operator final
1061
      : public Operator1<CheckTaggedInputParameters> {
1062
    CheckedTaggedToFloat64Operator()
1063
        : Operator1<CheckTaggedInputParameters>(
1064 1065
              IrOpcode::kCheckedTaggedToFloat64,
              Operator::kFoldable | Operator::kNoThrow,
1066
              "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0,
1067
              CheckTaggedInputParameters(kMode, FeedbackSource())) {}
1068 1069 1070
  };
  CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
      kCheckedTaggedToFloat64NumberOperator;
1071 1072
  CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrBoolean>
      kCheckedTaggedToFloat64NumberOrBooleanOperator;
1073 1074 1075
  CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
      kCheckedTaggedToFloat64NumberOrOddballOperator;

1076 1077
  template <CheckTaggedInputMode kMode>
  struct CheckedTruncateTaggedToWord32Operator final
1078
      : public Operator1<CheckTaggedInputParameters> {
1079
    CheckedTruncateTaggedToWord32Operator()
1080
        : Operator1<CheckTaggedInputParameters>(
1081 1082
              IrOpcode::kCheckedTruncateTaggedToWord32,
              Operator::kFoldable | Operator::kNoThrow,
1083
              "CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0,
1084
              CheckTaggedInputParameters(kMode, FeedbackSource())) {}
1085 1086 1087 1088 1089 1090
  };
  CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber>
      kCheckedTruncateTaggedToWord32NumberOperator;
  CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball>
      kCheckedTruncateTaggedToWord32NumberOrOddballOperator;

1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
  template <ConvertReceiverMode kMode>
  struct ConvertReceiverOperator final : public Operator1<ConvertReceiverMode> {
    ConvertReceiverOperator()
        : Operator1<ConvertReceiverMode>(  // --
              IrOpcode::kConvertReceiver,  // opcode
              Operator::kEliminatable,     // flags
              "ConvertReceiver",           // name
              2, 1, 1, 1, 1, 0,            // counts
              kMode) {}                    // param
  };
  ConvertReceiverOperator<ConvertReceiverMode::kAny>
      kConvertReceiverAnyOperator;
  ConvertReceiverOperator<ConvertReceiverMode::kNullOrUndefined>
      kConvertReceiverNullOrUndefinedOperator;
  ConvertReceiverOperator<ConvertReceiverMode::kNotNullOrUndefined>
      kConvertReceiverNotNullOrUndefinedOperator;

1108
  template <CheckFloat64HoleMode kMode>
1109
  struct CheckFloat64HoleNaNOperator final
1110
      : public Operator1<CheckFloat64HoleParameters> {
1111
    CheckFloat64HoleNaNOperator()
1112
        : Operator1<CheckFloat64HoleParameters>(
1113
              IrOpcode::kCheckFloat64Hole,
1114
              Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
1115
              1, 1, 1, 1, 0,
1116
              CheckFloat64HoleParameters(kMode, FeedbackSource())) {}
1117
  };
1118
  CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
1119
      kCheckFloat64HoleAllowReturnHoleOperator;
1120
  CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
1121 1122
      kCheckFloat64HoleNeverReturnHoleOperator;

1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
  struct EnsureWritableFastElementsOperator final : public Operator {
    EnsureWritableFastElementsOperator()
        : Operator(                                     // --
              IrOpcode::kEnsureWritableFastElements,    // opcode
              Operator::kNoDeopt | Operator::kNoThrow,  // flags
              "EnsureWritableFastElements",             // name
              2, 1, 1, 1, 1, 0) {}                      // counts
  };
  EnsureWritableFastElementsOperator kEnsureWritableFastElements;

1133 1134 1135 1136 1137 1138
  template <GrowFastElementsMode kMode>
  struct GrowFastElementsOperator final
      : public Operator1<GrowFastElementsParameters> {
    GrowFastElementsOperator()
        : Operator1(IrOpcode::kMaybeGrowFastElements, Operator::kNoThrow,
                    "MaybeGrowFastElements", 4, 1, 1, 1, 1, 0,
1139
                    GrowFastElementsParameters(kMode, FeedbackSource())) {}
1140 1141 1142 1143 1144 1145 1146
  };

  GrowFastElementsOperator<GrowFastElementsMode::kDoubleElements>
      kGrowFastElementsOperatorDoubleElements;
  GrowFastElementsOperator<GrowFastElementsMode::kSmiOrObjectElements>
      kGrowFastElementsOperatorSmiOrObjectElements;

1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
  struct LoadFieldByIndexOperator final : public Operator {
    LoadFieldByIndexOperator()
        : Operator(                         // --
              IrOpcode::kLoadFieldByIndex,  // opcode
              Operator::kEliminatable,      // flags,
              "LoadFieldByIndex",           // name
              2, 1, 1, 1, 1, 0) {}          // counts;
  };
  LoadFieldByIndexOperator kLoadFieldByIndex;

1157 1158 1159 1160
  struct LoadStackArgumentOperator final : public Operator {
    LoadStackArgumentOperator()
        : Operator(                          // --
              IrOpcode::kLoadStackArgument,  // opcode
1161 1162 1163
              Operator::kEliminatable,       // flags
              "LoadStackArgument",           // name
              2, 1, 1, 1, 1, 0) {}           // counts
1164 1165 1166
  };
  LoadStackArgumentOperator kLoadStackArgument;

1167 1168 1169 1170 1171 1172 1173 1174
#define SPECULATIVE_NUMBER_BINOP(Name)                                      \
  template <NumberOperationHint kHint>                                      \
  struct Name##Operator final : public Operator1<NumberOperationHint> {     \
    Name##Operator()                                                        \
        : Operator1<NumberOperationHint>(                                   \
              IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow,  \
              #Name, 2, 1, 1, 1, 1, 0, kHint) {}                            \
  };                                                                        \
1175 1176 1177 1178
  Name##Operator<NumberOperationHint::kSignedSmall>                         \
      k##Name##SignedSmallOperator;                                         \
  Name##Operator<NumberOperationHint::kSignedSmallInputs>                   \
      k##Name##SignedSmallInputsOperator;                                   \
1179
  Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator;     \
1180 1181 1182 1183
  Name##Operator<NumberOperationHint::kNumberOrOddball>                     \
      k##Name##NumberOrOddballOperator;
  SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
#undef SPECULATIVE_NUMBER_BINOP
1184 1185
  SpeculativeNumberEqualOperator<NumberOperationHint::kNumberOrBoolean>
      kSpeculativeNumberEqualNumberOrBooleanOperator;
1186

1187 1188
  template <NumberOperationHint kHint>
  struct SpeculativeToNumberOperator final
1189
      : public Operator1<NumberOperationParameters> {
1190
    SpeculativeToNumberOperator()
1191 1192 1193 1194
        : Operator1<NumberOperationParameters>(
              IrOpcode::kSpeculativeToNumber,
              Operator::kFoldable | Operator::kNoThrow, "SpeculativeToNumber",
              1, 1, 1, 1, 1, 0,
1195
              NumberOperationParameters(kHint, FeedbackSource())) {}
1196
  };
1197 1198
  SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
      kSpeculativeToNumberSignedSmallOperator;
1199 1200 1201 1202
  SpeculativeToNumberOperator<NumberOperationHint::kNumber>
      kSpeculativeToNumberNumberOperator;
  SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball>
      kSpeculativeToNumberNumberOrOddballOperator;
1203 1204
};

1205 1206
namespace {
DEFINE_LAZY_LEAKY_OBJECT_GETTER(SimplifiedOperatorGlobalCache,
1207
                                GetSimplifiedOperatorGlobalCache)
1208
}  // namespace
1209 1210

SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
1211
    : cache_(*GetSimplifiedOperatorGlobalCache()), zone_(zone) {}
1212

1213
#define GET_FROM_CACHE(Name, ...) \
1214
  const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
1215
PURE_OP_LIST(GET_FROM_CACHE)
1216
EFFECT_DEPENDENT_OP_LIST(GET_FROM_CACHE)
1217
CHECKED_OP_LIST(GET_FROM_CACHE)
1218
GET_FROM_CACHE(FindOrderedHashMapEntry)
1219
GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key)
1220
GET_FROM_CACHE(LoadFieldByIndex)
1221
#undef GET_FROM_CACHE
1222

1223 1224 1225
#define GET_FROM_CACHE_WITH_FEEDBACK(Name, value_input_count,               \
                                     value_output_count)                    \
  const Operator* SimplifiedOperatorBuilder::Name(                          \
1226
      const FeedbackSource& feedback) {                                     \
1227 1228 1229
    if (!feedback.IsValid()) {                                              \
      return &cache_.k##Name;                                               \
    }                                                                       \
1230
    return zone()->New<Operator1<CheckParameters>>(                         \
1231 1232 1233 1234 1235 1236 1237
        IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, \
        value_input_count, 1, 1, value_output_count, 1, 0,                  \
        CheckParameters(feedback));                                         \
  }
CHECKED_WITH_FEEDBACK_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK)
#undef GET_FROM_CACHE_WITH_FEEDBACK

1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
#define GET_FROM_CACHE_WITH_FEEDBACK(Name)                             \
  const Operator* SimplifiedOperatorBuilder::Name(                     \
      const FeedbackSource& feedback, CheckBoundsFlags flags) {        \
    DCHECK(!(flags & CheckBoundsFlag::kConvertStringAndMinusZero));    \
    if (!feedback.IsValid()) {                                         \
      if (flags & CheckBoundsFlag::kAbortOnOutOfBounds) {              \
        return &cache_.k##Name##Aborting;                              \
      } else {                                                         \
        return &cache_.k##Name;                                        \
      }                                                                \
    }                                                                  \
    return zone()->New<SimplifiedOperatorGlobalCache::Name##Operator>( \
        feedback, flags);                                              \
1251 1252 1253 1254
  }
CHECKED_BOUNDS_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK)
#undef GET_FROM_CACHE_WITH_FEEDBACK

1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
// For IrOpcode::kCheckBounds, we allow additional flags:
const Operator* SimplifiedOperatorBuilder::CheckBounds(
    const FeedbackSource& feedback, CheckBoundsFlags flags) {
  if (!feedback.IsValid()) {
    if (flags & CheckBoundsFlag::kAbortOnOutOfBounds) {
      if (flags & CheckBoundsFlag::kConvertStringAndMinusZero) {
        return &cache_.kCheckBoundsAbortingAndConverting;
      } else {
        return &cache_.kCheckBoundsAborting;
      }
    } else {
      if (flags & CheckBoundsFlag::kConvertStringAndMinusZero) {
        return &cache_.kCheckBoundsConverting;
      } else {
        return &cache_.kCheckBounds;
      }
    }
  }
1273 1274
  return zone()->New<SimplifiedOperatorGlobalCache::CheckBoundsOperator>(
      feedback, flags);
1275 1276
}

1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
bool IsCheckedWithFeedback(const Operator* op) {
#define CASE(Name, ...) case IrOpcode::k##Name:
  switch (op->opcode()) {
    CHECKED_WITH_FEEDBACK_OP_LIST(CASE) return true;
    default:
      return false;
  }
#undef CASE
}

1287
const Operator* SimplifiedOperatorBuilder::RuntimeAbort(AbortReason reason) {
1288
  return zone()->New<Operator1<int>>(           // --
1289 1290 1291 1292 1293
      IrOpcode::kRuntimeAbort,                  // opcode
      Operator::kNoThrow | Operator::kNoDeopt,  // flags
      "RuntimeAbort",                           // name
      0, 1, 1, 0, 1, 0,                         // counts
      static_cast<int>(reason));                // parameter
1294 1295
}

1296 1297
const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAsUintN(
    int bits, const FeedbackSource& feedback) {
1298 1299
  CHECK(0 <= bits && bits <= 64);

1300 1301 1302 1303
  return zone()->New<Operator1<SpeculativeBigIntAsUintNParameters>>(
      IrOpcode::kSpeculativeBigIntAsUintN, Operator::kNoProperties,
      "SpeculativeBigIntAsUintN", 1, 1, 1, 1, 1, 0,
      SpeculativeBigIntAsUintNParameters(bits, feedback));
1304 1305
}

1306 1307 1308 1309 1310 1311
const Operator* SimplifiedOperatorBuilder::UpdateInterruptBudget(int delta) {
  return zone()->New<Operator1<int>>(
      IrOpcode::kUpdateInterruptBudget, Operator::kNoThrow | Operator::kNoDeopt,
      "UpdateInterruptBudget", 1, 1, 1, 0, 1, 0, delta);
}

1312 1313 1314
const Operator* SimplifiedOperatorBuilder::TierUpCheck() {
  return zone()->New<Operator>(IrOpcode::kTierUpCheck,
                               Operator::kNoThrow | Operator::kNoDeopt,
1315
                               "TierUpCheck", 5, 1, 1, 0, 1, 0);
1316 1317
}

1318
const Operator* SimplifiedOperatorBuilder::AssertType(Type type) {
Georg Neis's avatar
Georg Neis committed
1319
  DCHECK(type.CanBeAsserted());
1320
  return zone()->New<Operator1<Type>>(IrOpcode::kAssertType,
1321 1322 1323 1324
                                      Operator::kNoThrow | Operator::kNoDeopt,
                                      "AssertType", 1, 0, 0, 1, 0, 0, type);
}

1325 1326 1327 1328 1329 1330
const Operator* SimplifiedOperatorBuilder::VerifyType() {
  return zone()->New<Operator>(IrOpcode::kVerifyType,
                               Operator::kNoThrow | Operator::kNoDeopt,
                               "VerifyType", 1, 0, 0, 1, 0, 0);
}

1331
const Operator* SimplifiedOperatorBuilder::CheckIf(
1332
    DeoptimizeReason reason, const FeedbackSource& feedback) {
1333 1334
  if (!feedback.IsValid()) {
    switch (reason) {
1335 1336 1337 1338 1339
#define CHECK_IF(Name, message)   \
  case DeoptimizeReason::k##Name: \
    return &cache_.kCheckIf##Name;
    DEOPTIMIZE_REASON_LIST(CHECK_IF)
#undef CHECK_IF
1340
    }
1341
  }
1342
  return zone()->New<Operator1<CheckIfParameters>>(
1343 1344
      IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow, "CheckIf",
      1, 1, 1, 0, 1, 0, CheckIfParameters(reason, feedback));
1345 1346
}

1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged(
    CheckForMinusZeroMode mode) {
  switch (mode) {
    case CheckForMinusZeroMode::kCheckForMinusZero:
      return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator;
    case CheckForMinusZeroMode::kDontCheckForMinusZero:
      return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
  }
  UNREACHABLE();
}

1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
    CheckForMinusZeroMode mode) {
  switch (mode) {
    case CheckForMinusZeroMode::kCheckForMinusZero:
      return &cache_.kCheckedInt32MulCheckForMinusZeroOperator;
    case CheckForMinusZeroMode::kDontCheckForMinusZero:
      return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator;
  }
  UNREACHABLE();
}

1369
const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32(
1370
    CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1371 1372 1373 1374 1375 1376 1377
  if (!feedback.IsValid()) {
    switch (mode) {
      case CheckForMinusZeroMode::kCheckForMinusZero:
        return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator;
      case CheckForMinusZeroMode::kDontCheckForMinusZero:
        return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
    }
1378
  }
1379
  return zone()->New<Operator1<CheckMinusZeroParameters>>(
1380 1381 1382
      IrOpcode::kCheckedFloat64ToInt32,
      Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32", 1, 1,
      1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback));
1383 1384
}

1385
const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt64(
1386
    CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1387 1388 1389 1390 1391 1392 1393 1394
  if (!feedback.IsValid()) {
    switch (mode) {
      case CheckForMinusZeroMode::kCheckForMinusZero:
        return &cache_.kCheckedFloat64ToInt64CheckForMinusZeroOperator;
      case CheckForMinusZeroMode::kDontCheckForMinusZero:
        return &cache_.kCheckedFloat64ToInt64DontCheckForMinusZeroOperator;
    }
  }
1395
  return zone()->New<Operator1<CheckMinusZeroParameters>>(
1396 1397 1398 1399 1400
      IrOpcode::kCheckedFloat64ToInt64,
      Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt64", 1, 1,
      1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback));
}

1401
const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
1402
    CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1403 1404 1405 1406 1407 1408 1409
  if (!feedback.IsValid()) {
    switch (mode) {
      case CheckForMinusZeroMode::kCheckForMinusZero:
        return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator;
      case CheckForMinusZeroMode::kDontCheckForMinusZero:
        return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
    }
1410
  }
1411
  return zone()->New<Operator1<CheckMinusZeroParameters>>(
1412 1413 1414
      IrOpcode::kCheckedTaggedToInt32, Operator::kFoldable | Operator::kNoThrow,
      "CheckedTaggedToInt32", 1, 1, 1, 1, 1, 0,
      CheckMinusZeroParameters(mode, feedback));
1415 1416
}

1417
const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt64(
1418
    CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1419 1420 1421 1422 1423 1424 1425 1426
  if (!feedback.IsValid()) {
    switch (mode) {
      case CheckForMinusZeroMode::kCheckForMinusZero:
        return &cache_.kCheckedTaggedToInt64CheckForMinusZeroOperator;
      case CheckForMinusZeroMode::kDontCheckForMinusZero:
        return &cache_.kCheckedTaggedToInt64DontCheckForMinusZeroOperator;
    }
  }
1427
  return zone()->New<Operator1<CheckMinusZeroParameters>>(
1428 1429 1430 1431 1432
      IrOpcode::kCheckedTaggedToInt64, Operator::kFoldable | Operator::kNoThrow,
      "CheckedTaggedToInt64", 1, 1, 1, 1, 1, 0,
      CheckMinusZeroParameters(mode, feedback));
}

1433
const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
1434
    CheckTaggedInputMode mode, const FeedbackSource& feedback) {
1435 1436 1437 1438
  if (!feedback.IsValid()) {
    switch (mode) {
      case CheckTaggedInputMode::kNumber:
        return &cache_.kCheckedTaggedToFloat64NumberOperator;
1439 1440
      case CheckTaggedInputMode::kNumberOrBoolean:
        return &cache_.kCheckedTaggedToFloat64NumberOrBooleanOperator;
1441 1442 1443
      case CheckTaggedInputMode::kNumberOrOddball:
        return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
    }
1444
  }
1445
  return zone()->New<Operator1<CheckTaggedInputParameters>>(
1446 1447 1448
      IrOpcode::kCheckedTaggedToFloat64,
      Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToFloat64", 1, 1,
      1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
1449 1450
}

1451
const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
1452
    CheckTaggedInputMode mode, const FeedbackSource& feedback) {
1453 1454 1455 1456
  if (!feedback.IsValid()) {
    switch (mode) {
      case CheckTaggedInputMode::kNumber:
        return &cache_.kCheckedTruncateTaggedToWord32NumberOperator;
1457 1458 1459
      case CheckTaggedInputMode::kNumberOrBoolean:
        // Not used currently.
        UNREACHABLE();
1460 1461 1462
      case CheckTaggedInputMode::kNumberOrOddball:
        return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
    }
1463
  }
1464
  return zone()->New<Operator1<CheckTaggedInputParameters>>(
1465 1466 1467
      IrOpcode::kCheckedTruncateTaggedToWord32,
      Operator::kFoldable | Operator::kNoThrow, "CheckedTruncateTaggedToWord32",
      1, 1, 1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
1468 1469
}

1470 1471
const Operator* SimplifiedOperatorBuilder::CheckMaps(
    CheckMapsFlags flags, ZoneHandleSet<Map> maps,
1472
    const FeedbackSource& feedback) {
1473
  CheckMapsParameters const parameters(flags, maps, feedback);
1474
  return zone()->New<Operator1<CheckMapsParameters>>(  // --
1475 1476 1477 1478 1479
      IrOpcode::kCheckMaps,                            // opcode
      Operator::kNoThrow | Operator::kNoWrite,         // flags
      "CheckMaps",                                     // name
      1, 1, 1, 0, 1, 0,                                // counts
      parameters);                                     // parameter
1480 1481
}

1482
const Operator* SimplifiedOperatorBuilder::DynamicCheckMaps(
1483 1484 1485
    CheckMapsFlags flags, Handle<Object> handler,
    ZoneHandleSet<Map> const& maps, const FeedbackSource& feedback) {
  DynamicCheckMapsParameters const parameters(flags, handler, maps, feedback);
1486 1487 1488 1489 1490 1491 1492 1493
  return zone()->New<Operator1<DynamicCheckMapsParameters>>(  // --
      IrOpcode::kDynamicCheckMaps,                            // opcode
      Operator::kNoThrow | Operator::kNoWrite,                // flags
      "DynamicCheckMaps",                                     // name
      1, 1, 1, 0, 1, 0,                                       // counts
      parameters);                                            // parameter
}

1494
const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
1495
  DCHECK_LT(0, maps.size());
1496
  return zone()->New<Operator1<ZoneHandleSet<Map>>>(  // --
1497 1498 1499 1500
      IrOpcode::kMapGuard, Operator::kEliminatable,   // opcode
      "MapGuard",                                     // name
      1, 1, 1, 0, 1, 0,                               // counts
      maps);                                          // parameter
1501 1502
}

1503 1504
const Operator* SimplifiedOperatorBuilder::CompareMaps(
    ZoneHandleSet<Map> maps) {
1505
  DCHECK_LT(0, maps.size());
1506
  return zone()->New<Operator1<ZoneHandleSet<Map>>>(  // --
1507
      IrOpcode::kCompareMaps,                         // opcode
1508
      Operator::kNoThrow | Operator::kNoWrite,        // flags
1509 1510 1511
      "CompareMaps",                                  // name
      1, 1, 1, 1, 1, 0,                               // counts
      maps);                                          // parameter
1512 1513
}

1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526
const Operator* SimplifiedOperatorBuilder::ConvertReceiver(
    ConvertReceiverMode mode) {
  switch (mode) {
    case ConvertReceiverMode::kAny:
      return &cache_.kConvertReceiverAnyOperator;
    case ConvertReceiverMode::kNullOrUndefined:
      return &cache_.kConvertReceiverNullOrUndefinedOperator;
    case ConvertReceiverMode::kNotNullOrUndefined:
      return &cache_.kConvertReceiverNotNullOrUndefinedOperator;
  }
  UNREACHABLE();
}

1527
const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
1528
    CheckFloat64HoleMode mode, FeedbackSource const& feedback) {
1529 1530 1531 1532 1533 1534 1535 1536
  if (!feedback.IsValid()) {
    switch (mode) {
      case CheckFloat64HoleMode::kAllowReturnHole:
        return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
      case CheckFloat64HoleMode::kNeverReturnHole:
        return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
    }
    UNREACHABLE();
1537
  }
1538
  return zone()->New<Operator1<CheckFloat64HoleParameters>>(
1539 1540 1541
      IrOpcode::kCheckFloat64Hole, Operator::kFoldable | Operator::kNoThrow,
      "CheckFloat64Hole", 1, 1, 1, 1, 1, 0,
      CheckFloat64HoleParameters(mode, feedback));
1542 1543
}

1544
const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAdd(
1545
    BigIntOperationHint hint) {
1546
  return zone()->New<Operator1<BigIntOperationHint>>(
1547
      IrOpcode::kSpeculativeBigIntAdd, Operator::kFoldable | Operator::kNoThrow,
1548
      "SpeculativeBigIntAdd", 2, 1, 1, 1, 1, 0, hint);
1549 1550
}

1551 1552
const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntSubtract(
    BigIntOperationHint hint) {
1553
  return zone()->New<Operator1<BigIntOperationHint>>(
1554 1555 1556
      IrOpcode::kSpeculativeBigIntSubtract,
      Operator::kFoldable | Operator::kNoThrow, "SpeculativeBigIntSubtract", 2,
      1, 1, 1, 1, 0, hint);
1557 1558
}

1559 1560
const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntNegate(
    BigIntOperationHint hint) {
1561
  return zone()->New<Operator1<BigIntOperationHint>>(
1562 1563 1564 1565 1566
      IrOpcode::kSpeculativeBigIntNegate,
      Operator::kFoldable | Operator::kNoThrow, "SpeculativeBigIntNegate", 1, 1,
      1, 1, 1, 0, hint);
}

1567 1568
const Operator* SimplifiedOperatorBuilder::CheckClosure(
    const Handle<FeedbackCell>& feedback_cell) {
1569
  return zone()->New<Operator1<Handle<FeedbackCell>>>(  // --
1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
      IrOpcode::kCheckClosure,                          // opcode
      Operator::kNoThrow | Operator::kNoWrite,          // flags
      "CheckClosure",                                   // name
      1, 1, 1, 1, 1, 0,                                 // counts
      feedback_cell);                                   // parameter
}

Handle<FeedbackCell> FeedbackCellOf(const Operator* op) {
  DCHECK(IrOpcode::kCheckClosure == op->opcode());
  return OpParameter<Handle<FeedbackCell>>(op);
}

1582
const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
1583
    NumberOperationHint hint, const FeedbackSource& feedback) {
1584 1585
  if (!feedback.IsValid()) {
    switch (hint) {
1586 1587 1588 1589
      case NumberOperationHint::kSignedSmall:
        return &cache_.kSpeculativeToNumberSignedSmallOperator;
      case NumberOperationHint::kSignedSmallInputs:
        break;
1590 1591
      case NumberOperationHint::kNumber:
        return &cache_.kSpeculativeToNumberNumberOperator;
1592 1593 1594
      case NumberOperationHint::kNumberOrBoolean:
        // Not used currently.
        UNREACHABLE();
1595 1596 1597
      case NumberOperationHint::kNumberOrOddball:
        return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
    }
1598
  }
1599
  return zone()->New<Operator1<NumberOperationParameters>>(
1600 1601 1602
      IrOpcode::kSpeculativeToNumber, Operator::kFoldable | Operator::kNoThrow,
      "SpeculativeToNumber", 1, 1, 1, 1, 1, 0,
      NumberOperationParameters(hint, feedback));
1603 1604
}

1605 1606 1607 1608
const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
  return &cache_.kEnsureWritableFastElements;
}

1609
const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements(
1610
    GrowFastElementsMode mode, const FeedbackSource& feedback) {
1611 1612 1613 1614 1615 1616 1617 1618
  if (!feedback.IsValid()) {
    switch (mode) {
      case GrowFastElementsMode::kDoubleElements:
        return &cache_.kGrowFastElementsOperatorDoubleElements;
      case GrowFastElementsMode::kSmiOrObjectElements:
        return &cache_.kGrowFastElementsOperatorSmiOrObjectElements;
    }
  }
1619
  return zone()->New<Operator1<GrowFastElementsParameters>>(  // --
1620 1621 1622 1623 1624
      IrOpcode::kMaybeGrowFastElements,                       // opcode
      Operator::kNoThrow,                                     // flags
      "MaybeGrowFastElements",                                // name
      4, 1, 1, 1, 1, 0,                                       // counts
      GrowFastElementsParameters(mode, feedback));            // parameter
1625 1626
}

1627 1628
const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
    ElementsTransition transition) {
1629
  return zone()->New<Operator1<ElementsTransition>>(  // --
1630
      IrOpcode::kTransitionElementsKind,              // opcode
1631
      Operator::kNoThrow,                             // flags
1632
      "TransitionElementsKind",                       // name
1633
      1, 1, 1, 0, 1, 0,                               // counts
1634 1635 1636
      transition);                                    // parameter
}

1637 1638 1639 1640 1641 1642
const Operator* SimplifiedOperatorBuilder::ArgumentsLength() {
  return zone()->New<Operator>(    // --
      IrOpcode::kArgumentsLength,  // opcode
      Operator::kPure,             // flags
      "ArgumentsLength",           // name
      0, 0, 0, 1, 0, 0);           // counts
1643 1644
}

1645 1646 1647 1648 1649 1650
const Operator* SimplifiedOperatorBuilder::RestLength(
    int formal_parameter_count) {
  return zone()->New<Operator1<int>>(  // --
      IrOpcode::kRestLength,           // opcode
      Operator::kPure,                 // flags
      "RestLength",                    // name
1651
      0, 0, 0, 1, 0, 0,                // counts
1652
      formal_parameter_count);         // parameter
1653 1654
}

1655 1656 1657 1658
int FormalParameterCountOf(const Operator* op) {
  DCHECK(op->opcode() == IrOpcode::kArgumentsLength ||
         op->opcode() == IrOpcode::kRestLength);
  return OpParameter<int>(op);
1659 1660
}

1661 1662 1663 1664
bool operator==(CheckParameters const& lhs, CheckParameters const& rhs) {
  return lhs.feedback() == rhs.feedback();
}

1665 1666 1667 1668
size_t hash_value(CheckParameters const& p) {
  FeedbackSource::Hash feedback_hash;
  return feedback_hash(p.feedback());
}
1669 1670 1671 1672 1673 1674

std::ostream& operator<<(std::ostream& os, CheckParameters const& p) {
  return os << p.feedback();
}

CheckParameters const& CheckParametersOf(Operator const* op) {
1675
  if (op->opcode() == IrOpcode::kCheckBounds ||
1676 1677
      op->opcode() == IrOpcode::kCheckedUint32Bounds ||
      op->opcode() == IrOpcode::kCheckedUint64Bounds) {
1678 1679
    return OpParameter<CheckBoundsParameters>(op).check_parameters();
  }
1680 1681 1682 1683 1684 1685
#define MAKE_OR(name, arg2, arg3) op->opcode() == IrOpcode::k##name ||
  CHECK((CHECKED_WITH_FEEDBACK_OP_LIST(MAKE_OR) false));
#undef MAKE_OR
  return OpParameter<CheckParameters>(op);
}

1686 1687 1688
bool operator==(CheckBoundsParameters const& lhs,
                CheckBoundsParameters const& rhs) {
  return lhs.check_parameters() == rhs.check_parameters() &&
1689
         lhs.flags() == rhs.flags();
1690 1691 1692
}

size_t hash_value(CheckBoundsParameters const& p) {
1693
  return base::hash_combine(hash_value(p.check_parameters()), p.flags());
1694 1695 1696
}

std::ostream& operator<<(std::ostream& os, CheckBoundsParameters const& p) {
1697
  os << p.check_parameters() << ", " << p.flags();
1698 1699 1700 1701
  return os;
}

CheckBoundsParameters const& CheckBoundsParametersOf(Operator const* op) {
1702 1703 1704
  DCHECK(op->opcode() == IrOpcode::kCheckBounds ||
         op->opcode() == IrOpcode::kCheckedUint32Bounds ||
         op->opcode() == IrOpcode::kCheckedUint64Bounds);
1705 1706 1707
  return OpParameter<CheckBoundsParameters>(op);
}

1708 1709 1710 1711 1712
bool operator==(CheckIfParameters const& lhs, CheckIfParameters const& rhs) {
  return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback();
}

size_t hash_value(CheckIfParameters const& p) {
1713 1714
  FeedbackSource::Hash feedback_hash;
  return base::hash_combine(p.reason(), feedback_hash(p.feedback()));
1715 1716 1717
}

std::ostream& operator<<(std::ostream& os, CheckIfParameters const& p) {
1718
  return os << p.reason() << ", " << p.feedback();
1719 1720 1721 1722 1723 1724 1725
}

CheckIfParameters const& CheckIfParametersOf(Operator const* op) {
  CHECK(op->opcode() == IrOpcode::kCheckIf);
  return OpParameter<CheckIfParameters>(op);
}

1726 1727 1728 1729 1730 1731
FastApiCallParameters const& FastApiCallParametersOf(const Operator* op) {
  DCHECK_EQ(IrOpcode::kFastApiCall, op->opcode());
  return OpParameter<FastApiCallParameters>(op);
}

std::ostream& operator<<(std::ostream& os, FastApiCallParameters const& p) {
1732 1733 1734 1735 1736
  const auto& c_functions = p.c_functions();
  for (size_t i = 0; i < c_functions.size(); i++) {
    os << c_functions[i].address << ":" << c_functions[i].signature << ", ";
  }
  return os << p.feedback() << ", " << p.descriptor();
1737 1738 1739
}

size_t hash_value(FastApiCallParameters const& p) {
1740 1741 1742 1743 1744 1745
  const auto& c_functions = p.c_functions();
  size_t hash = 0;
  for (size_t i = 0; i < c_functions.size(); i++) {
    hash = base::hash_combine(c_functions[i].address, c_functions[i].signature);
  }
  return base::hash_combine(hash, FeedbackSource::Hash()(p.feedback()),
1746 1747 1748 1749 1750
                            p.descriptor());
}

bool operator==(FastApiCallParameters const& lhs,
                FastApiCallParameters const& rhs) {
1751
  return lhs.c_functions() == rhs.c_functions() &&
1752 1753 1754 1755
         lhs.feedback() == rhs.feedback() &&
         lhs.descriptor() == rhs.descriptor();
}

1756
const Operator* SimplifiedOperatorBuilder::NewDoubleElements(
1757
    AllocationType allocation) {
1758
  return zone()->New<Operator1<AllocationType>>(  // --
1759 1760 1761 1762 1763
      IrOpcode::kNewDoubleElements,               // opcode
      Operator::kEliminatable,                    // flags
      "NewDoubleElements",                        // name
      1, 1, 1, 1, 1, 0,                           // counts
      allocation);                                // parameter
1764 1765
}

1766
const Operator* SimplifiedOperatorBuilder::NewSmiOrObjectElements(
1767
    AllocationType allocation) {
1768
  return zone()->New<Operator1<AllocationType>>(  // --
1769 1770 1771 1772 1773
      IrOpcode::kNewSmiOrObjectElements,          // opcode
      Operator::kEliminatable,                    // flags
      "NewSmiOrObjectElements",                   // name
      1, 1, 1, 1, 1, 0,                           // counts
      allocation);                                // parameter
1774 1775
}

1776
const Operator* SimplifiedOperatorBuilder::NewArgumentsElements(
1777
    CreateArgumentsType type, int formal_parameter_count) {
1778
  return zone()->New<Operator1<NewArgumentsElementsParameters>>(  // --
1779 1780 1781
      IrOpcode::kNewArgumentsElements,                            // opcode
      Operator::kEliminatable,                                    // flags
      "NewArgumentsElements",                                     // name
1782
      1, 1, 0, 1, 1, 0,                                           // counts
1783 1784
      NewArgumentsElementsParameters(type,
                                     formal_parameter_count));  // parameter
1785 1786
}

1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
bool operator==(const NewArgumentsElementsParameters& lhs,
                const NewArgumentsElementsParameters& rhs) {
  return lhs.arguments_type() == rhs.arguments_type() &&
         lhs.formal_parameter_count() == rhs.formal_parameter_count();
}

inline size_t hash_value(const NewArgumentsElementsParameters& params) {
  return base::hash_combine(params.arguments_type(),
                            params.formal_parameter_count());
}

std::ostream& operator<<(std::ostream& os,
                         const NewArgumentsElementsParameters& params) {
  return os << params.arguments_type()
            << ", parameter_count = " << params.formal_parameter_count();
}

const NewArgumentsElementsParameters& NewArgumentsElementsParametersOf(
    const Operator* op) {
1806
  DCHECK_EQ(IrOpcode::kNewArgumentsElements, op->opcode());
1807
  return OpParameter<NewArgumentsElementsParameters>(op);
1808 1809
}

1810
const Operator* SimplifiedOperatorBuilder::Allocate(Type type,
1811
                                                    AllocationType allocation) {
1812
  return zone()->New<Operator1<AllocateParameters>>(
1813 1814
      IrOpcode::kAllocate, Operator::kEliminatable, "Allocate", 1, 1, 1, 1, 1,
      0, AllocateParameters(type, allocation));
1815 1816
}

1817
const Operator* SimplifiedOperatorBuilder::AllocateRaw(
1818 1819 1820 1821 1822 1823 1824
    Type type, AllocationType allocation,
    AllowLargeObjects allow_large_objects) {
  // We forbid optimized allocations to allocate in a different generation than
  // requested.
  DCHECK(!(allow_large_objects == AllowLargeObjects::kTrue &&
           allocation == AllocationType::kYoung &&
           !FLAG_young_generation_large_objects));
1825
  return zone()->New<Operator1<AllocateParameters>>(
1826 1827
      IrOpcode::kAllocateRaw, Operator::kEliminatable, "AllocateRaw", 1, 1, 1,
      1, 1, 1, AllocateParameters(type, allocation, allow_large_objects));
1828 1829
}

1830 1831 1832
#define SPECULATIVE_NUMBER_BINOP(Name)                                        \
  const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \
    switch (hint) {                                                           \
1833 1834 1835 1836
      case NumberOperationHint::kSignedSmall:                                 \
        return &cache_.k##Name##SignedSmallOperator;                          \
      case NumberOperationHint::kSignedSmallInputs:                           \
        return &cache_.k##Name##SignedSmallInputsOperator;                    \
1837 1838
      case NumberOperationHint::kNumber:                                      \
        return &cache_.k##Name##NumberOperator;                               \
1839 1840 1841
      case NumberOperationHint::kNumberOrBoolean:                             \
        /* Not used currenly. */                                              \
        UNREACHABLE();                                                        \
1842 1843 1844 1845 1846
      case NumberOperationHint::kNumberOrOddball:                             \
        return &cache_.k##Name##NumberOrOddballOperator;                      \
    }                                                                         \
    UNREACHABLE();                                                            \
    return nullptr;                                                           \
1847
  }
1848 1849 1850
SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
SPECULATIVE_NUMBER_BINOP(SpeculativeNumberLessThan)
SPECULATIVE_NUMBER_BINOP(SpeculativeNumberLessThanOrEqual)
1851
#undef SPECULATIVE_NUMBER_BINOP
1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867
const Operator* SimplifiedOperatorBuilder::SpeculativeNumberEqual(
    NumberOperationHint hint) {
  switch (hint) {
    case NumberOperationHint::kSignedSmall:
      return &cache_.kSpeculativeNumberEqualSignedSmallOperator;
    case NumberOperationHint::kSignedSmallInputs:
      return &cache_.kSpeculativeNumberEqualSignedSmallInputsOperator;
    case NumberOperationHint::kNumber:
      return &cache_.kSpeculativeNumberEqualNumberOperator;
    case NumberOperationHint::kNumberOrBoolean:
      return &cache_.kSpeculativeNumberEqualNumberOrBooleanOperator;
    case NumberOperationHint::kNumberOrOddball:
      return &cache_.kSpeculativeNumberEqualNumberOrOddballOperator;
  }
  UNREACHABLE();
}
1868

1869 1870 1871 1872 1873 1874
#define ACCESS_OP_LIST(V)                                                \
  V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)                 \
  V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)                 \
  V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1)             \
  V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)             \
  V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1)    \
1875
  V(LoadFromObject, ObjectAccess, Operator::kNoWrite, 2, 1, 1)           \
1876
  V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)    \
1877
  V(StoreToObject, ObjectAccess, Operator::kNoRead, 3, 1, 0)             \
1878 1879
  V(LoadDataViewElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \
  V(StoreDataViewElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)
1880 1881 1882 1883

#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
               output_count)                                                   \
  const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
1884 1885 1886 1887 1888
    return zone()->New<Operator1<Type>>(                                       \
        IrOpcode::k##Name,                                                     \
        Operator::kNoDeopt | Operator::kNoThrow | properties, #Name,           \
        value_input_count, 1, control_input_count, output_count, 1, 0,         \
        access);                                                               \
1889 1890 1891 1892
  }
ACCESS_OP_LIST(ACCESS)
#undef ACCESS

1893
const Operator* SimplifiedOperatorBuilder::LoadMessage() {
1894
  return zone()->New<Operator>(IrOpcode::kLoadMessage, Operator::kEliminatable,
1895
                               "LoadMessage", 1, 1, 1, 1, 1, 0);
1896 1897 1898
}

const Operator* SimplifiedOperatorBuilder::StoreMessage() {
1899 1900 1901 1902
  return zone()->New<Operator>(
      IrOpcode::kStoreMessage,
      Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoRead,
      "StoreMessage", 2, 1, 1, 0, 1, 0);
1903 1904
}

1905 1906 1907 1908
const Operator* SimplifiedOperatorBuilder::LoadStackArgument() {
  return &cache_.kLoadStackArgument;
}

1909 1910 1911
const Operator* SimplifiedOperatorBuilder::TransitionAndStoreElement(
    Handle<Map> double_map, Handle<Map> fast_map) {
  TransitionAndStoreElementParameters parameters(double_map, fast_map);
1912
  return zone()->New<Operator1<TransitionAndStoreElementParameters>>(
1913 1914 1915 1916 1917
      IrOpcode::kTransitionAndStoreElement,
      Operator::kNoDeopt | Operator::kNoThrow, "TransitionAndStoreElement", 3,
      1, 1, 0, 1, 0, parameters);
}

1918
const Operator* SimplifiedOperatorBuilder::StoreSignedSmallElement() {
1919
  return zone()->New<Operator>(IrOpcode::kStoreSignedSmallElement,
1920 1921 1922 1923
                               Operator::kNoDeopt | Operator::kNoThrow,
                               "StoreSignedSmallElement", 3, 1, 1, 0, 1, 0);
}

1924 1925 1926
const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNumberElement(
    Handle<Map> double_map) {
  TransitionAndStoreNumberElementParameters parameters(double_map);
1927
  return zone()->New<Operator1<TransitionAndStoreNumberElementParameters>>(
1928 1929 1930 1931 1932 1933
      IrOpcode::kTransitionAndStoreNumberElement,
      Operator::kNoDeopt | Operator::kNoThrow,
      "TransitionAndStoreNumberElement", 3, 1, 1, 0, 1, 0, parameters);
}

const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
1934
    Handle<Map> fast_map, Type value_type) {
1935
  TransitionAndStoreNonNumberElementParameters parameters(fast_map, value_type);
1936
  return zone()->New<Operator1<TransitionAndStoreNonNumberElementParameters>>(
1937 1938 1939 1940 1941
      IrOpcode::kTransitionAndStoreNonNumberElement,
      Operator::kNoDeopt | Operator::kNoThrow,
      "TransitionAndStoreNonNumberElement", 3, 1, 1, 0, 1, 0, parameters);
}

1942
const Operator* SimplifiedOperatorBuilder::FastApiCall(
1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
    const FastApiCallFunctionVector& c_functions,
    FeedbackSource const& feedback, CallDescriptor* descriptor) {
  DCHECK(!c_functions.empty());

  // All function overloads have the same number of arguments and options.
  const CFunctionInfo* signature = c_functions[0].signature;
  const int argument_count = signature->ArgumentCount();
  for (size_t i = 1; i < c_functions.size(); i++) {
    CHECK_NOT_NULL(c_functions[i].signature);
    DCHECK_EQ(c_functions[i].signature->ArgumentCount(), argument_count);
    DCHECK_EQ(c_functions[i].signature->HasOptions(),
              c_functions[0].signature->HasOptions());
  }

1957
  int value_input_count =
1958
      argument_count +
1959 1960
      static_cast<int>(descriptor->ParameterCount()) +  // slow call
      FastApiCallNode::kEffectAndControlInputCount;
1961
  return zone()->New<Operator1<FastApiCallParameters>>(
1962 1963
      IrOpcode::kFastApiCall, Operator::kNoThrow, "FastApiCall",
      value_input_count, 1, 1, 1, 1, 0,
1964
      FastApiCallParameters(c_functions, feedback, descriptor));
1965 1966
}

1967
int FastApiCallNode::FastCallExtraInputCount() const {
1968 1969 1970
  const CFunctionInfo* signature = Parameters().c_functions()[0].signature;
  CHECK_NOT_NULL(signature);
  return kEffectAndControlInputCount + (signature->HasOptions() ? 1 : 0);
1971 1972
}

1973 1974
int FastApiCallNode::FastCallArgumentCount() const {
  FastApiCallParameters p = FastApiCallParametersOf(node()->op());
1975
  const CFunctionInfo* signature = p.c_functions()[0].signature;
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987
  CHECK_NOT_NULL(signature);
  return signature->ArgumentCount();
}

int FastApiCallNode::SlowCallArgumentCount() const {
  FastApiCallParameters p = FastApiCallParametersOf(node()->op());
  CallDescriptor* descriptor = p.descriptor();
  CHECK_NOT_NULL(descriptor);
  return static_cast<int>(descriptor->ParameterCount()) +
         kContextAndFrameStateInputCount;
}

1988
#undef PURE_OP_LIST
1989
#undef EFFECT_DEPENDENT_OP_LIST
1990
#undef SPECULATIVE_NUMBER_BINOP_LIST
1991
#undef CHECKED_WITH_FEEDBACK_OP_LIST
1992
#undef CHECKED_BOUNDS_OP_LIST
1993 1994 1995
#undef CHECKED_OP_LIST
#undef ACCESS_OP_LIST

1996 1997 1998
}  // namespace compiler
}  // namespace internal
}  // namespace v8