simplified-operator.h 43.5 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2014 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.

#ifndef V8_COMPILER_SIMPLIFIED_OPERATOR_H_
#define V8_COMPILER_SIMPLIFIED_OPERATOR_H_

8 9
#include <iosfwd>

10
#include "src/base/compiler-specific.h"
11
#include "src/codegen/machine-type.h"
12
#include "src/codegen/tnode.h"
13
#include "src/common/globals.h"
14
#include "src/compiler/common-operator.h"
15
#include "src/compiler/feedback-source.h"
16
#include "src/compiler/node-properties.h"
17
#include "src/compiler/operator.h"
18
#include "src/compiler/types.h"
19
#include "src/compiler/write-barrier-kind.h"
20
#include "src/deoptimizer/deoptimize-reason.h"
21 22
#include "src/handles/handles.h"
#include "src/handles/maybe-handles.h"
23
#include "src/objects/objects.h"
24
#include "src/objects/type-hints.h"
25
#include "src/zone/zone-handle-set.h"
26 27

namespace v8 {
28 29
class CFunctionInfo;

30
namespace internal {
31 32

// Forward declarations.
33
enum class AbortReason : uint8_t;
34
class Zone;
35

36 37
namespace compiler {

38
// Forward declarations.
39
class CallDescriptor;
40
class Operator;
41
struct SimplifiedOperatorGlobalCache;
42
struct WasmTypeCheckConfig;
43

44
enum BaseTaggedness : uint8_t { kUntaggedBase, kTaggedBase };
45

46
size_t hash_value(BaseTaggedness);
47

48
std::ostream& operator<<(std::ostream&, BaseTaggedness);
49

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
struct ConstFieldInfo {
  // the map that introduced the const field, if any. An access is considered
  // mutable iff the handle is null.
  MaybeHandle<Map> owner_map;

  ConstFieldInfo() : owner_map(MaybeHandle<Map>()) {}
  explicit ConstFieldInfo(Handle<Map> owner_map) : owner_map(owner_map) {}

  bool IsConst() const { return !owner_map.is_null(); }

  // No const field owner, i.e., a mutable field
  static ConstFieldInfo None() { return ConstFieldInfo(); }
};

V8_EXPORT_PRIVATE bool operator==(ConstFieldInfo const&, ConstFieldInfo const&);

size_t hash_value(ConstFieldInfo const&);

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
                                           ConstFieldInfo const&);

71 72 73
// An access descriptor for loads/stores of fixed structures like field
// accesses of heap objects. Accesses from either tagged or untagged base
// pointers are supported; untagging is done automatically during lowering.
74
struct FieldAccess {
75 76
  BaseTaggedness base_is_tagged;  // specifies if the base pointer is tagged.
  int offset;                     // offset of the field, without tag.
77
  MaybeHandle<Name> name;         // debugging only.
78
  MaybeHandle<Map> map;           // map of the field value (if known).
79
  Type type;                      // type of the field.
80
  MachineType machine_type;       // machine type of the field.
81
  WriteBarrierKind write_barrier_kind;  // write barrier hint.
82 83
  ConstFieldInfo const_field_info;      // the constness of this access, and the
                                    // field owner map, if the access is const
84
  bool is_store_in_literal;  // originates from a kStoreInLiteral access
Samuel Groß's avatar
Samuel Groß committed
85
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
86 87
  ExternalPointerTag external_pointer_tag = kExternalPointerNullTag;
#endif
88 89 90 91
  bool maybe_initializing_or_transitioning_store;  // store is potentially
                                                   // initializing a newly
                                                   // allocated object or part
                                                   // of a map transition.
92

93 94 95 96 97
  FieldAccess()
      : base_is_tagged(kTaggedBase),
        offset(0),
        type(Type::None()),
        machine_type(MachineType::None()),
98
        write_barrier_kind(kFullWriteBarrier),
99
        const_field_info(ConstFieldInfo::None()),
100 101
        is_store_in_literal(false),
        maybe_initializing_or_transitioning_store(false) {}
102 103

  FieldAccess(BaseTaggedness base_is_tagged, int offset, MaybeHandle<Name> name,
104
              MaybeHandle<Map> map, Type type, MachineType machine_type,
105
              WriteBarrierKind write_barrier_kind,
106
              ConstFieldInfo const_field_info = ConstFieldInfo::None(),
107
              bool is_store_in_literal = false,
Samuel Groß's avatar
Samuel Groß committed
108
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
109
              ExternalPointerTag external_pointer_tag = kExternalPointerNullTag,
110
#endif
111
              bool maybe_initializing_or_transitioning_store = false)
112 113 114 115 116 117
      : base_is_tagged(base_is_tagged),
        offset(offset),
        name(name),
        map(map),
        type(type),
        machine_type(machine_type),
118
        write_barrier_kind(write_barrier_kind),
119
        const_field_info(const_field_info),
120
        is_store_in_literal(is_store_in_literal),
Samuel Groß's avatar
Samuel Groß committed
121
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
122
        external_pointer_tag(external_pointer_tag),
123
#endif
124 125
        maybe_initializing_or_transitioning_store(
            maybe_initializing_or_transitioning_store) {
126
    DCHECK_GE(offset, 0);
127 128 129 130 131 132 133
    DCHECK_IMPLIES(
        machine_type.IsMapWord(),
        offset == HeapObject::kMapOffset && base_is_tagged != kUntaggedBase);
    DCHECK_IMPLIES(machine_type.IsMapWord(),
                   (write_barrier_kind == kMapWriteBarrier ||
                    write_barrier_kind == kNoWriteBarrier ||
                    write_barrier_kind == kAssertNoWriteBarrier));
134
  }
135

136
  int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
137 138
};

139
V8_EXPORT_PRIVATE bool operator==(FieldAccess const&, FieldAccess const&);
140 141

size_t hash_value(FieldAccess const&);
142

143
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, FieldAccess const&);
144

145
V8_EXPORT_PRIVATE FieldAccess const& FieldAccessOf(const Operator* op)
146
    V8_WARN_UNUSED_RESULT;
147

148 149 150
template <>
void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
                                            PrintVerbosity verbose) const;
151

152 153 154 155
// An access descriptor for loads/stores of indexed structures like characters
// in strings or off-heap backing stores. Accesses from either tagged or
// untagged base pointers are supported; untagging is done automatically during
// lowering.
156
struct ElementAccess {
157 158
  BaseTaggedness base_is_tagged;  // specifies if the base pointer is tagged.
  int header_size;                // size of the header, without tag.
159
  Type type;                      // type of the element.
160
  MachineType machine_type;       // machine type of the element.
161
  WriteBarrierKind write_barrier_kind;  // write barrier hint.
162

163 164 165 166 167
  ElementAccess()
      : base_is_tagged(kTaggedBase),
        header_size(0),
        type(Type::None()),
        machine_type(MachineType::None()),
168
        write_barrier_kind(kFullWriteBarrier) {}
169

170
  ElementAccess(BaseTaggedness base_is_tagged, int header_size, Type type,
171
                MachineType machine_type, WriteBarrierKind write_barrier_kind)
172 173 174 175
      : base_is_tagged(base_is_tagged),
        header_size(header_size),
        type(type),
        machine_type(machine_type),
176
        write_barrier_kind(write_barrier_kind) {}
177

178
  int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
179 180
};

181
V8_EXPORT_PRIVATE bool operator==(ElementAccess const&, ElementAccess const&);
182 183

size_t hash_value(ElementAccess const&);
184

185
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ElementAccess const&);
186

187
V8_EXPORT_PRIVATE ElementAccess const& ElementAccessOf(const Operator* op)
188
    V8_WARN_UNUSED_RESULT;
189

190
ExternalArrayType ExternalArrayTypeOf(const Operator* op) V8_WARN_UNUSED_RESULT;
191

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
// An access descriptor for loads/stores of CSA-accessible structures.
struct ObjectAccess {
  MachineType machine_type;             // machine type of the field.
  WriteBarrierKind write_barrier_kind;  // write barrier hint.

  ObjectAccess()
      : machine_type(MachineType::None()),
        write_barrier_kind(kFullWriteBarrier) {}

  ObjectAccess(MachineType machine_type, WriteBarrierKind write_barrier_kind)
      : machine_type(machine_type), write_barrier_kind(write_barrier_kind) {}

  int tag() const { return kHeapObjectTag; }
};

V8_EXPORT_PRIVATE bool operator==(ObjectAccess const&, ObjectAccess const&);

size_t hash_value(ObjectAccess const&);

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ObjectAccess const&);

V8_EXPORT_PRIVATE ObjectAccess const& ObjectAccessOf(const Operator* op)
    V8_WARN_UNUSED_RESULT;

216
// The ConvertReceiverMode is used as parameter by ConvertReceiver operators.
217
ConvertReceiverMode ConvertReceiverModeOf(Operator const* op)
218
    V8_WARN_UNUSED_RESULT;
219

220 221 222 223 224
// A the parameters for several Check nodes. The {feedback} parameter is
// optional. If {feedback} references a valid CallIC slot and this MapCheck
// fails, then speculation on that CallIC slot will be disabled.
class CheckParameters final {
 public:
225
  explicit CheckParameters(const FeedbackSource& feedback)
226 227
      : feedback_(feedback) {}

228
  FeedbackSource const& feedback() const { return feedback_; }
229 230

 private:
231
  FeedbackSource feedback_;
232 233 234 235 236 237 238 239
};

bool operator==(CheckParameters const&, CheckParameters const&);

size_t hash_value(CheckParameters const&);

std::ostream& operator<<(std::ostream&, CheckParameters const&);

240
CheckParameters const& CheckParametersOf(Operator const*) V8_WARN_UNUSED_RESULT;
241

242 243 244 245 246 247 248
enum class CheckBoundsFlag : uint8_t {
  kConvertStringAndMinusZero = 1 << 0,  // instead of deopting on such inputs
  kAbortOnOutOfBounds = 1 << 1,         // instead of deopting if input is OOB
};
using CheckBoundsFlags = base::Flags<CheckBoundsFlag>;
DEFINE_OPERATORS_FOR_FLAGS(CheckBoundsFlags)

249 250
class CheckBoundsParameters final {
 public:
251 252
  CheckBoundsParameters(const FeedbackSource& feedback, CheckBoundsFlags flags)
      : check_parameters_(feedback), flags_(flags) {}
253

254
  CheckBoundsFlags flags() const { return flags_; }
255 256 257 258
  const CheckParameters& check_parameters() const { return check_parameters_; }

 private:
  CheckParameters check_parameters_;
259
  CheckBoundsFlags flags_;
260 261 262 263 264 265 266 267 268 269 270
};

bool operator==(CheckBoundsParameters const&, CheckBoundsParameters const&);

size_t hash_value(CheckBoundsParameters const&);

std::ostream& operator<<(std::ostream&, CheckBoundsParameters const&);

CheckBoundsParameters const& CheckBoundsParametersOf(Operator const*)
    V8_WARN_UNUSED_RESULT;

271 272 273
class CheckIfParameters final {
 public:
  explicit CheckIfParameters(DeoptimizeReason reason,
274
                             const FeedbackSource& feedback)
275 276
      : reason_(reason), feedback_(feedback) {}

277
  FeedbackSource const& feedback() const { return feedback_; }
278 279 280 281
  DeoptimizeReason reason() const { return reason_; }

 private:
  DeoptimizeReason reason_;
282
  FeedbackSource feedback_;
283 284 285 286 287 288 289 290 291 292 293
};

bool operator==(CheckIfParameters const&, CheckIfParameters const&);

size_t hash_value(CheckIfParameters const&);

std::ostream& operator<<(std::ostream&, CheckIfParameters const&);

CheckIfParameters const& CheckIfParametersOf(Operator const*)
    V8_WARN_UNUSED_RESULT;

294 295 296 297 298 299 300 301 302
enum class CheckFloat64HoleMode : uint8_t {
  kNeverReturnHole,  // Never return the hole (deoptimize instead).
  kAllowReturnHole   // Allow to return the hole (signaling NaN).
};

size_t hash_value(CheckFloat64HoleMode);

std::ostream& operator<<(std::ostream&, CheckFloat64HoleMode);

303 304 305
class CheckFloat64HoleParameters {
 public:
  CheckFloat64HoleParameters(CheckFloat64HoleMode mode,
306
                             FeedbackSource const& feedback)
307 308 309
      : mode_(mode), feedback_(feedback) {}

  CheckFloat64HoleMode mode() const { return mode_; }
310
  FeedbackSource const& feedback() const { return feedback_; }
311 312 313

 private:
  CheckFloat64HoleMode mode_;
314
  FeedbackSource feedback_;
315 316 317
};

CheckFloat64HoleParameters const& CheckFloat64HoleParametersOf(Operator const*)
318
    V8_WARN_UNUSED_RESULT;
319

320 321 322 323 324 325 326 327 328
std::ostream& operator<<(std::ostream&, CheckFloat64HoleParameters const&);

size_t hash_value(CheckFloat64HoleParameters const&);

bool operator==(CheckFloat64HoleParameters const&,
                CheckFloat64HoleParameters const&);
bool operator!=(CheckFloat64HoleParameters const&,
                CheckFloat64HoleParameters const&);

329 330 331
// Parameter for CheckClosure node.
Handle<FeedbackCell> FeedbackCellOf(const Operator* op);

332 333
enum class CheckTaggedInputMode : uint8_t {
  kNumber,
334
  kNumberOrBoolean,
335 336 337 338 339
  kNumberOrOddball,
};

size_t hash_value(CheckTaggedInputMode);

340
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, CheckTaggedInputMode);
341

342 343 344
class CheckTaggedInputParameters {
 public:
  CheckTaggedInputParameters(CheckTaggedInputMode mode,
345
                             const FeedbackSource& feedback)
346 347 348
      : mode_(mode), feedback_(feedback) {}

  CheckTaggedInputMode mode() const { return mode_; }
349
  const FeedbackSource& feedback() const { return feedback_; }
350 351 352

 private:
  CheckTaggedInputMode mode_;
353
  FeedbackSource feedback_;
354 355 356
};

const CheckTaggedInputParameters& CheckTaggedInputParametersOf(const Operator*)
357
    V8_WARN_UNUSED_RESULT;
358 359 360 361 362 363 364 365

std::ostream& operator<<(std::ostream&,
                         const CheckTaggedInputParameters& params);

size_t hash_value(const CheckTaggedInputParameters& params);

bool operator==(CheckTaggedInputParameters const&,
                CheckTaggedInputParameters const&);
366

367 368 369 370 371 372 373
enum class CheckForMinusZeroMode : uint8_t {
  kCheckForMinusZero,
  kDontCheckForMinusZero,
};

size_t hash_value(CheckForMinusZeroMode);

374 375
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
                                           CheckForMinusZeroMode);
376

377 378
CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator*)
    V8_WARN_UNUSED_RESULT;
379

380 381 382
class CheckMinusZeroParameters {
 public:
  CheckMinusZeroParameters(CheckForMinusZeroMode mode,
383
                           const FeedbackSource& feedback)
384 385 386
      : mode_(mode), feedback_(feedback) {}

  CheckForMinusZeroMode mode() const { return mode_; }
387
  const FeedbackSource& feedback() const { return feedback_; }
388 389 390

 private:
  CheckForMinusZeroMode mode_;
391
  FeedbackSource feedback_;
392 393
};

394 395
V8_EXPORT_PRIVATE const CheckMinusZeroParameters& CheckMinusZeroParametersOf(
    const Operator* op) V8_WARN_UNUSED_RESULT;
396

397 398
V8_EXPORT_PRIVATE std::ostream& operator<<(
    std::ostream&, const CheckMinusZeroParameters& params);
399 400 401 402 403 404

size_t hash_value(const CheckMinusZeroParameters& params);

bool operator==(CheckMinusZeroParameters const&,
                CheckMinusZeroParameters const&);

405 406
enum class CheckMapsFlag : uint8_t {
  kNone = 0u,
407
  kTryMigrateInstance = 1u << 0,
408
};
409
using CheckMapsFlags = base::Flags<CheckMapsFlag>;
410 411 412 413 414

DEFINE_OPERATORS_FOR_FLAGS(CheckMapsFlags)

std::ostream& operator<<(std::ostream&, CheckMapsFlags);

415 416 417
// A descriptor for map checks. The {feedback} parameter is optional.
// If {feedback} references a valid CallIC slot and this MapCheck fails,
// then speculation on that CallIC slot will be disabled.
418 419
class CheckMapsParameters final {
 public:
420
  CheckMapsParameters(CheckMapsFlags flags, ZoneHandleSet<Map> const& maps,
421
                      const FeedbackSource& feedback)
422
      : flags_(flags), maps_(maps), feedback_(feedback) {}
423

424
  CheckMapsFlags flags() const { return flags_; }
425
  ZoneHandleSet<Map> const& maps() const { return maps_; }
426
  FeedbackSource const& feedback() const { return feedback_; }
427 428

 private:
429
  CheckMapsFlags const flags_;
430
  ZoneHandleSet<Map> const maps_;
431
  FeedbackSource const feedback_;
432 433 434 435 436 437 438 439 440
};

bool operator==(CheckMapsParameters const&, CheckMapsParameters const&);

size_t hash_value(CheckMapsParameters const&);

std::ostream& operator<<(std::ostream&, CheckMapsParameters const&);

CheckMapsParameters const& CheckMapsParametersOf(Operator const*)
441
    V8_WARN_UNUSED_RESULT;
442

443
ZoneHandleSet<Map> const& MapGuardMapsOf(Operator const*) V8_WARN_UNUSED_RESULT;
444

445
// Parameters for CompareMaps operator.
446
ZoneHandleSet<Map> const& CompareMapsParametersOf(Operator const*)
447
    V8_WARN_UNUSED_RESULT;
448

449
// A descriptor for growing elements backing stores.
450 451 452
enum class GrowFastElementsMode : uint8_t {
  kDoubleElements,
  kSmiOrObjectElements
453 454
};

455 456 457
inline size_t hash_value(GrowFastElementsMode mode) {
  return static_cast<uint8_t>(mode);
}
458

459
std::ostream& operator<<(std::ostream&, GrowFastElementsMode);
460

461 462 463
class GrowFastElementsParameters {
 public:
  GrowFastElementsParameters(GrowFastElementsMode mode,
464
                             const FeedbackSource& feedback)
465 466 467
      : mode_(mode), feedback_(feedback) {}

  GrowFastElementsMode mode() const { return mode_; }
468
  const FeedbackSource& feedback() const { return feedback_; }
469 470 471

 private:
  GrowFastElementsMode mode_;
472
  FeedbackSource feedback_;
473 474 475 476 477 478 479 480 481 482
};

bool operator==(const GrowFastElementsParameters&,
                const GrowFastElementsParameters&);

inline size_t hash_value(const GrowFastElementsParameters&);

std::ostream& operator<<(std::ostream&, const GrowFastElementsParameters&);

const GrowFastElementsParameters& GrowFastElementsParametersOf(const Operator*)
483
    V8_WARN_UNUSED_RESULT;
484

485
// A descriptor for elements kind transitions.
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
class ElementsTransition final {
 public:
  enum Mode : uint8_t {
    kFastTransition,  // simple transition, just updating the map.
    kSlowTransition   // full transition, round-trip to the runtime.
  };

  ElementsTransition(Mode mode, Handle<Map> source, Handle<Map> target)
      : mode_(mode), source_(source), target_(target) {}

  Mode mode() const { return mode_; }
  Handle<Map> source() const { return source_; }
  Handle<Map> target() const { return target_; }

 private:
  Mode const mode_;
  Handle<Map> const source_;
  Handle<Map> const target_;
504 505
};

506 507
bool operator==(ElementsTransition const&, ElementsTransition const&);

508 509
size_t hash_value(ElementsTransition);

510 511
std::ostream& operator<<(std::ostream&, ElementsTransition);

512
ElementsTransition const& ElementsTransitionOf(const Operator* op)
513
    V8_WARN_UNUSED_RESULT;
514

515 516 517
// Parameters for TransitionAndStoreElement, or
// TransitionAndStoreNonNumberElement, or
// TransitionAndStoreNumberElement.
518 519
Handle<Map> DoubleMapParameterOf(const Operator* op) V8_WARN_UNUSED_RESULT;
Handle<Map> FastMapParameterOf(const Operator* op) V8_WARN_UNUSED_RESULT;
520

521
// Parameters for TransitionAndStoreNonNumberElement.
522
Type ValueTypeParameterOf(const Operator* op) V8_WARN_UNUSED_RESULT;
523

524 525
// A hint for speculative number operations.
enum class NumberOperationHint : uint8_t {
526 527 528
  kSignedSmall,        // Inputs were Smi, output was in Smi.
  kSignedSmallInputs,  // Inputs were Smi, output was Number.
  kNumber,             // Inputs were Number, output was Number.
529
  kNumberOrBoolean,    // Inputs were Number or Boolean, output was Number.
530
  kNumberOrOddball,    // Inputs were Number or Oddball, output was Number.
531 532
};

533 534 535 536
enum class BigIntOperationHint : uint8_t {
  kBigInt,
};

537
size_t hash_value(NumberOperationHint);
538
size_t hash_value(BigIntOperationHint);
539

540
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, NumberOperationHint);
541
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BigIntOperationHint);
542
V8_EXPORT_PRIVATE NumberOperationHint NumberOperationHintOf(const Operator* op)
543 544
    V8_WARN_UNUSED_RESULT;

545 546 547
class NumberOperationParameters {
 public:
  NumberOperationParameters(NumberOperationHint hint,
548
                            const FeedbackSource& feedback)
549 550 551
      : hint_(hint), feedback_(feedback) {}

  NumberOperationHint hint() const { return hint_; }
552
  const FeedbackSource& feedback() const { return feedback_; }
553 554 555

 private:
  NumberOperationHint hint_;
556
  FeedbackSource feedback_;
557 558 559 560 561 562 563 564
};

size_t hash_value(NumberOperationParameters const&);
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
                                           const NumberOperationParameters&);
bool operator==(NumberOperationParameters const&,
                NumberOperationParameters const&);
const NumberOperationParameters& NumberOperationParametersOf(const Operator* op)
565
    V8_WARN_UNUSED_RESULT;
566

567
class SpeculativeBigIntAsNParameters {
568
 public:
569
  SpeculativeBigIntAsNParameters(int bits, const FeedbackSource& feedback)
570 571 572 573 574 575 576 577 578 579 580 581 582
      : bits_(bits), feedback_(feedback) {
    DCHECK_GE(bits_, 0);
    DCHECK_LE(bits_, 64);
  }

  int bits() const { return bits_; }
  const FeedbackSource& feedback() const { return feedback_; }

 private:
  int bits_;
  FeedbackSource feedback_;
};

583
size_t hash_value(SpeculativeBigIntAsNParameters const&);
584
V8_EXPORT_PRIVATE std::ostream& operator<<(
585 586 587 588
    std::ostream&, const SpeculativeBigIntAsNParameters&);
bool operator==(SpeculativeBigIntAsNParameters const&,
                SpeculativeBigIntAsNParameters const&);
const SpeculativeBigIntAsNParameters& SpeculativeBigIntAsNParametersOf(
589 590
    const Operator* op) V8_WARN_UNUSED_RESULT;

591
int FormalParameterCountOf(const Operator* op) V8_WARN_UNUSED_RESULT;
592

593 594
class AllocateParameters {
 public:
595 596 597 598 599 600
  AllocateParameters(
      Type type, AllocationType allocation_type,
      AllowLargeObjects allow_large_objects = AllowLargeObjects::kFalse)
      : type_(type),
        allocation_type_(allocation_type),
        allow_large_objects_(allow_large_objects) {}
601

602
  Type type() const { return type_; }
603
  AllocationType allocation_type() const { return allocation_type_; }
604
  AllowLargeObjects allow_large_objects() const { return allow_large_objects_; }
605 606

 private:
607
  Type type_;
608
  AllocationType allocation_type_;
609
  AllowLargeObjects allow_large_objects_;
610 611
};

612 613
bool IsCheckedWithFeedback(const Operator* op);

614 615 616 617 618 619
size_t hash_value(AllocateParameters);

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, AllocateParameters);

bool operator==(AllocateParameters const&, AllocateParameters const&);

620 621 622
const AllocateParameters& AllocateParametersOf(const Operator* op)
    V8_WARN_UNUSED_RESULT;

623
AllocationType AllocationTypeOf(const Operator* op) V8_WARN_UNUSED_RESULT;
624

625
Type AllocateTypeOf(const Operator* op) V8_WARN_UNUSED_RESULT;
626

627
UnicodeEncoding UnicodeEncodingOf(const Operator*) V8_WARN_UNUSED_RESULT;
628

629
AbortReason AbortReasonOf(const Operator* op) V8_WARN_UNUSED_RESULT;
630

631
DeoptimizeReason DeoptimizeReasonOf(const Operator* op) V8_WARN_UNUSED_RESULT;
632

633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
class NewArgumentsElementsParameters {
 public:
  NewArgumentsElementsParameters(CreateArgumentsType type,
                                 int formal_parameter_count)
      : type_(type), formal_parameter_count_(formal_parameter_count) {}

  CreateArgumentsType arguments_type() const { return type_; }
  int formal_parameter_count() const { return formal_parameter_count_; }

 private:
  CreateArgumentsType type_;
  int formal_parameter_count_;
};

bool operator==(const NewArgumentsElementsParameters&,
                const NewArgumentsElementsParameters&);

inline size_t hash_value(const NewArgumentsElementsParameters&);

std::ostream& operator<<(std::ostream&, const NewArgumentsElementsParameters&);

const NewArgumentsElementsParameters& NewArgumentsElementsParametersOf(
    const Operator*) V8_WARN_UNUSED_RESULT;
656

657 658 659 660 661 662 663 664 665 666
struct FastApiCallFunction {
  Address address;
  const CFunctionInfo* signature;

  bool operator==(const FastApiCallFunction& rhs) const {
    return address == rhs.address && signature == rhs.signature;
  }
};
typedef ZoneVector<FastApiCallFunction> FastApiCallFunctionVector;

667 668
class FastApiCallParameters {
 public:
669
  explicit FastApiCallParameters(const FastApiCallFunctionVector& c_functions,
670 671
                                 FeedbackSource const& feedback,
                                 CallDescriptor* descriptor)
672 673 674
      : c_functions_(c_functions),
        feedback_(feedback),
        descriptor_(descriptor) {}
675

676
  const FastApiCallFunctionVector& c_functions() const { return c_functions_; }
677
  FeedbackSource const& feedback() const { return feedback_; }
678
  CallDescriptor* descriptor() const { return descriptor_; }
679 680

 private:
681 682 683
  // A single FastApiCall node can represent multiple overloaded functions.
  const FastApiCallFunctionVector c_functions_;

684
  const FeedbackSource feedback_;
685
  CallDescriptor* descriptor_;
686 687 688 689 690 691 692 693 694 695 696 697
};

FastApiCallParameters const& FastApiCallParametersOf(const Operator* op)
    V8_WARN_UNUSED_RESULT;

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
                                           FastApiCallParameters const&);

size_t hash_value(FastApiCallParameters const&);

bool operator==(FastApiCallParameters const&, FastApiCallParameters const&);

698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
// Interface for building simplified operators, which represent the
// medium-level operations of V8, including adding numbers, allocating objects,
// indexing into objects and arrays, etc.
// All operators are typed but many are representation independent.

// Number values from JS can be in one of these representations:
//   - Tagged: word-sized integer that is either
//     - a signed small integer (31 or 32 bits plus a tag)
//     - a tagged pointer to a HeapNumber object that has a float64 field
//   - Int32: an untagged signed 32-bit integer
//   - Uint32: an untagged unsigned 32-bit integer
//   - Float64: an untagged float64

// Additional representations for intermediate code or non-JS code:
//   - Int64: an untagged signed 64-bit integer
//   - Uint64: an untagged unsigned 64-bit integer
//   - Float32: an untagged float32

// Boolean values can be:
//   - Bool: a tagged pointer to either the canonical JS #false or
//           the canonical JS #true object
//   - Bit: an untagged integer 0 or 1, but word-sized
720 721
class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
    : public NON_EXPORTED_BASE(ZoneObject) {
722
 public:
723
  explicit SimplifiedOperatorBuilder(Zone* zone);
724 725 726
  SimplifiedOperatorBuilder(const SimplifiedOperatorBuilder&) = delete;
  SimplifiedOperatorBuilder& operator=(const SimplifiedOperatorBuilder&) =
      delete;
727

728 729 730
  const Operator* BooleanNot();

  const Operator* NumberEqual();
731
  const Operator* NumberSameValue();
732 733 734 735 736 737 738
  const Operator* NumberLessThan();
  const Operator* NumberLessThanOrEqual();
  const Operator* NumberAdd();
  const Operator* NumberSubtract();
  const Operator* NumberMultiply();
  const Operator* NumberDivide();
  const Operator* NumberModulus();
739 740 741
  const Operator* NumberBitwiseOr();
  const Operator* NumberBitwiseXor();
  const Operator* NumberBitwiseAnd();
742 743 744
  const Operator* NumberShiftLeft();
  const Operator* NumberShiftRight();
  const Operator* NumberShiftRightLogical();
745
  const Operator* NumberImul();
746
  const Operator* NumberAbs();
747
  const Operator* NumberClz32();
748
  const Operator* NumberCeil();
749
  const Operator* NumberFloor();
750
  const Operator* NumberFround();
751 752 753 754
  const Operator* NumberAcos();
  const Operator* NumberAcosh();
  const Operator* NumberAsin();
  const Operator* NumberAsinh();
755 756
  const Operator* NumberAtan();
  const Operator* NumberAtan2();
757
  const Operator* NumberAtanh();
758 759
  const Operator* NumberCbrt();
  const Operator* NumberCos();
760
  const Operator* NumberCosh();
761
  const Operator* NumberExp();
762
  const Operator* NumberExpm1();
763
  const Operator* NumberLog();
764
  const Operator* NumberLog1p();
765
  const Operator* NumberLog10();
766
  const Operator* NumberLog2();
767 768
  const Operator* NumberMax();
  const Operator* NumberMin();
769
  const Operator* NumberPow();
770
  const Operator* NumberRound();
771
  const Operator* NumberSign();
772
  const Operator* NumberSin();
773
  const Operator* NumberSinh();
774
  const Operator* NumberSqrt();
775
  const Operator* NumberTan();
776
  const Operator* NumberTanh();
777
  const Operator* NumberTrunc();
778
  const Operator* NumberToBoolean();
779
  const Operator* NumberToInt32();
780
  const Operator* NumberToString();
781
  const Operator* NumberToUint32();
782
  const Operator* NumberToUint8Clamped();
783

784 785
  const Operator* NumberSilenceNaN();

786
  const Operator* BigIntAdd();
787
  const Operator* BigIntSubtract();
788 789
  const Operator* BigIntNegate();

790 791 792
  const Operator* SpeculativeSafeIntegerAdd(NumberOperationHint hint);
  const Operator* SpeculativeSafeIntegerSubtract(NumberOperationHint hint);

793 794 795 796 797 798 799 800 801 802 803
  const Operator* SpeculativeNumberAdd(NumberOperationHint hint);
  const Operator* SpeculativeNumberSubtract(NumberOperationHint hint);
  const Operator* SpeculativeNumberMultiply(NumberOperationHint hint);
  const Operator* SpeculativeNumberDivide(NumberOperationHint hint);
  const Operator* SpeculativeNumberModulus(NumberOperationHint hint);
  const Operator* SpeculativeNumberShiftLeft(NumberOperationHint hint);
  const Operator* SpeculativeNumberShiftRight(NumberOperationHint hint);
  const Operator* SpeculativeNumberShiftRightLogical(NumberOperationHint hint);
  const Operator* SpeculativeNumberBitwiseAnd(NumberOperationHint hint);
  const Operator* SpeculativeNumberBitwiseOr(NumberOperationHint hint);
  const Operator* SpeculativeNumberBitwiseXor(NumberOperationHint hint);
804
  const Operator* SpeculativeNumberPow(NumberOperationHint hint);
805 806 807 808

  const Operator* SpeculativeNumberLessThan(NumberOperationHint hint);
  const Operator* SpeculativeNumberLessThanOrEqual(NumberOperationHint hint);
  const Operator* SpeculativeNumberEqual(NumberOperationHint hint);
809

810
  const Operator* SpeculativeBigIntAdd(BigIntOperationHint hint);
811
  const Operator* SpeculativeBigIntSubtract(BigIntOperationHint hint);
812
  const Operator* SpeculativeBigIntNegate(BigIntOperationHint hint);
813 814
  const Operator* SpeculativeBigIntAsIntN(int bits,
                                          const FeedbackSource& feedback);
815 816
  const Operator* SpeculativeBigIntAsUintN(int bits,
                                           const FeedbackSource& feedback);
817

818
  const Operator* ReferenceEqual();
819
  const Operator* SameValue();
820
  const Operator* SameValueNumbersOnly();
821

822 823
  const Operator* TypeOf();

824
  const Operator* ToBoolean();
825

826
  const Operator* StringConcat();
827 828 829
  const Operator* StringEqual();
  const Operator* StringLessThan();
  const Operator* StringLessThanOrEqual();
830
  const Operator* StringCharCodeAt();
831
  const Operator* StringCodePointAt();
832
  const Operator* StringFromSingleCharCode();
833 834
  const Operator* StringFromSingleCodePoint();
  const Operator* StringFromCodePointAt();
835
  const Operator* StringIndexOf();
836
  const Operator* StringLength();
837 838
  const Operator* StringToLowerCaseIntl();
  const Operator* StringToUpperCaseIntl();
839
  const Operator* StringSubstring();
840

841
  const Operator* FindOrderedHashMapEntry();
842
  const Operator* FindOrderedHashMapEntryForInt32Key();
843

844
  const Operator* SpeculativeToNumber(NumberOperationHint hint,
845
                                      const FeedbackSource& feedback);
846

847
  const Operator* StringToNumber();
848 849 850 851
  const Operator* PlainPrimitiveToNumber();
  const Operator* PlainPrimitiveToWord32();
  const Operator* PlainPrimitiveToFloat64();

852
  const Operator* ChangeTaggedSignedToInt32();
853
  const Operator* ChangeTaggedSignedToInt64();
854
  const Operator* ChangeTaggedToInt32();
855
  const Operator* ChangeTaggedToInt64();
856 857
  const Operator* ChangeTaggedToUint32();
  const Operator* ChangeTaggedToFloat64();
858
  const Operator* ChangeTaggedToTaggedSigned();
859
  const Operator* ChangeInt31ToTaggedSigned();
860
  const Operator* ChangeInt32ToTagged();
861
  const Operator* ChangeInt64ToTagged();
862
  const Operator* ChangeUint32ToTagged();
863
  const Operator* ChangeUint64ToTagged();
864
  const Operator* ChangeFloat64ToTagged(CheckForMinusZeroMode);
865
  const Operator* ChangeFloat64ToTaggedPointer();
866 867
  const Operator* ChangeTaggedToBit();
  const Operator* ChangeBitToTagged();
868 869
  const Operator* TruncateBigIntToWord64();
  const Operator* ChangeInt64ToBigInt();
870
  const Operator* ChangeUint64ToBigInt();
871
  const Operator* TruncateTaggedToWord32();
872
  const Operator* TruncateTaggedToFloat64();
873
  const Operator* TruncateTaggedToBit();
874
  const Operator* TruncateTaggedPointerToBit();
875

876
  const Operator* CompareMaps(ZoneHandleSet<Map>);
877
  const Operator* MapGuard(ZoneHandleSet<Map> maps);
878

879
  const Operator* CheckBounds(const FeedbackSource& feedback,
880
                              CheckBoundsFlags flags = {});
881
  const Operator* CheckedUint32Bounds(const FeedbackSource& feedback,
882
                                      CheckBoundsFlags flags);
883
  const Operator* CheckedUint64Bounds(const FeedbackSource& feedback,
884
                                      CheckBoundsFlags flags);
885

886
  const Operator* CheckClosure(const Handle<FeedbackCell>& feedback_cell);
887 888
  const Operator* CheckEqualsInternalizedString();
  const Operator* CheckEqualsSymbol();
889
  const Operator* CheckFloat64Hole(CheckFloat64HoleMode, FeedbackSource const&);
890
  const Operator* CheckHeapObject();
891
  const Operator* CheckIf(DeoptimizeReason deoptimize_reason,
892
                          const FeedbackSource& feedback = FeedbackSource());
893
  const Operator* CheckInternalizedString();
894
  const Operator* CheckMaps(CheckMapsFlags, ZoneHandleSet<Map>,
895
                            const FeedbackSource& = FeedbackSource());
896
  const Operator* CheckNotTaggedHole();
897
  const Operator* CheckNumber(const FeedbackSource& feedback);
898
  const Operator* CheckReceiver();
899
  const Operator* CheckReceiverOrNullOrUndefined();
900 901
  const Operator* CheckSmi(const FeedbackSource& feedback);
  const Operator* CheckString(const FeedbackSource& feedback);
902
  const Operator* CheckSymbol();
903

904
  const Operator* CheckedFloat64ToInt32(CheckForMinusZeroMode,
905
                                        const FeedbackSource& feedback);
906
  const Operator* CheckedFloat64ToInt64(CheckForMinusZeroMode,
907
                                        const FeedbackSource& feedback);
908
  const Operator* CheckedInt32Add();
909 910
  const Operator* CheckedInt32Div();
  const Operator* CheckedInt32Mod();
911
  const Operator* CheckedInt32Mul(CheckForMinusZeroMode);
912
  const Operator* CheckedInt32Sub();
913 914 915 916
  const Operator* CheckedInt32ToTaggedSigned(const FeedbackSource& feedback);
  const Operator* CheckedInt64ToInt32(const FeedbackSource& feedback);
  const Operator* CheckedInt64ToTaggedSigned(const FeedbackSource& feedback);
  const Operator* CheckedTaggedSignedToInt32(const FeedbackSource& feedback);
917
  const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode,
918
                                         const FeedbackSource& feedback);
919
  const Operator* CheckedTaggedToInt32(CheckForMinusZeroMode,
920
                                       const FeedbackSource& feedback);
921
  const Operator* CheckedTaggedToArrayIndex(const FeedbackSource& feedback);
922
  const Operator* CheckedTaggedToInt64(CheckForMinusZeroMode,
923 924 925 926
                                       const FeedbackSource& feedback);
  const Operator* CheckedTaggedToTaggedPointer(const FeedbackSource& feedback);
  const Operator* CheckedTaggedToTaggedSigned(const FeedbackSource& feedback);
  const Operator* CheckBigInt(const FeedbackSource& feedback);
927
  const Operator* CheckedTruncateTaggedToWord32(CheckTaggedInputMode,
928
                                                const FeedbackSource& feedback);
929 930
  const Operator* CheckedUint32Div();
  const Operator* CheckedUint32Mod();
931 932 933 934
  const Operator* CheckedUint32ToInt32(const FeedbackSource& feedback);
  const Operator* CheckedUint32ToTaggedSigned(const FeedbackSource& feedback);
  const Operator* CheckedUint64ToInt32(const FeedbackSource& feedback);
  const Operator* CheckedUint64ToTaggedSigned(const FeedbackSource& feedback);
935

936 937
  const Operator* ConvertReceiver(ConvertReceiverMode);

938
  const Operator* ConvertTaggedHoleToUndefined();
939

940
  const Operator* ObjectIsArrayBufferView();
941
  const Operator* ObjectIsBigInt();
942
  const Operator* ObjectIsCallable();
943
  const Operator* ObjectIsConstructor();
944
  const Operator* ObjectIsDetectableCallable();
945
  const Operator* ObjectIsMinusZero();
946
  const Operator* NumberIsMinusZero();
947
  const Operator* ObjectIsNaN();
948
  const Operator* NumberIsNaN();
949
  const Operator* ObjectIsNonCallable();
950
  const Operator* ObjectIsNumber();
951
  const Operator* ObjectIsReceiver();
952
  const Operator* ObjectIsSmi();
953
  const Operator* ObjectIsString();
954
  const Operator* ObjectIsSymbol();
955
  const Operator* ObjectIsUndetectable();
956

957
  const Operator* NumberIsFloat64Hole();
958 959
  const Operator* NumberIsFinite();
  const Operator* ObjectIsFiniteNumber();
960
  const Operator* NumberIsInteger();
961 962
  const Operator* ObjectIsSafeInteger();
  const Operator* NumberIsSafeInteger();
963
  const Operator* ObjectIsInteger();
964

965
  const Operator* ArgumentsLength();
966
  const Operator* RestLength(int formal_parameter_count);
967

968 969
  const Operator* NewDoubleElements(AllocationType);
  const Operator* NewSmiOrObjectElements(AllocationType);
970

971
  // new-arguments-elements arguments-length
972 973
  const Operator* NewArgumentsElements(CreateArgumentsType type,
                                       int formal_parameter_count);
974

975 976 977
  // new-cons-string length, first, second
  const Operator* NewConsString();

978 979 980
  // ensure-writable-fast-elements object, elements
  const Operator* EnsureWritableFastElements();

981
  // maybe-grow-fast-elements object, elements, index, length
982
  const Operator* MaybeGrowFastElements(GrowFastElementsMode mode,
983
                                        const FeedbackSource& feedback);
984

985 986 987
  // transition-elements-kind object, from-map, to-map
  const Operator* TransitionElementsKind(ElementsTransition transition);

988 989 990
  const Operator* Allocate(Type type,
                           AllocationType allocation = AllocationType::kYoung);
  const Operator* AllocateRaw(
991 992
      Type type, AllocationType allocation = AllocationType::kYoung,
      AllowLargeObjects allow_large_objects = AllowLargeObjects::kFalse);
993

994 995 996
  const Operator* LoadMessage();
  const Operator* StoreMessage();

997
  const Operator* LoadFieldByIndex();
998
  const Operator* LoadField(FieldAccess const&);
999 1000
  const Operator* StoreField(FieldAccess const&,
                             bool maybe_initializing_or_transitioning = true);
1001

1002
  // load-element [base + index]
1003 1004
  const Operator* LoadElement(ElementAccess const&);

1005 1006 1007
  // load-stack-argument [base + index]
  const Operator* LoadStackArgument();

1008
  // store-element [base + index], value
1009
  const Operator* StoreElement(ElementAccess const&);
1010

1011 1012 1013
  // store-element [base + index], value, only with fast arrays.
  const Operator* TransitionAndStoreElement(Handle<Map> double_map,
                                            Handle<Map> fast_map);
1014 1015
  // store-element [base + index], smi value, only with fast arrays.
  const Operator* StoreSignedSmallElement();
1016

1017 1018 1019 1020 1021
  // store-element [base + index], double value, only with fast arrays.
  const Operator* TransitionAndStoreNumberElement(Handle<Map> double_map);

  // store-element [base + index], object value, only with fast arrays.
  const Operator* TransitionAndStoreNonNumberElement(Handle<Map> fast_map,
1022
                                                     Type value_type);
1023

1024
  // load-from-object [base + offset]
1025 1026 1027 1028 1029 1030
  // This operator comes in two flavors: LoadImmutableFromObject guarantees that
  // the underlying object field will be initialized at most once for the
  // duration of the program. This enables more optimizations in
  // CsaLoadElimination.
  // Note: LoadImmutableFromObject is unrelated to LoadImmutable and is lowered
  // into a regular Load.
1031
  const Operator* LoadFromObject(ObjectAccess const&);
1032
  const Operator* LoadImmutableFromObject(ObjectAccess const&);
1033 1034

  // store-to-object [base + offset], value
1035 1036 1037 1038
  // This operator comes in two flavors: InitializeImmutableInObject guarantees
  // that the underlying object field has not and will not be initialized again
  // for the duration of the program. This enables more optimizations in
  // CsaLoadElimination.
1039
  const Operator* StoreToObject(ObjectAccess const&);
1040
  const Operator* InitializeImmutableInObject(ObjectAccess const&);
1041

1042 1043 1044
  // load-typed-element buffer, [base + external + index]
  const Operator* LoadTypedElement(ExternalArrayType const&);

1045
  // load-data-view-element object, [base + index]
1046 1047
  const Operator* LoadDataViewElement(ExternalArrayType const&);

1048 1049 1050
  // store-typed-element buffer, [base + external + index], value
  const Operator* StoreTypedElement(ExternalArrayType const&);

1051
  // store-data-view-element object, [base + index], value
1052 1053
  const Operator* StoreDataViewElement(ExternalArrayType const&);

1054
  // Abort (for terminating execution on internal error).
1055
  const Operator* RuntimeAbort(AbortReason reason);
1056

1057 1058 1059
  // Abort if the value input does not inhabit the given type
  const Operator* AssertType(Type type);

1060 1061 1062 1063
  // Abort if the value does not match the node's computed type after
  // SimplifiedLowering.
  const Operator* VerifyType();

1064 1065 1066
#if V8_ENABLE_WEBASSEMBLY
  const Operator* AssertNotNull();
  const Operator* IsNull();
1067
  const Operator* IsNotNull();
1068 1069 1070 1071 1072 1073
  const Operator* Null();
  const Operator* RttCanon(int index);
  const Operator* WasmTypeCheck(WasmTypeCheckConfig config);
  const Operator* WasmTypeCast(WasmTypeCheckConfig config);
#endif

1074
  const Operator* DateNow();
1075 1076 1077 1078 1079
  // Unsigned32Divide is a special operator to express the division of two
  // Unsigned32 inputs and truncating the result to Unsigned32. It's semantics
  // is equivalent to NumberFloor(NumberDivide(x:Unsigned32, y:Unsigned32)) but
  // is required to allow consistent typing of the graph.
  const Operator* Unsigned32Divide();
1080

1081
  // Represents the inputs necessary to construct a fast and a slow API call.
1082 1083 1084
  const Operator* FastApiCall(
      const FastApiCallFunctionVector& c_candidate_functions,
      FeedbackSource const& feedback, CallDescriptor* descriptor);
1085

1086
 private:
1087 1088
  Zone* zone() const { return zone_; }

1089
  const SimplifiedOperatorGlobalCache& cache_;
1090
  Zone* const zone_;
1091
};
1092

1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
// Node wrappers.

// TODO(jgruber): Consider merging with JSNodeWrapperBase.
class SimplifiedNodeWrapperBase : public NodeWrapper {
 public:
  explicit constexpr SimplifiedNodeWrapperBase(Node* node)
      : NodeWrapper(node) {}

  // Valid iff this node has a context input.
  TNode<Object> context() const {
    // Could be a Context or NoContextConstant.
    return TNode<Object>::UncheckedCast(
        NodeProperties::GetContextInput(node()));
  }

  // Valid iff this node has exactly one effect input.
  Effect effect() const {
    DCHECK_EQ(node()->op()->EffectInputCount(), 1);
    return Effect{NodeProperties::GetEffectInput(node())};
  }

  // Valid iff this node has exactly one control input.
  Control control() const {
    DCHECK_EQ(node()->op()->ControlInputCount(), 1);
    return Control{NodeProperties::GetControlInput(node())};
  }

  // Valid iff this node has a frame state input.
  FrameState frame_state() const {
    return FrameState{NodeProperties::GetFrameStateInput(node())};
  }
};

1126 1127 1128 1129 1130 1131 1132
#define DEFINE_INPUT_ACCESSORS(Name, name, TheIndex, Type) \
  static constexpr int Name##Index() { return TheIndex; }  \
  TNode<Type> name() const {                               \
    return TNode<Type>::UncheckedCast(                     \
        NodeProperties::GetValueInput(node(), TheIndex));  \
  }

1133
class FastApiCallNode final : public SimplifiedNodeWrapperBase {
1134
 public:
1135 1136
  explicit constexpr FastApiCallNode(Node* node)
      : SimplifiedNodeWrapperBase(node) {
1137
    DCHECK_EQ(IrOpcode::kFastApiCall, node->opcode());
1138 1139 1140 1141 1142 1143
  }

  const FastApiCallParameters& Parameters() const {
    return FastApiCallParametersOf(node()->op());
  }

1144
#define INPUTS(V) V(Receiver, receiver, 0, Object)
1145 1146 1147 1148 1149 1150 1151
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS

  // Besides actual arguments, FastApiCall nodes also take:
  static constexpr int kSlowTargetInputCount = 1;
  static constexpr int kFastReceiverInputCount = 1;
  static constexpr int kSlowReceiverInputCount = 1;
1152
  static constexpr int kExtraInputCount = kFastReceiverInputCount;
1153 1154 1155 1156 1157 1158

  static constexpr int kArityInputCount = 1;
  static constexpr int kNewTargetInputCount = 1;
  static constexpr int kHolderInputCount = 1;
  static constexpr int kContextAndFrameStateInputCount = 2;
  static constexpr int kEffectAndControlInputCount = 2;
1159
  int FastCallExtraInputCount() const;
1160 1161 1162 1163 1164
  static constexpr int kSlowCallExtraInputCount =
      kSlowTargetInputCount + kArityInputCount + kNewTargetInputCount +
      kSlowReceiverInputCount + kHolderInputCount +
      kContextAndFrameStateInputCount + kEffectAndControlInputCount;

1165 1166
  static constexpr int kSlowCallDataArgumentIndex = 3;

1167 1168
  // This is the arity fed into FastApiCallArguments.
  static constexpr int ArityForArgc(int c_arg_count, int js_arg_count) {
1169
    return c_arg_count + js_arg_count + kEffectAndControlInputCount;
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
  }

  int FastCallArgumentCount() const;
  int SlowCallArgumentCount() const;

  constexpr int FirstFastCallArgumentIndex() const {
    return ReceiverIndex() + 1;
  }
  constexpr int FastCallArgumentIndex(int i) const {
    return FirstFastCallArgumentIndex() + i;
  }
  TNode<Object> FastCallArgument(int i) const {
    DCHECK_LT(i, FastCallArgumentCount());
    return TNode<Object>::UncheckedCast(
        NodeProperties::GetValueInput(node(), FastCallArgumentIndex(i)));
  }

1187
  int FirstSlowCallArgumentIndex() const { return FastCallArgumentCount(); }
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
  int SlowCallArgumentIndex(int i) const {
    return FirstSlowCallArgumentIndex() + i;
  }
  TNode<Object> SlowCallArgument(int i) const {
    DCHECK_LT(i, SlowCallArgumentCount());
    return TNode<Object>::UncheckedCast(
        NodeProperties::GetValueInput(node(), SlowCallArgumentIndex(i)));
  }
};

#undef DEFINE_INPUT_ACCESSORS

1200 1201 1202
}  // namespace compiler
}  // namespace internal
}  // namespace v8
1203 1204

#endif  // V8_COMPILER_SIMPLIFIED_OPERATOR_H_