base.tq 63.5 KB
Newer Older
1
// Copyright 2018 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be:
// Context found in the LICENSE file.
4

5
#include 'src/builtins/builtins-regexp-gen.h'
6 7
#include 'src/builtins/builtins-utils-gen.h'
#include 'src/builtins/builtins.h'
8
#include 'src/codegen/code-factory.h'
9 10 11
#include 'src/heap/factory-inl.h'
#include 'src/objects/arguments.h'
#include 'src/objects/bigint.h'
12
#include 'src/objects/elements-kind.h'
13
#include 'src/objects/free-space.h'
14
#include 'src/objects/js-function.h'
15 16
#include 'src/objects/js-generator.h'
#include 'src/objects/js-promise.h'
Irina Yatsenko's avatar
Irina Yatsenko committed
17
#include 'src/objects/js-regexp-string-iterator.h'
18
#include 'src/objects/js-weak-refs.h'
19
#include 'src/objects/objects.h'
20
#include 'src/objects/source-text-module.h'
21
#include 'src/objects/stack-frame-info.h'
22
#include 'src/objects/synthetic-module.h'
23
#include 'src/objects/template-objects.h'
24
#include 'src/torque/runtime-support.h'
25

26 27
type void;
type never;
28

29 30 31 32
type Tagged generates 'TNode<MaybeObject>' constexpr 'MaybeObject';
type StrongTagged extends Tagged
    generates 'TNode<Object>' constexpr 'ObjectPtr';
type Smi extends StrongTagged generates 'TNode<Smi>' constexpr 'Smi';
33 34
type TaggedIndex extends StrongTagged
    generates 'TNode<TaggedIndex>' constexpr 'TaggedIndex';
35 36 37 38 39 40 41 42
// A possibly cleared weak pointer with a bit pattern that distinguishes it from
// strong HeapObject pointers and Smi values.
type WeakHeapObject extends Tagged;
type Weak<T : type extends HeapObject> extends WeakHeapObject;

type Object = Smi|HeapObject;
type MaybeObject = Smi|HeapObject|WeakHeapObject;

43
// A Smi that is greater than or equal to 0. See TaggedIsPositiveSmi.
44
type PositiveSmi extends Smi;
45

46 47 48
// The Smi value zero, which is often used as null for HeapObject types.
type Zero extends PositiveSmi;

49 50 51
// A value with the size of Tagged which may contain arbitrary data.
type Uninitialized extends Tagged;

52 53 54
extern macro MakeWeak(HeapObject): WeakHeapObject;
extern macro GetHeapObjectAssumeWeak(WeakHeapObject):
    HeapObject labels ClearedWeakPointer;
55
extern macro GetHeapObjectIfStrong(MaybeObject): HeapObject labels IfNotStrong;
56
extern macro IsWeakOrCleared(MaybeObject): bool;
57
extern macro IsWeakReferenceToObject(MaybeObject, Object): bool;
58
extern macro IsStrong(MaybeObject): bool;
59

60 61 62 63 64 65 66
macro StrongToWeak<T: type>(x: T): Weak<T> {
  return %RawDownCast<Weak<T>>(MakeWeak(x));
}
macro WeakToStrong<T: type>(x: Weak<T>): T labels ClearedWeakPointer {
  const x = GetHeapObjectAssumeWeak(x) otherwise ClearedWeakPointer;
  return %RawDownCast<T>(x);
}
67

68 69
// Defined to coincide with https://tc39.es/ecma262/#sec-ispropertykey
// Doesn't include PrivateSymbol.
70
type PropertyKey = String|PublicSymbol;
71 72 73 74 75 76 77

// TODO(tebbi): PrivateSymbol is only exposed to JavaScript through the debugger
// API. We should reconsider this and try not to expose it at all. Then JSAny
// would not need to contain it.

// A JavaScript primitive value as defined in
// https://tc39.es/ecma262/#sec-primitive-value.
78
type JSPrimitive = Numeric|String|Symbol|Boolean|Null|Undefined;
79 80 81

// A user-exposed JavaScript value, as opposed to V8-internal values like
// TheHole or FixedArray.
82
type JSAny = JSReceiver|JSPrimitive;
83

84 85
type JSAnyNotNumeric = String|Symbol|Boolean|Null|Undefined|JSReceiver;
type JSAnyNotNumber = BigInt|JSAnyNotNumeric;
86 87

// This is the intersection of JSAny and HeapObject.
88
type JSAnyNotSmi = JSAnyNotNumber|HeapNumber;
89

90 91
type int32 generates 'TNode<Int32T>' constexpr 'int32_t';
type uint32 generates 'TNode<Uint32T>' constexpr 'uint32_t';
92 93 94
type int31 extends int32
    generates 'TNode<Int32T>' constexpr 'int31_t';
type uint31 extends uint32
95
    generates 'TNode<Uint32T>' constexpr 'uint32_t';
96
type int16 extends int31
97
    generates 'TNode<Int16T>' constexpr 'int16_t';
98
type uint16 extends uint31
99 100
    generates 'TNode<Uint16T>' constexpr 'uint16_t';
type int8 extends int16 generates 'TNode<Int8T>' constexpr 'int8_t';
101
type uint8 extends uint16
102
    generates 'TNode<Uint8T>' constexpr 'uint8_t';
103 104
type char8 extends int8 constexpr 'char';
type char16 extends uint16 constexpr 'char16_t';
105
type int64 generates 'TNode<Int64T>' constexpr 'int64_t';
106
type intptr generates 'TNode<IntPtrT>' constexpr 'intptr_t';
107
type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t';
108
type float32 generates 'TNode<Float32T>' constexpr 'float';
109 110
type float64 generates 'TNode<Float64T>' constexpr 'double';
type bool generates 'TNode<BoolT>' constexpr 'bool';
111
type bint generates 'TNode<BInt>' constexpr 'BInt';
112
type string constexpr 'const char*';
113

114 115 116
// A Smi value containing a bitfield struct as its integer data.
type SmiTagged<T : type extends uint31> extends Smi;

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
// WARNING: The memory representation (i.e., in class fields and arrays) of
// float64_or_hole is just a float64 that may be the hole-representing
// signalling NaN bit-pattern. So it's memory size is that of float64 and
// loading and storing float64_or_hole emits special code.
struct float64_or_hole {
  macro Value(): float64 labels IfHole {
    if (this.is_hole) {
      goto IfHole;
    }
    return this.value;
  }
  macro ValueUnsafeAssumeNotHole(): float64 {
    assert(!this.is_hole);
    return this.value;
  }

  is_hole: bool;
  value: float64;
}
const kDoubleHole: float64_or_hole = float64_or_hole{is_hole: true, value: 0};

138 139 140
// The HashTable inheritance hierarchy doesn't actually look like this in C++
// because it uses some class templates that we can't yet (and may never)
// express in Torque, but this is the expected organization of instance types.
141
@doNotGenerateCast
142 143 144 145 146 147 148 149 150 151 152
extern class HashTable extends FixedArray generates 'TNode<FixedArray>';
extern class OrderedHashMap extends HashTable;
extern class OrderedHashSet extends HashTable;
extern class OrderedNameDictionary extends HashTable;
extern class NameDictionary extends HashTable;
extern class GlobalDictionary extends HashTable;
extern class SimpleNumberDictionary extends HashTable;
extern class EphemeronHashTable extends HashTable;
type ObjectHashTable extends HashTable
    generates 'TNode<ObjectHashTable>';
extern class NumberDictionary extends HashTable;
153

154
type RawPtr generates 'TNode<RawPtrT>' constexpr 'void*';
155 156
type ExternalPointer
    generates 'TNode<ExternalPointerT>' constexpr 'ExternalPointer_t';
157
extern class Code extends HeapObject;
158
type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>';
159

160 161
type Number = Smi|HeapNumber;
type Numeric = Number|BigInt;
162

163 164 165 166
extern class ObjectBoilerplateDescription extends FixedArray;
extern class ClosureFeedbackCellArray extends FixedArray;
extern class ScriptContextTable extends FixedArray;

167 168
type LayoutDescriptor extends ByteArray
    generates 'TNode<LayoutDescriptor>';
169
extern class TransitionArray extends WeakFixedArray;
170

171 172 173
extern operator '.length_intptr' macro LoadAndUntagWeakFixedArrayLength(
    WeakFixedArray): intptr;

174
type InstanceType extends uint16 constexpr 'InstanceType';
175

176
type NoSharedNameSentinel extends Smi;
177

178
// Specialized types. The following three type definitions don't correspond to
179 180
// actual C++ classes, but have Is... methods that check additional constraints.

181 182 183
// A Foreign object whose raw pointer is not allowed to be null.
type NonNullForeign extends Foreign;

184
// A function built with InstantiateFunction for the public API.
185
type CallableApiObject extends JSObject;
186 187 188 189

// A JSProxy with the callable bit set.
type CallableJSProxy extends JSProxy;

190
type Callable = JSFunction|JSBoundFunction|CallableJSProxy|CallableApiObject;
191

192 193
type WriteBarrierMode
    generates 'TNode<Int32T>' constexpr 'WriteBarrierMode';
194

195
extern enum UnicodeEncoding { UTF16, UTF32 }
196

197
// Promise constants
198 199 200 201 202
extern enum PromiseState extends int31 constexpr 'Promise::PromiseState' {
  kPending,
  kFulfilled,
  kRejected
}
203

204 205
type FrameArray extends FixedArray;

Tobias Tebbi's avatar
Tobias Tebbi committed
206 207
const kTaggedSize: constexpr int31 generates 'kTaggedSize';
const kDoubleSize: constexpr int31 generates 'kDoubleSize';
208 209
const kVariableSizeSentinel:
    constexpr int31 generates 'kVariableSizeSentinel';
210

Tobias Tebbi's avatar
Tobias Tebbi committed
211
const kSmiTagSize: constexpr int31 generates 'kSmiTagSize';
212
const kHeapObjectTag: constexpr int31 generates 'kHeapObjectTag';
Tobias Tebbi's avatar
Tobias Tebbi committed
213
const V8_INFINITY: constexpr float64 generates 'V8_INFINITY';
214
const MINUS_V8_INFINITY: constexpr float64 generates '-V8_INFINITY';
215

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
extern enum ElementsKind extends int32 {
  NO_ELEMENTS,

  PACKED_SMI_ELEMENTS,
  HOLEY_SMI_ELEMENTS,
  PACKED_ELEMENTS,
  HOLEY_ELEMENTS,
  PACKED_DOUBLE_ELEMENTS,
  HOLEY_DOUBLE_ELEMENTS,
  LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND,
  DICTIONARY_ELEMENTS,

  UINT8_ELEMENTS,
  INT8_ELEMENTS,
  UINT16_ELEMENTS,
  INT16_ELEMENTS,
  UINT32_ELEMENTS,
  INT32_ELEMENTS,
  FLOAT32_ELEMENTS,
  FLOAT64_ELEMENTS,
  UINT8_CLAMPED_ELEMENTS,
  BIGUINT64_ELEMENTS,
  BIGINT64_ELEMENTS,
  ...
}

242 243
extern enum AllocationFlag extends int32
constexpr 'CodeStubAssembler::AllocationFlag' {
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
  kNone,
  kDoubleAlignment,
  kPretenured,
  kAllowLargeObjectAllocation
}

extern enum SlackTrackingMode
constexpr 'CodeStubAssembler::SlackTrackingMode' {
  kWithSlackTracking,
  kNoSlackTracking
}

extern enum ExtractFixedArrayFlag
constexpr 'CodeStubAssembler::ExtractFixedArrayFlag' {
  kFixedDoubleArrays,
  kAllFixedArrays,
  kFixedArrays,
  ...
}

const kBigIntMaxLength: constexpr intptr generates 'BigInt::kMaxLength';

extern enum MessageTemplate {
267
  kAllPromisesRejected,
268 269
  kInvalidArrayBufferLength,
  kInvalidArrayLength,
270
  kInvalidIndex,
271
  kNotConstructor,
272
  kNotGeneric,
273 274
  kCalledNonCallable,
  kCalledOnNullOrUndefined,
275
  kCannotConvertToPrimitive,
276 277 278 279 280 281 282 283 284 285
  kProtoObjectOrNull,
  kInvalidOffset,
  kInvalidTypedArrayLength,
  kIteratorSymbolNonCallable,
  kIteratorValueNotAnObject,
  kNotIterable,
  kReduceNoInitial,
  kFirstArgumentNotRegExp,
  kBigIntMixedTypes,
  kTypedArrayTooShort,
286
  kTypedArrayTooLargeToSort,
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
  kInvalidCountValue,
  kConstructorNotFunction,
  kSymbolToString,
  kPropertyNotFunction,
  kBigIntTooBig,
  kNotTypedArray,
  kDetachedOperation,
  kBadSortComparisonFunction,
  kIncompatibleMethodReceiver,
  kInvalidDataViewAccessorOffset,
  kTypedArraySetOffsetOutOfBounds,
  kInvalidArgument,
  kInvalidRegExpExecResult,
  kRegExpNonRegExp,
  kRegExpNonObject,
  kPromiseNonCallable,
  kNotAPromise,
  kResolverNotAFunction,
305
  kTooManyElementsInPromiseCombinator,
306 307 308 309 310 311 312 313 314 315 316 317 318 319
  kToRadixFormatRange,
  kCalledOnNonObject,
  kRegExpGlobalInvokedOnNonGlobal,
  kProxyNonObject,
  kProxyRevoked,
  kProxyTrapReturnedFalsishFor,
  kProxyPrivate,
  kProxyIsExtensibleInconsistent,
  kProxyPreventExtensionsExtensible,
  kProxyTrapReturnedFalsish,
  kProxyGetPrototypeOfInvalid,
  kProxyGetPrototypeOfNonExtensible,
  kProxySetPrototypeOfNonExtensible,
  kProxyDeletePropertyNonExtensible,
320
  kUndefinedOrNullToObject,
321
  kWeakRefsCleanupMustBeCallable,
322 323 324 325 326 327 328 329 330 331
  kWasmTrapUnreachable,
  kWasmTrapMemOutOfBounds,
  kWasmTrapUnalignedAccess,
  kWasmTrapDivByZero,
  kWasmTrapDivUnrepresentable,
  kWasmTrapRemByZero,
  kWasmTrapFloatUnrepresentable,
  kWasmTrapFuncSigMismatch,
  kWasmTrapDataSegmentDropped,
  kWasmTrapElemSegmentDropped,
332
  kWasmTrapTableOutOfBounds,
333 334
  kWasmTrapBrOnExnNull,
  kWasmTrapRethrowNull,
335
  kWasmTrapNullDereference,
336
  kWasmTrapIllegalCast,
337
  kWasmTrapArrayOutOfBounds,
338
  kWasmTrapWasmJSFunction,
339 340 341
  kWeakRefsRegisterTargetAndHoldingsMustNotBeSame,
  kWeakRefsRegisterTargetMustBeObject,
  kWeakRefsUnregisterTokenMustBeObject,
342
  kWeakRefsWeakRefConstructorTargetMustBeObject,
343 344
  ...
}
345

346 347 348 349 350 351 352 353 354 355
extern enum PropertyAttributes extends int31 {
  NONE,
  READ_ONLY,
  DONT_ENUM,
  DONT_DELETE,
  ALL_ATTRIBUTES_MASK,
  FROZEN,
  ...
}

356 357
const kMaxArrayIndex:
    constexpr uint32 generates 'JSArray::kMaxArrayIndex';
358 359
const kArrayBufferMaxByteLength:
    constexpr uintptr generates 'JSArrayBuffer::kMaxByteLength';
360 361
const kTypedArrayMaxLength:
    constexpr uintptr generates 'JSTypedArray::kMaxLength';
362 363
const kMaxTypedArrayInHeap:
    constexpr int31 generates 'JSTypedArray::kMaxSizeInHeap';
364 365 366 367
// CSA does not support 64-bit types on 32-bit platforms so as a workaround the
// kMaxSafeIntegerUint64 is defined as uintptr and allowed to be used only
// inside if constexpr (Is64()) i.e. on 64-bit architectures.
const kMaxSafeIntegerUint64: constexpr uintptr
368
    generates 'CodeStubAssembler::MaxSafeIntegerUintPtr()';
369
const kMaxSafeInteger: constexpr float64 generates 'kMaxSafeInteger';
370
const kMaxUInt32Double: constexpr float64 generates 'kMaxUInt32Double';
371
const kSmiMaxValue: constexpr uintptr generates 'kSmiMaxValue';
372
const kSmiMax: uintptr = kSmiMaxValue;
373
// TODO(v8:8996): Use uintptr version instead and drop this one.
374
const kStringMaxLength: constexpr int31 generates 'String::kMaxLength';
375 376
const kStringMaxLengthUintptr:
    constexpr uintptr generates 'String::kMaxLength';
377 378
const kFixedArrayMaxLength:
    constexpr int31 generates 'FixedArray::kMaxLength';
379 380
const kFixedDoubleArrayMaxLength:
    constexpr int31 generates 'FixedDoubleArray::kMaxLength';
381 382
const kObjectAlignmentMask: constexpr intptr
    generates 'kObjectAlignmentMask';
383 384 385 386
const kMinAddedElementsCapacity:
    constexpr int31 generates 'JSObject::kMinAddedElementsCapacity';
const kMaxCopyElements:
    constexpr int31 generates 'JSArray::kMaxCopyElements';
387 388 389 390 391 392
const kMaxRegularHeapObjectSize: constexpr int31
    generates 'kMaxRegularHeapObjectSize';

const kMaxNewSpaceFixedArrayElements: constexpr int31
    generates 'FixedArray::kMaxRegularLength';

393
extern enum PrimitiveType { kString, kBoolean, kSymbol, kNumber }
394

395 396 397
const kNameDictionaryInitialCapacity:
    constexpr int32 generates 'NameDictionary::kInitialCapacity';

398
type TheHole extends Oddball;
399 400 401 402
type Null extends Oddball;
type Undefined extends Oddball;
type True extends Oddball;
type False extends Oddball;
403
type Exception extends Oddball;
404
type EmptyString extends String;
405
type Boolean = True|False;
406

407
type NumberOrUndefined = Number|Undefined;
408

409
extern macro DefaultStringConstant(): String;
410
extern macro EmptyStringConstant(): EmptyString;
411
extern macro ErrorsStringConstant(): String;
412
extern macro FalseConstant(): False;
413
extern macro Int32FalseConstant(): bool;
414 415
extern macro Int32TrueConstant(): bool;
extern macro IteratorSymbolConstant(): PublicSymbol;
416
extern macro LengthStringConstant(): String;
417
extern macro MatchSymbolConstant(): Symbol;
418
extern macro MessageStringConstant(): String;
419
extern macro NanConstant(): NaN;
420
extern macro NameStringConstant(): String;
421
extern macro NullConstant(): Null;
422
extern macro NumberStringConstant(): String;
423
extern macro ReturnStringConstant(): String;
424
extern macro StringStringConstant(): String;
425
extern macro TheHoleConstant(): TheHole;
426 427
extern macro ToPrimitiveSymbolConstant(): PublicSymbol;
extern macro ToStringStringConstant(): String;
428 429
extern macro TrueConstant(): True;
extern macro UndefinedConstant(): Undefined;
430
extern macro ValueOfStringConstant(): String;
431
extern macro WasmWrappedObjectSymbolConstant(): Symbol;
432

433
const TheHole: TheHole = TheHoleConstant();
434 435 436 437
const Null: Null = NullConstant();
const Undefined: Undefined = UndefinedConstant();
const True: True = TrueConstant();
const False: False = FalseConstant();
438
const kEmptyString: EmptyString = EmptyStringConstant();
439
const kLengthString: String = LengthStringConstant();
440
const kMessageString: String = MessageStringConstant();
441 442
const kReturnString: String = ReturnStringConstant();

443
const kNaN: NaN = NanConstant();
444
const kZero: Zero = %RawDownCast<Zero>(SmiConstant(0));
445

446 447 448
const true: constexpr bool generates 'true';
const false: constexpr bool generates 'false';

449 450
extern enum LanguageMode extends bool { kStrict, kSloppy }
type LanguageModeSmi extends Smi;
451

452 453
const SKIP_WRITE_BARRIER:
    constexpr WriteBarrierMode generates 'SKIP_WRITE_BARRIER';
454 455
const UNSAFE_SKIP_WRITE_BARRIER:
    constexpr WriteBarrierMode generates 'UNSAFE_SKIP_WRITE_BARRIER';
456

457
extern transitioning macro AllocateJSIteratorResult(implicit context: Context)(
458
    JSAny, Boolean): JSObject;
459

460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
extern class Filler extends HeapObject generates 'TNode<HeapObject>';

// Various logical subclasses of JSObject, which have their own instance types
// but not their own class definitions:

// Like JSObject, but created from API function.
@apiExposedInstanceTypeValue(0x420)
extern class JSApiObject extends JSObject generates 'TNode<JSObject>';
// Like JSApiObject, but requires access checks and/or has interceptors.
@apiExposedInstanceTypeValue(0x410)
extern class JSSpecialApiObject extends JSSpecialObject
    generates 'TNode<JSSpecialObject>';
extern class JSContextExtensionObject extends JSObject
    generates 'TNode<JSObject>';
extern class JSError extends JSObject generates 'TNode<JSObject>';

476 477
extern macro Is64(): constexpr bool;

478 479
extern macro SelectBooleanConstant(bool): Boolean;

480 481
extern macro Print(constexpr string);
extern macro Print(constexpr string, Object);
482
extern macro Comment(constexpr string);
483 484
extern macro Print(Object);
extern macro DebugBreak();
485 486

// ES6 7.1.4 ToInteger ( argument )
487
transitioning macro ToIntegerImpl(implicit context: Context)(input: JSAny):
488
    Number {
489 490 491 492 493 494 495 496 497 498 499
  let input = input;

  while (true) {
    typeswitch (input) {
      case (s: Smi): {
        return s;
      }
      case (hn: HeapNumber): {
        let value = Convert<float64>(hn);
        if (Float64IsNaN(value)) return SmiConstant(0);
        value = math::Float64Trunc(value);
500 501
        // ToInteger normalizes -0 to +0.
        if (value == 0.0) return SmiConstant(0);
502
        const result = ChangeFloat64ToTagged(value);
503
        assert(IsNumberNormalized(result));
504 505
        return result;
      }
506 507
      case (a: JSAnyNotNumber): {
        input = conversion::NonNumberToNumber(a);
508 509 510 511 512 513
      }
    }
  }
  unreachable;
}

514
transitioning builtin ToInteger(implicit context: Context)(input: JSAny):
515
    Number {
516
  return ToIntegerImpl(input);
517 518 519
}

@export
520
transitioning macro ToInteger_Inline(implicit context: Context)(input: JSAny):
521 522 523 524 525
    Number {
  typeswitch (input) {
    case (s: Smi): {
      return s;
    }
526 527
    case (JSAny): {
      return ToInteger(input);
528 529 530 531
    }
  }
}

532 533 534 535 536 537
extern enum BigIntHandling extends int32
constexpr 'CodeStubAssembler::BigIntHandling' { kConvertToNumber, kThrow }

extern transitioning macro ToNumber(implicit context: Context)(
    JSAny, constexpr BigIntHandling): Number;

538 539 540 541 542 543
extern transitioning macro ToLength_Inline(implicit context: Context)(JSAny):
    Number;
extern transitioning macro ToNumber_Inline(implicit context: Context)(JSAny):
    Number;
extern transitioning macro ToString_Inline(implicit context: Context)(JSAny):
    String;
544
extern transitioning macro ToThisString(implicit context: Context)(
545
    JSAny, String): String;
546
extern transitioning macro ToThisValue(implicit context: Context)(
547
    JSAny, constexpr PrimitiveType, constexpr string): JSAny;
548
extern transitioning macro GetProperty(implicit context: Context)(
549
    JSAny, JSAny): JSAny;
550
extern transitioning builtin SetProperty(implicit context: Context)(
551
    JSAny, JSAny, JSAny): JSAny;
552 553
extern transitioning builtin SetPropertyIgnoreAttributes(
    implicit context: Context)(JSObject, String, JSAny, Smi): JSAny;
554
extern transitioning builtin SetPropertyInLiteral(implicit context: Context)(
555
    JSAny, JSAny, JSAny): JSAny;
556
extern transitioning builtin DeleteProperty(implicit context: Context)(
557
    JSAny, JSAny | PrivateSymbol, LanguageModeSmi): Boolean;
558
extern transitioning builtin HasProperty(implicit context: Context)(
559
    JSAny, JSAny): Boolean;
560
extern transitioning macro HasProperty_Inline(implicit context: Context)(
561
    JSReceiver, JSAny): Boolean;
562 563
extern builtin LoadIC(
    Context, JSAny, JSAny, TaggedIndex, FeedbackVector): JSAny;
564

565 566
extern macro SetPropertyStrict(Context, Object, Object, Object): Object;

567 568 569 570 571 572 573 574 575 576
extern macro ThrowRangeError(implicit context: Context)(
    constexpr MessageTemplate): never;
extern macro ThrowRangeError(implicit context: Context)(
    constexpr MessageTemplate, Object): never;
extern macro ThrowTypeError(implicit context: Context)(
    constexpr MessageTemplate): never;
extern macro ThrowTypeError(implicit context: Context)(
    constexpr MessageTemplate, constexpr string): never;
extern macro ThrowTypeError(implicit context: Context)(
    constexpr MessageTemplate, Object): never;
577 578
extern macro ThrowTypeError(implicit context: Context)(
    constexpr MessageTemplate, Object, Object): never;
579 580
extern macro ThrowTypeError(implicit context: Context)(
    constexpr MessageTemplate, Object, Object, Object): never;
581 582
extern transitioning runtime ThrowTypeErrorIfStrict(implicit context: Context)(
    Smi, Object, Object): void;
583 584
extern transitioning runtime ThrowCalledNonCallable(implicit context: Context)(
    JSAny): never;
585

586 587 588
extern transitioning macro ThrowIfNotJSReceiver(implicit context: Context)(
    JSAny, constexpr MessageTemplate, constexpr string): void;

589
extern macro ArraySpeciesCreate(Context, JSAny, Number): JSReceiver;
590
extern macro ArrayCreate(implicit context: Context)(Number): JSArray;
591
extern macro BuildAppendJSArray(
592
    constexpr ElementsKind, FastJSArray, JSAny): void labels Bailout;
593

594
extern macro EnsureArrayPushable(implicit context: Context)(Map): ElementsKind
595
    labels Bailout;
596
// TODO: Reduce duplication once varargs are supported in macros.
597
extern macro Construct(implicit context: Context)(Constructor): JSReceiver;
598
extern macro Construct(implicit context: Context)(
599
    Constructor, JSAny): JSReceiver;
600
extern macro Construct(implicit context: Context)(
601
    Constructor, JSAny, JSAny): JSReceiver;
602
extern macro Construct(implicit context: Context)(
603
    Constructor, JSAny, JSAny, JSAny): JSReceiver;
604 605 606
extern macro ConstructWithTarget(implicit context: Context)(
    Constructor, JSReceiver): JSReceiver;
extern macro ConstructWithTarget(implicit context: Context)(
607
    Constructor, JSReceiver, JSAny): JSReceiver;
608
extern macro SpeciesConstructor(implicit context: Context)(
609
    JSAny, JSReceiver): JSReceiver;
610

611 612 613 614
extern macro ConstructorBuiltinsAssembler::IsDictionaryMap(Map): bool;
extern macro CodeStubAssembler::AllocateNameDictionary(constexpr int32):
    NameDictionary;

615 616
extern builtin ToObject(Context, JSAny): JSReceiver;
extern macro ToObject_Inline(Context, JSAny): JSReceiver;
617
extern macro IsUndefined(Object): bool;
618
extern macro IsNullOrUndefined(Object): bool;
619
extern macro IsString(HeapObject): bool;
620
extern macro IsSeqOneByteString(HeapObject): bool;
Shiyu Zhang's avatar
Shiyu Zhang committed
621
extern transitioning builtin NonPrimitiveToPrimitive_String(
622
    Context, JSAny): JSPrimitive;
623
extern transitioning builtin NonPrimitiveToPrimitive_Default(
624 625 626 627 628 629 630 631 632 633 634 635 636
    Context, JSAny): JSPrimitive;

transitioning macro ToPrimitiveDefault(implicit context: Context)(v: JSAny):
    JSPrimitive {
  typeswitch (v) {
    case (v: JSReceiver): {
      return NonPrimitiveToPrimitive_Default(context, v);
    }
    case (v: JSPrimitive): {
      return v;
    }
  }
}
637

638 639 640
extern transitioning runtime NormalizeElements(Context, JSObject);
extern transitioning runtime TransitionElementsKindWithKind(
    Context, JSObject, Smi);
641

642 643 644
extern macro LoadBufferObject(RawPtr, constexpr int32): Object;
extern macro LoadBufferPointer(RawPtr, constexpr int32): RawPtr;
extern macro LoadBufferSmi(RawPtr, constexpr int32): Smi;
645
extern macro LoadBufferIntptr(RawPtr, constexpr int32): intptr;
646

647
extern runtime StringEqual(Context, String, String): Oddball;
648
extern builtin StringLessThan(Context, String, String): Boolean;
649
extern macro StringCharCodeAt(String, uintptr): int32;
650
extern runtime StringCompareSequence(Context, String, String, Number): Boolean;
651
extern macro StringFromSingleCharCode(int32): String;
652

653 654
extern macro NumberToString(Number): String;
extern macro StringToNumber(String): Number;
655 656 657 658
extern transitioning macro NonNumberToNumber(implicit context: Context)(
    JSAnyNotNumber): Number;
extern transitioning macro NonNumberToNumeric(implicit context: Context)(
    JSAnyNotNumber): Numeric;
659

660 661 662 663 664
extern macro Equal(JSAny, JSAny, Context): Boolean;
macro Equal(implicit context: Context)(left: JSAny, right: JSAny): Boolean {
  return Equal(left, right);
}

665
extern macro StrictEqual(JSAny, JSAny): Boolean;
666
extern macro SmiLexicographicCompare(Smi, Smi): Smi;
667
extern runtime ReThrow(Context, JSAny): never;
668
extern runtime Throw(implicit context: Context)(JSAny): never;
669
extern runtime ThrowInvalidStringLength(Context): never;
670

671 672
extern operator '==' macro WordEqual(RawPtr, RawPtr): bool;
extern operator '!=' macro WordNotEqual(RawPtr, RawPtr): bool;
673 674
extern operator '+' macro RawPtrAdd(RawPtr, intptr): RawPtr;
extern operator '+' macro RawPtrAdd(intptr, RawPtr): RawPtr;
675

676
extern operator '<' macro Int32LessThan(int32, int32): bool;
677
extern operator '<' macro Uint32LessThan(uint32, uint32): bool;
678
extern operator '>' macro Int32GreaterThan(int32, int32): bool;
679
extern operator '>' macro Uint32GreaterThan(uint32, uint32): bool;
680
extern operator '<=' macro Int32LessThanOrEqual(int32, int32): bool;
681
extern operator '<=' macro Uint32LessThanOrEqual(uint32, uint32): bool;
682
extern operator '>=' macro Int32GreaterThanOrEqual(int32, int32): bool;
683
extern operator '>=' macro Uint32GreaterThanOrEqual(uint32, uint32): bool;
684

685 686 687 688 689 690
extern operator '==' macro SmiEqual(Smi, Smi): bool;
extern operator '!=' macro SmiNotEqual(Smi, Smi): bool;
extern operator '<' macro SmiLessThan(Smi, Smi): bool;
extern operator '<=' macro SmiLessThanOrEqual(Smi, Smi): bool;
extern operator '>' macro SmiGreaterThan(Smi, Smi): bool;
extern operator '>=' macro SmiGreaterThanOrEqual(Smi, Smi): bool;
691

692 693
extern operator '==' macro ElementsKindEqual(
    constexpr ElementsKind, constexpr ElementsKind): constexpr bool;
694
extern operator '==' macro ElementsKindEqual(ElementsKind, ElementsKind): bool;
695 696 697 698
operator '!=' macro ElementsKindNotEqual(
    k1: ElementsKind, k2: ElementsKind): bool {
  return !ElementsKindEqual(k1, k2);
}
699 700 701 702
extern macro IsElementsKindLessThanOrEqual(
    ElementsKind, constexpr ElementsKind): bool;
extern macro IsElementsKindGreaterThan(
    ElementsKind, constexpr ElementsKind): bool;
703 704 705
extern macro IsElementsKindInRange(
    ElementsKind, constexpr ElementsKind, constexpr ElementsKind): bool;

706
extern macro IsFastElementsKind(constexpr ElementsKind): constexpr bool;
707
extern macro IsDoubleElementsKind(constexpr ElementsKind): constexpr bool;
708

709 710 711 712
extern macro IsFastAliasedArgumentsMap(implicit context: Context)(Map): bool;
extern macro IsSlowAliasedArgumentsMap(implicit context: Context)(Map): bool;
extern macro IsSloppyArgumentsMap(implicit context: Context)(Map): bool;
extern macro IsStrictArgumentsMap(implicit context: Context)(Map): bool;
713
extern macro IsTuple2Map(Map): bool;
714

715
extern macro SmiAbove(Smi, Smi): bool;
716

717
extern operator '==' macro WordEqual(intptr, intptr): bool;
718
extern operator '==' macro WordEqual(uintptr, uintptr): bool;
719
extern operator '!=' macro WordNotEqual(intptr, intptr): bool;
720
extern operator '!=' macro WordNotEqual(uintptr, uintptr): bool;
721
extern operator '<' macro IntPtrLessThan(intptr, intptr): bool;
722
extern operator '<' macro UintPtrLessThan(uintptr, uintptr): bool;
723
extern operator '>' macro IntPtrGreaterThan(intptr, intptr): bool;
724
extern operator '>' macro UintPtrGreaterThan(uintptr, uintptr): bool;
725
extern operator '<=' macro IntPtrLessThanOrEqual(intptr, intptr): bool;
726
extern operator '<=' macro UintPtrLessThanOrEqual(uintptr, uintptr): bool;
727
extern operator '>=' macro IntPtrGreaterThanOrEqual(intptr, intptr): bool;
728
extern operator '>=' macro UintPtrGreaterThanOrEqual(uintptr, uintptr): bool;
729 730 731 732 733
extern operator '~' macro WordNot(intptr): intptr;
extern operator '~' macro WordNot(uintptr): uintptr;
extern operator '~' macro ConstexprWordNot(constexpr intptr): constexpr intptr;
extern operator '~' macro ConstexprWordNot(constexpr uintptr):
    constexpr uintptr;
734

735
extern operator '==' macro Float64Equal(float64, float64): bool;
736
extern operator '!=' macro Float64NotEqual(float64, float64): bool;
737
extern operator '>' macro Float64GreaterThan(float64, float64): bool;
738
extern operator '>=' macro Float64GreaterThanOrEqual(float64, float64): bool;
739
extern operator '<' macro Float64LessThan(float64, float64): bool;
740
extern operator '<=' macro Float64LessThanOrEqual(float64, float64): bool;
741

742
extern macro BranchIfNumberEqual(Number, Number): never
743
    labels Taken, NotTaken;
744
operator '==' macro IsNumberEqual(a: Number, b: Number): bool {
745
  BranchIfNumberEqual(a, b) otherwise return true, return false;
746
}
747
operator '!=' macro IsNumberNotEqual(a: Number, b: Number): bool {
748
  return !(a == b);
749
}
750
extern macro BranchIfNumberLessThan(Number, Number): never
751
    labels Taken, NotTaken;
752 753 754 755
operator '<' macro NumberIsLessThan(a: Number, b: Number): bool {
  BranchIfNumberLessThan(a, b) otherwise return true, return false;
}
extern macro BranchIfNumberLessThanOrEqual(Number, Number): never
756
    labels Taken, NotTaken;
757 758 759
operator '<=' macro NumberIsLessThanOrEqual(a: Number, b: Number): bool {
  BranchIfNumberLessThanOrEqual(a, b) otherwise return true, return false;
}
760

761 762 763 764 765 766
operator '>' macro NumberIsGreaterThan(a: Number, b: Number): bool {
  return b < a;
}
operator '>=' macro NumberIsGreaterThanOrEqual(a: Number, b: Number): bool {
  return b <= a;
}
767

768 769 770
extern macro BranchIfFloat64IsNaN(float64): never
    labels Taken, NotTaken;
macro Float64IsNaN(n: float64): bool {
771
  BranchIfFloat64IsNaN(n) otherwise return true, return false;
772 773
}

774
// The type of all tagged values that can safely be compared with TaggedEqual.
775
type TaggedWithIdentity =
776
    JSReceiver|FixedArrayBase|Oddball|Map|WeakCell|Context|EmptyString;
777

778 779 780
extern operator '==' macro TaggedEqual(TaggedWithIdentity, Object): bool;
extern operator '==' macro TaggedEqual(Object, TaggedWithIdentity): bool;
extern operator '==' macro TaggedEqual(
781
    TaggedWithIdentity, TaggedWithIdentity): bool;
782
extern operator '==' macro TaggedEqual(WeakHeapObject, WeakHeapObject): bool;
783 784 785
extern operator '!=' macro TaggedNotEqual(TaggedWithIdentity, Object): bool;
extern operator '!=' macro TaggedNotEqual(Object, TaggedWithIdentity): bool;
extern operator '!=' macro TaggedNotEqual(
786
    TaggedWithIdentity, TaggedWithIdentity): bool;
787
extern operator '!=' macro TaggedNotEqual(WeakHeapObject, WeakHeapObject): bool;
788 789
// Do not overload == and != if it is unclear if object identity is the right
// equality.
790 791
extern macro TaggedEqual(MaybeObject, MaybeObject): bool;
extern macro TaggedNotEqual(MaybeObject, MaybeObject): bool;
792 793 794

extern operator '+' macro SmiAdd(Smi, Smi): Smi;
extern operator '-' macro SmiSub(Smi, Smi): Smi;
795
extern operator '&' macro SmiAnd(Smi, Smi): Smi;
796 797
extern operator '|' macro SmiOr(Smi, Smi): Smi;
extern operator '<<' macro SmiShl(Smi, constexpr int31): Smi;
798
extern operator '>>' macro SmiSar(Smi, constexpr int31): Smi;
799 800

extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
801 802 803 804
extern operator '+' macro ConstexprIntPtrAdd(
    constexpr intptr, constexpr intptr): constexpr intptr;
extern operator '+' macro ConstexprUintPtrAdd(
    constexpr uintptr, constexpr uintptr): constexpr intptr;
805
extern operator '-' macro IntPtrSub(intptr, intptr): intptr;
806
extern operator '*' macro IntPtrMul(intptr, intptr): intptr;
807
extern operator '/' macro IntPtrDiv(intptr, intptr): intptr;
808
extern operator '<<' macro WordShl(intptr, intptr): intptr;
809
extern operator '>>' macro WordSar(intptr, intptr): intptr;
810
extern operator '&' macro WordAnd(intptr, intptr): intptr;
811 812 813 814
extern operator '|' macro WordOr(intptr, intptr): intptr;

extern operator '+' macro UintPtrAdd(uintptr, uintptr): uintptr;
extern operator '-' macro UintPtrSub(uintptr, uintptr): uintptr;
815
extern operator '<<' macro WordShl(uintptr, uintptr): uintptr;
Tobias Tebbi's avatar
Tobias Tebbi committed
816 817 818
extern operator '>>>' macro WordShr(uintptr, uintptr): uintptr;
extern operator '&' macro WordAnd(uintptr, uintptr): uintptr;
extern operator '|' macro WordOr(uintptr, uintptr): uintptr;
819

Tobias Tebbi's avatar
Tobias Tebbi committed
820 821 822 823 824 825 826
extern operator '+' macro Int32Add(int32, int32): int32;
extern operator '+' macro ConstexprUint32Add(
    constexpr uint32, constexpr int32): constexpr uint32;
extern operator '+' macro ConstexprInt31Add(
    constexpr int31, constexpr int31): constexpr int31;
extern operator '*' macro ConstexprInt31Mul(
    constexpr int31, constexpr int31): constexpr int31;
827 828
extern operator '-' macro Int32Sub(int16, int16): int32;
extern operator '-' macro Int32Sub(uint16, uint16): int32;
Tobias Tebbi's avatar
Tobias Tebbi committed
829 830 831 832 833 834 835 836 837 838 839 840 841
extern operator '-' macro Int32Sub(int32, int32): int32;
extern operator '*' macro Int32Mul(int32, int32): int32;
extern operator '/' macro Int32Div(int32, int32): int32;
extern operator '%' macro Int32Mod(int32, int32): int32;
extern operator '&' macro Word32And(int32, int32): int32;
extern operator '&' macro Word32And(uint32, uint32): uint32;
extern operator '==' macro
ConstexprInt31Equal(constexpr int31, constexpr int31): constexpr bool;
extern operator '!=' macro
ConstexprInt31NotEqual(constexpr int31, constexpr int31): constexpr bool;
extern operator '>=' macro
ConstexprInt31GreaterThanEqual(
    constexpr int31, constexpr int31): constexpr bool;
842 843 844 845
extern operator '==' macro ConstexprInt32Equal(
    constexpr int32, constexpr int32): constexpr bool;
extern operator '!=' macro ConstexprInt32NotEqual(
    constexpr int32, constexpr int32): constexpr bool;
846

Tobias Tebbi's avatar
Tobias Tebbi committed
847 848 849 850 851
extern operator '==' macro Word32Equal(int32, int32): bool;
extern operator '==' macro Word32Equal(uint32, uint32): bool;
extern operator '!=' macro Word32NotEqual(int32, int32): bool;
extern operator '!=' macro Word32NotEqual(uint32, uint32): bool;
extern operator '>>>' macro Word32Shr(uint32, uint32): uint32;
852
extern operator '>>' macro Word32Sar(int32, int32): int32;
Tobias Tebbi's avatar
Tobias Tebbi committed
853 854 855 856 857 858 859 860
extern operator '<<' macro Word32Shl(int32, int32): int32;
extern operator '<<' macro Word32Shl(uint32, uint32): uint32;
extern operator '|' macro Word32Or(int32, int32): int32;
extern operator '|' macro Word32Or(uint32, uint32): uint32;
extern operator '&' macro Word32And(bool, bool): bool;
extern operator '|' macro Word32Or(bool, bool): bool;
extern operator '==' macro Word32Equal(bool, bool): bool;
extern operator '!=' macro Word32NotEqual(bool, bool): bool;
861 862
extern operator '|' macro ConstexprWord32Or(
    constexpr int32, constexpr int32): constexpr int32;
863

Tobias Tebbi's avatar
Tobias Tebbi committed
864 865 866 867
extern operator '+' macro Float64Add(float64, float64): float64;
extern operator '-' macro Float64Sub(float64, float64): float64;
extern operator '*' macro Float64Mul(float64, float64): float64;
extern operator '/' macro Float64Div(float64, float64): float64;
868
extern operator '%' macro Float64Mod(float64, float64): float64;
869

Tobias Tebbi's avatar
Tobias Tebbi committed
870 871 872 873 874 875
extern operator '+' macro NumberAdd(Number, Number): Number;
extern operator '-' macro NumberSub(Number, Number): Number;
extern macro NumberMin(Number, Number): Number;
extern macro NumberMax(Number, Number): Number;
macro Min(x: Number, y: Number): Number {
  return NumberMin(x, y);
876
}
Tobias Tebbi's avatar
Tobias Tebbi committed
877 878
macro Max(x: Number, y: Number): Number {
  return NumberMax(x, y);
879 880
}

Tobias Tebbi's avatar
Tobias Tebbi committed
881 882 883
extern macro TryIntPtrAdd(intptr, intptr): intptr labels Overflow;
extern macro TryIntPtrSub(intptr, intptr): intptr labels Overflow;
extern macro TryInt32Mul(int32, int32): int32 labels Overflow;
884

Tobias Tebbi's avatar
Tobias Tebbi committed
885 886 887 888 889 890
extern operator '<' macro ConstexprUintPtrLessThan(
    constexpr uintptr, constexpr uintptr): constexpr bool;
extern operator '<<' macro ConstexprUintPtrShl(
    constexpr uintptr, constexpr int31): constexpr uintptr;
extern operator '>>>' macro ConstexprUintPtrShr(
    constexpr uintptr, constexpr int31): constexpr uintptr;
891

Tobias Tebbi's avatar
Tobias Tebbi committed
892 893 894 895
extern macro SmiMax(Smi, Smi): Smi;
extern macro SmiMin(Smi, Smi): Smi;
extern macro SmiMul(Smi, Smi): Number;
extern macro SmiMod(Smi, Smi): Number;
896

Tobias Tebbi's avatar
Tobias Tebbi committed
897 898 899
extern macro IntPtrMax(intptr, intptr): intptr;
extern macro IntPtrMin(intptr, intptr): intptr;
extern macro UintPtrMin(uintptr, uintptr): uintptr;
900

Tobias Tebbi's avatar
Tobias Tebbi committed
901 902 903
extern operator '!' macro ConstexprBoolNot(constexpr bool): constexpr bool;
extern operator '!' macro Word32BinaryNot(bool): bool;
extern operator '!' macro IsFalse(Boolean): bool;
904

905 906 907 908 909 910
extern operator '==' macro
ConstexprInt31Equal(
    constexpr InstanceType, constexpr InstanceType): constexpr bool;
extern operator '-' macro ConstexprUint32Sub(
    constexpr InstanceType, constexpr InstanceType): constexpr int32;

Tobias Tebbi's avatar
Tobias Tebbi committed
911 912
extern operator '.instanceType' macro LoadInstanceType(HeapObject):
    InstanceType;
913

Tobias Tebbi's avatar
Tobias Tebbi committed
914 915 916
operator '.length_uintptr' macro LoadJSArrayLengthAsUintPtr(array: JSArray):
    uintptr {
  return Convert<uintptr>(array.length);
917 918
}

Tobias Tebbi's avatar
Tobias Tebbi committed
919 920 921
extern operator '.length_intptr' macro LoadStringLengthAsWord(String): intptr;
operator '.length_uintptr' macro LoadStringLengthAsUintPtr(s: String): uintptr {
  return Unsigned(s.length_intptr);
922
}
Tobias Tebbi's avatar
Tobias Tebbi committed
923 924
extern operator '.length_uint32' macro LoadStringLengthAsWord32(String): uint32;
extern operator '.length_smi' macro LoadStringLengthAsSmi(String): Smi;
925

Tobias Tebbi's avatar
Tobias Tebbi committed
926 927 928 929 930
extern builtin StringAdd_CheckNone(implicit context: Context)(
    String, String): String;
operator '+' macro StringAdd(implicit context: Context)(
    a: String, b: String): String {
  return StringAdd_CheckNone(a, b);
931 932
}

Tobias Tebbi's avatar
Tobias Tebbi committed
933 934 935
operator '==' macro PromiseStateEquals(
    s1: PromiseState, s2: PromiseState): bool {
  return Word32Equal(s1, s2);
936 937
}

Tobias Tebbi's avatar
Tobias Tebbi committed
938 939 940 941
extern macro TaggedIsSmi(Object): bool;
extern macro TaggedIsNotSmi(Object): bool;
extern macro TaggedIsPositiveSmi(Object): bool;
extern macro IsValidPositiveSmi(intptr): bool;
942

943
extern macro IsInteger(JSAny): bool;
Tobias Tebbi's avatar
Tobias Tebbi committed
944
extern macro IsInteger(HeapNumber): bool;
945

946
extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
947 948
extern macro ChangeInt32ToTagged(int32): Number;
extern macro ChangeUint32ToTagged(uint32): Number;
949 950
extern macro ChangeUintPtrToFloat64(uintptr): float64;
extern macro ChangeUintPtrToTagged(uintptr): Number;
951
extern macro Unsigned(int32): uint32;
952 953
extern macro Unsigned(int16): uint16;
extern macro Unsigned(int8): uint8;
954
extern macro Unsigned(intptr): uintptr;
955 956
extern macro Unsigned(RawPtr): uintptr;
extern macro Signed(uint32): int32;
957 958
extern macro Signed(uint16): int16;
extern macro Signed(uint8): int8;
959
extern macro Signed(uintptr): intptr;
960
extern macro Signed(RawPtr): intptr;
961 962 963
extern macro TruncateIntPtrToInt32(intptr): int32;
extern macro SmiTag(intptr): Smi;
extern macro SmiFromInt32(int32): Smi;
964
extern macro SmiFromUint32(uint32): Smi;
965
extern macro SmiFromIntPtr(intptr): Smi;
966
extern macro SmiUntag(Smi): intptr;
967 968 969
macro SmiUntag<T: type>(value: SmiTagged<T>): T {
  return %RawDownCast<T>(Unsigned(SmiToInt32(Convert<Smi>(value))));
}
970 971 972
macro SmiTag<T : type extends uint31>(value: T): SmiTagged<T> {
  return %RawDownCast<SmiTagged<T>>(SmiFromUint32(value));
}
973
extern macro SmiToInt32(Smi): int32;
974
extern macro SmiToFloat64(Smi): float64;
975 976 977 978
extern macro TaggedIndexToIntPtr(TaggedIndex): intptr;
extern macro IntPtrToTaggedIndex(intptr): TaggedIndex;
extern macro TaggedIndexToSmi(TaggedIndex): Smi;
extern macro SmiToTaggedIndex(Smi): TaggedIndex;
979
extern macro RoundIntPtrToFloat64(intptr): float64;
980 981
extern macro ChangeFloat32ToFloat64(float32): float64;
extern macro ChangeNumberToFloat64(Number): float64;
982
extern macro ChangeNumberToUint32(Number): uint32;
983 984 985
extern macro ChangeTaggedNonSmiToInt32(implicit context: Context)(JSAnyNotSmi):
    int32;
extern macro ChangeTaggedToFloat64(implicit context: Context)(JSAny): float64;
986
extern macro ChangeFloat64ToTagged(float64): Number;
987
extern macro ChangeFloat64ToUintPtr(float64): uintptr;
988
extern macro ChangeFloat64ToIntPtr(float64): intptr;
989
extern macro ChangeInt32ToFloat64(int32): float64;
990
extern macro ChangeInt32ToIntPtr(int32): intptr;   // Sign-extends.
991
extern macro ChangeUint32ToWord(uint32): uintptr;  // Doesn't sign-extend.
992
extern macro LoadNativeContext(Context): NativeContext;
993
extern macro TruncateFloat64ToFloat32(float64): float32;
994
extern macro TruncateHeapNumberValueToWord32(HeapNumber): int32;
995 996
extern macro LoadJSArrayElementsMap(constexpr ElementsKind, NativeContext): Map;
extern macro LoadJSArrayElementsMap(ElementsKind, NativeContext): Map;
997 998
extern macro NumberConstant(constexpr float64): Number;
extern macro NumberConstant(constexpr int32): Number;
999
extern macro NumberConstant(constexpr uint32): Number;
1000 1001
extern macro IntPtrConstant(constexpr int31): intptr;
extern macro IntPtrConstant(constexpr int32): intptr;
1002
extern macro Uint16Constant(constexpr uint16): uint16;
1003
extern macro Int32Constant(constexpr int31): int31;
1004
extern macro Int32Constant(constexpr int32): int32;
1005
extern macro Float64Constant(constexpr int31): float64;
1006
extern macro Float64Constant(constexpr float64): float64;
1007
extern macro SmiConstant(constexpr int31): Smi;
1008
extern macro SmiConstant(constexpr Smi): Smi;
1009
extern macro SmiConstant(constexpr MessageTemplate): Smi;
1010 1011
extern macro SmiConstant(constexpr bool): Smi;
extern macro SmiConstant(constexpr uint32): Smi;
1012
extern macro BoolConstant(constexpr bool): bool;
1013
extern macro StringConstant(constexpr string): String;
1014
extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot;
1015
extern macro IntPtrConstant(constexpr intptr): intptr;
1016
extern macro PointerConstant(constexpr RawPtr): RawPtr;
1017
extern macro SingleCharacterStringConstant(constexpr string): String;
1018
extern macro Float64SilenceNaN(float64): float64;
1019

1020
extern macro BitcastWordToTaggedSigned(intptr): Smi;
1021
extern macro BitcastWordToTaggedSigned(uintptr): Smi;
1022
extern macro BitcastWordToTagged(intptr): Object;
1023 1024
extern macro BitcastWordToTagged(uintptr): Object;
extern macro BitcastTaggedToWord(Tagged): intptr;
1025
extern macro BitcastTaggedToWordForTagAndSmiBits(Tagged): intptr;
1026

1027
extern macro FixedArrayMapConstant(): Map;
1028
extern macro FixedDoubleArrayMapConstant(): Map;
1029 1030
extern macro FixedCOWArrayMapConstant(): Map;
extern macro EmptyByteArrayConstant(): ByteArray;
1031
extern macro EmptyFixedArrayConstant(): EmptyFixedArray;
1032
extern macro PromiseCapabilityMapConstant(): Map;
1033 1034
extern macro OneByteStringMapConstant(): Map;
extern macro StringMapConstant(): Map;
1035 1036

const kFixedArrayMap: Map = FixedArrayMapConstant();
1037
const kFixedDoubleArrayMap: Map = FixedDoubleArrayMapConstant();
1038 1039
const kCOWMap: Map = FixedCOWArrayMapConstant();
const kEmptyByteArray: ByteArray = EmptyByteArrayConstant();
1040
const kEmptyFixedArray: EmptyFixedArray = EmptyFixedArrayConstant();
1041
const kPromiseCapabilityMap: Map = PromiseCapabilityMapConstant();
1042 1043 1044 1045
// The map of a non-internalized internal SeqOneByteString.
const kOneByteStringMap: Map = OneByteStringMapConstant();
// The map of a non-internalized internal SeqTwoByteString.
const kStringMap: Map = StringMapConstant();
1046

1047 1048 1049 1050 1051 1052
macro OutOfBounds<T: type, X: type>(index: T, length: X): bool {
  return UintPtrGreaterThanOrEqual(
      Convert<uintptr>(Convert<intptr>(index)),
      Convert<uintptr>(Convert<intptr>(length)));
}

1053 1054
extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
    bool;
1055
extern macro IsNoElementsProtectorCellInvalid(): bool;
1056
extern macro IsArrayIteratorProtectorCellInvalid(): bool;
1057 1058 1059
extern macro IsArraySpeciesProtectorCellInvalid(): bool;
extern macro IsTypedArraySpeciesProtectorCellInvalid(): bool;
extern macro IsPromiseSpeciesProtectorCellInvalid(): bool;
1060
extern macro IsMockArrayBufferAllocatorFlag(): bool;
1061 1062
extern macro IsPrototypeTypedArrayPrototype(implicit context: Context)(Map):
    bool;
1063

1064
extern operator '.data_ptr' macro LoadJSTypedArrayDataPtr(JSTypedArray): RawPtr;
1065

1066
extern operator '.elements_kind' macro LoadMapElementsKind(Map): ElementsKind;
1067 1068
extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray):
    ElementsKind;
1069

1070
extern operator '.length' macro LoadFastJSArrayLength(FastJSArray): Smi;
1071 1072 1073 1074 1075
operator '.length=' macro StoreFastJSArrayLength(
    array: FastJSArray, length: Smi) {
  const array: JSArray = array;
  array.length = length;
}
1076

1077
extern macro GetNumberDictionaryNumberOfElements(NumberDictionary): Smi;
1078

1079 1080
extern macro LoadConstructorOrBackPointer(Map): Object;

1081
extern macro BasicLoadNumberDictionaryElement(NumberDictionary, intptr): JSAny
1082
    labels NotData, IfHole;
1083

1084
extern macro IsFastElementsKind(ElementsKind): bool;
1085
extern macro IsDoubleElementsKind(ElementsKind): bool;
1086 1087
extern macro IsFastSmiOrTaggedElementsKind(ElementsKind): bool;
extern macro IsFastSmiElementsKind(ElementsKind): bool;
1088
extern macro IsHoleyFastElementsKind(ElementsKind): bool;
1089

1090
macro FastHoleyElementsKind(kind: ElementsKind): ElementsKind {
1091 1092 1093 1094
  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
    return ElementsKind::HOLEY_SMI_ELEMENTS;
  } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) {
    return ElementsKind::HOLEY_DOUBLE_ELEMENTS;
1095
  }
1096 1097
  assert(kind == ElementsKind::PACKED_ELEMENTS);
  return ElementsKind::HOLEY_ELEMENTS;
1098 1099
}

1100
macro AllowDoubleElements(kind: ElementsKind): ElementsKind {
1101 1102 1103 1104
  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
    return ElementsKind::PACKED_DOUBLE_ELEMENTS;
  } else if (kind == ElementsKind::HOLEY_SMI_ELEMENTS) {
    return ElementsKind::HOLEY_DOUBLE_ELEMENTS;
1105 1106 1107 1108 1109
  }
  return kind;
}

macro AllowNonNumberElements(kind: ElementsKind): ElementsKind {
1110 1111 1112 1113 1114 1115 1116 1117
  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
    return ElementsKind::PACKED_ELEMENTS;
  } else if (kind == ElementsKind::HOLEY_SMI_ELEMENTS) {
    return ElementsKind::HOLEY_ELEMENTS;
  } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) {
    return ElementsKind::PACKED_ELEMENTS;
  } else if (kind == ElementsKind::HOLEY_DOUBLE_ELEMENTS) {
    return ElementsKind::HOLEY_ELEMENTS;
1118 1119 1120 1121
  }
  return kind;
}

1122
macro GetObjectFunction(implicit context: Context)(): JSFunction {
1123
  return *NativeContextSlot(ContextSlot::OBJECT_FUNCTION_INDEX);
1124
}
1125
macro GetArrayFunction(implicit context: Context)(): JSFunction {
1126
  return *NativeContextSlot(ContextSlot::ARRAY_FUNCTION_INDEX);
1127
}
1128
macro GetArrayBufferFunction(implicit context: Context)(): Constructor {
1129
  return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_FUN_INDEX);
1130
}
1131
macro GetArrayBufferNoInitFunction(implicit context: Context)(): JSFunction {
1132
  return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_NOINIT_FUN_INDEX);
1133
}
1134
macro GetFastPackedElementsJSArrayMap(implicit context: Context)(): Map {
1135
  return *NativeContextSlot(ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
1136
}
1137
macro GetFastPackedSmiElementsJSArrayMap(implicit context: Context)(): Map {
1138 1139
  return *NativeContextSlot(
      ContextSlot::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX);
1140
}
1141
macro GetProxyRevocableResultMap(implicit context: Context)(): Map {
1142
  return *NativeContextSlot(ContextSlot::PROXY_REVOCABLE_RESULT_MAP_INDEX);
1143
}
1144
macro GetIteratorResultMap(implicit context: Context)(): Map {
1145
  return *NativeContextSlot(ContextSlot::ITERATOR_RESULT_MAP_INDEX);
1146
}
1147
macro GetInitialStringIteratorMap(implicit context: Context)(): Map {
1148
  return *NativeContextSlot(ContextSlot::INITIAL_STRING_ITERATOR_MAP_INDEX);
1149
}
1150
macro GetReflectApply(implicit context: Context)(): Callable {
1151
  return *NativeContextSlot(ContextSlot::REFLECT_APPLY_INDEX);
1152 1153
}
macro GetRegExpLastMatchInfo(implicit context: Context)(): RegExpMatchInfo {
1154
  return *NativeContextSlot(ContextSlot::REGEXP_LAST_MATCH_INFO_INDEX);
1155
}
1156
macro GetStrictArgumentsMap(implicit context: Context)(): Map {
1157
  return *NativeContextSlot(ContextSlot::STRICT_ARGUMENTS_MAP_INDEX);
1158 1159
}
macro GetSloppyArgumentsMap(implicit context: Context)(): Map {
1160
  return *NativeContextSlot(ContextSlot::SLOPPY_ARGUMENTS_MAP_INDEX);
1161 1162
}
macro GetFastAliasedArgumentsMap(implicit context: Context)(): Map {
1163
  return *NativeContextSlot(ContextSlot::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
1164
}
1165 1166 1167
macro GetWeakCellMap(implicit context: Context)(): Map {
  return %GetClassMapConstant<WeakCell>();
}
1168

1169 1170 1171 1172 1173 1174 1175
// Call(Context, Target, Receiver, ...Args)
// TODO(joshualitt): Assuming the context parameter is for throwing when Target
//                   is non-callable, then we should make it an implicit
//                   parameter.
extern transitioning macro Call(Context, JSAny, JSAny): JSAny;
extern transitioning macro Call(Context, JSAny, JSAny, JSAny): JSAny;
extern transitioning macro Call(Context, JSAny, JSAny, JSAny, JSAny): JSAny;
1176
extern transitioning macro Call(
1177
    Context, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1178
extern transitioning macro Call(
1179
    Context, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1180
extern transitioning macro Call(
1181
    Context, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1182

1183
extern macro TransitionElementsKind(
1184 1185
    JSObject, Map, constexpr ElementsKind,
    constexpr ElementsKind): void labels Bailout;
1186
extern macro PerformStackCheck(implicit context: Context)(): void;
1187

1188
extern macro Typeof(JSAny): String;
1189

1190 1191
// Return true iff number is NaN.
macro NumberIsNaN(number: Number): bool {
1192 1193
  typeswitch (number) {
    case (Smi): {
1194
      return false;
1195 1196
    }
    case (hn: HeapNumber): {
1197
      const value: float64 = Convert<float64>(hn);
1198 1199
      return value != value;
    }
1200
  }
1201
}
1202

1203
extern macro GotoIfForceSlowPath() labels Taken;
1204 1205 1206 1207 1208
macro IsForceSlowPath(): bool {
  GotoIfForceSlowPath() otherwise return true;
  return false;
}

1209
extern macro BranchIfToBooleanIsTrue(JSAny): never
1210
    labels Taken, NotTaken;
1211
extern macro BranchIfToBooleanIsFalse(JSAny): never
1212
    labels Taken, NotTaken;
1213

1214
macro ToBoolean(obj: JSAny): bool {
1215
  BranchIfToBooleanIsTrue(obj) otherwise return true, return false;
1216
}
1217

1218 1219
@export
macro RequireObjectCoercible(implicit context: Context)(
1220
    value: JSAny, name: constexpr string): JSAny {
1221
  if (IsNullOrUndefined(value)) {
1222
    ThrowTypeError(MessageTemplate::kCalledOnNullOrUndefined, name);
1223 1224 1225 1226
  }
  return value;
}

1227 1228
extern macro BranchIfSameValue(JSAny, JSAny): never labels Taken, NotTaken;
macro SameValue(a: JSAny, b: JSAny): bool {
1229 1230
  BranchIfSameValue(a, b) otherwise return true, return false;
}
1231

1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
// Does "if (index1 + index2 > limit) goto IfOverflow" in an uintptr overflow
// friendly way where index1 and index2 are in [0, kMaxSafeInteger] range.
macro CheckIntegerIndexAdditionOverflow(
    index1: uintptr, index2: uintptr, limit: uintptr) labels IfOverflow {
  if constexpr (Is64()) {
    assert(index1 <= kMaxSafeIntegerUint64);
    assert(index2 <= kMaxSafeIntegerUint64);
    // Given that both index1 and index2 are in a safe integer range the
    // addition can't overflow.
    if (index1 + index2 > limit) goto IfOverflow;
  } else {
    // Uintptr range is "smaller" than [0, kMaxSafeInteger] range, so
    // "index1 + index2" may overflow, so we check the condition in the
    // following way "if (index1 > limit - index2) goto IfOverflow" and check
    // that "limit - index2" does not underflow.
    const index1Limit = limit - index2;
    if (index1 > index1Limit) goto IfOverflow;
    // Handle potential index1Limit underflow.
    if (index1Limit > limit) goto IfOverflow;
  }
}

1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
// TODO(tebbi): Define enum here once they appear in Torque.
//
// The value is a SafeInteger that fits into uintptr range, so no bounds checks
// are necessary.
const kModeValueIsSafeIntegerUintPtr: constexpr int31 = 0;
// The value is a SafeInteger that may not fit into uintptr range, so only
// uintptr bounds check is necessary.
const kModeValueIsSafeInteger: constexpr int31 = 1;
// The value is can be whatever non-NaN number, all checks are necessary.
const kModeValueIsAnyNumber: constexpr int31 = 2;

macro TryNumberToUintPtr(valueNumber: Number, kMode: constexpr int31):
    uintptr labels IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow {
  typeswitch (valueNumber) {
    case (valueSmi: Smi): {
      if (kMode == kModeValueIsAnyNumber) {
        if (valueSmi < 0) goto IfLessThanZero;
      } else {
        assert(valueSmi >= 0);
      }
      const value: uintptr = Unsigned(Convert<intptr>(valueSmi));
1275 1276
      // Positive Smi values definitely fit into both [0, kMaxSafeInteger] and
      // [0, kMaxUintPtr] ranges.
1277
      return value;
1278
    }
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
    case (valueHeapNumber: HeapNumber): {
      assert(IsNumberNormalized(valueHeapNumber));
      const valueDouble: float64 = Convert<float64>(valueHeapNumber);
      // NaNs must be handled outside.
      assert(!Float64IsNaN(valueDouble));
      if (kMode == kModeValueIsAnyNumber) {
        if (valueDouble < 0) goto IfLessThanZero;
      } else {
        assert(valueDouble >= 0);
      }
1289

1290
      if constexpr (Is64()) {
1291 1292 1293 1294 1295 1296 1297
        // On 64-bit architectures uintptr range is bigger than safe integer
        // range.
        if (kMode == kModeValueIsAnyNumber) {
          if (valueDouble > kMaxSafeInteger) goto IfSafeIntegerOverflow;
        } else {
          assert(valueDouble <= kMaxSafeInteger);
        }
1298
      } else {
1299 1300 1301 1302 1303 1304 1305 1306
        // On 32-bit architectures uintptr range is smaller than safe integer
        // range.
        if (kMode == kModeValueIsAnyNumber ||
            kMode == kModeValueIsSafeInteger) {
          if (valueDouble > kMaxUInt32Double) goto IfUIntPtrOverflow;
        } else {
          assert(valueDouble <= kMaxUInt32Double);
        }
1307
      }
1308
      return ChangeFloat64ToUintPtr(valueDouble);
1309 1310
    }
  }
1311
}
1312

1313 1314 1315 1316 1317
@export
macro ChangeUintPtrNumberToUintPtr(value: Number): uintptr {
  try {
    return TryNumberToUintPtr(value, kModeValueIsSafeIntegerUintPtr)
        otherwise InvalidValue, InvalidValue, InvalidValue;
1318
  } label InvalidValue {
1319 1320 1321 1322
    unreachable;
  }
}

1323
@export
1324 1325 1326 1327 1328
macro ChangeSafeIntegerNumberToUintPtr(value: Number):
    uintptr labels IfUIntPtrOverflow {
  try {
    return TryNumberToUintPtr(value, kModeValueIsSafeInteger)
        otherwise InvalidValue, IfUIntPtrOverflow, InvalidValue;
1329
  } label InvalidValue {
1330 1331 1332 1333
    unreachable;
  }
}

1334 1335 1336
transitioning macro ToUintPtr(implicit context: Context)(value: JSAny):
    uintptr labels IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow {
  if (value == Undefined) return 0;
1337
  const indexNumber = ToInteger_Inline(value);
1338 1339 1340 1341
  return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
      otherwise IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow;
}

1342 1343 1344 1345 1346 1347 1348 1349 1350
// https://tc39.github.io/ecma262/#sec-toindex
// Unlike ToIndex from the spec this implementation triggers IfRangeError if
// the result is bigger than min(kMaxUIntPtr, kMaxSafeInteger).
// We can do this because all callers do a range checks against uintptr length
// anyway and throw a RangeError in case of out-of-bounds index.
@export
transitioning macro ToIndex(implicit context: Context)(value: JSAny):
    uintptr labels IfRangeError {
  if (value == Undefined) return 0;
1351
  const indexNumber = ToInteger_Inline(value);
1352 1353 1354 1355 1356 1357
  // Less than 0 case, uintptr range overflow and safe integer range overflow
  // imply IfRangeError.
  return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
      otherwise IfRangeError, IfRangeError, IfRangeError;
}

1358
transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny):
1359
    Number {
1360
  try {
1361 1362 1363 1364
    typeswitch (o) {
      case (a: JSArray): {
        return a.length;
      }
1365 1366 1367 1368
      case (a: JSStrictArgumentsObject): {
        goto ToLength(a.length);
      }
      case (a: JSSloppyArgumentsObject): {
1369
        goto ToLength(a.length);
1370
      }
1371
      case (JSAny): deferred {
1372 1373 1374
        goto ToLength(GetProperty(o, kLengthString));
      }
    }
1375
  } label ToLength(length: JSAny) deferred {
1376
    return ToLength_Inline(length);
1377 1378
  }
}
1379

1380
transitioning macro GetMethod(implicit context: Context)(
1381 1382
    o: JSAny, name: AnyName): Callable labels IfNullOrUndefined,
    IfMethodNotCallable(JSAny) {
1383
  const value = GetProperty(o, name);
1384 1385
  // TODO(v8:9933): Consider checking for null/undefined after checking for
  // callable because the latter seems to be more common.
1386 1387
  if (value == Undefined || value == Null) goto IfNullOrUndefined;
  return Cast<Callable>(value)
1388 1389 1390 1391 1392 1393 1394
      otherwise goto IfMethodNotCallable(value);
}

transitioning macro GetMethod(implicit context: Context)(
    o: JSAny, name: String): Callable labels IfNullOrUndefined {
  try {
    return GetMethod(o, name) otherwise IfNullOrUndefined, IfMethodNotCallable;
1395
  } label IfMethodNotCallable(value: JSAny) deferred {
1396
    ThrowTypeError(MessageTemplate::kPropertyNotFunction, value, name, o);
1397 1398 1399 1400 1401 1402
  }
}

transitioning macro GetMethod(implicit context: Context)(
    o: JSAny, name: constexpr string): Callable labels IfNullOrUndefined {
  return GetMethod(o, StringConstant(name)) otherwise IfNullOrUndefined;
1403 1404
}

1405 1406 1407 1408 1409
transitioning macro GetMethod(implicit context: Context)(
    o: JSAny, symbol: Symbol): Callable labels IfNullOrUndefined {
  const value = GetProperty(o, symbol);
  if (value == Undefined || value == Null) goto IfNullOrUndefined;
  return Cast<Callable>(value)
1410 1411
      otherwise ThrowTypeError(
      MessageTemplate::kPropertyNotFunction, value, symbol, o);
1412 1413
}

1414
extern macro IsOneByteStringInstanceType(InstanceType): bool;
1415 1416 1417 1418 1419

// After converting an index to an integer, calculate a relative index:
// return index < 0 ? max(length + index, 0) : min(index, length)
@export
transitioning macro ConvertToRelativeIndex(implicit context: Context)(
1420
    index: JSAny, length: uintptr): uintptr {
1421
  const indexNumber: Number = ToInteger_Inline(index);
1422 1423 1424 1425 1426 1427
  return ConvertToRelativeIndex(indexNumber, length);
}

// Calculate a relative index:
// return index < 0 ? max(length + index, 0) : min(index, length)
@export
1428
macro ConvertToRelativeIndex(indexNumber: Number, length: uintptr): uintptr {
1429 1430 1431 1432 1433 1434
  typeswitch (indexNumber) {
    case (indexSmi: Smi): {
      const indexIntPtr: intptr = Convert<intptr>(indexSmi);
      // The logic is implemented using unsigned types.
      if (indexIntPtr < 0) {
        const relativeIndex: uintptr = Unsigned(indexIntPtr) + length;
1435
        return relativeIndex < length ? relativeIndex : 0;
1436 1437 1438

      } else {
        const relativeIndex: uintptr = Unsigned(indexIntPtr);
1439
        return relativeIndex < length ? relativeIndex : length;
1440 1441 1442
      }
    }
    case (indexHeapNumber: HeapNumber): {
1443
      assert(IsNumberNormalized(indexHeapNumber));
1444 1445 1446
      const indexDouble: float64 = Convert<float64>(indexHeapNumber);
      // NaNs must already be handled by ConvertToRelativeIndex() version
      // above accepting JSAny indices.
1447
      assert(!Float64IsNaN(indexDouble));
1448 1449 1450 1451
      const lengthDouble: float64 = Convert<float64>(length);
      assert(lengthDouble <= kMaxSafeInteger);
      if (indexDouble < 0) {
        const relativeIndex: float64 = lengthDouble + indexDouble;
1452
        return relativeIndex > 0 ? ChangeFloat64ToUintPtr(relativeIndex) : 0;
1453 1454

      } else {
1455 1456
        return ChangeFloat64ToUintPtr(
            indexDouble < lengthDouble ? indexDouble : lengthDouble);
1457 1458 1459 1460
      }
    }
  }
}
1461

1462 1463 1464 1465 1466 1467
// After converting an index to a signed integer, clamps it to the provided
// range [0, limit]:
// return min(max(index, 0), limit)
@export
transitioning macro ClampToIndexRange(implicit context: Context)(
    index: JSAny, limit: uintptr): uintptr {
1468
  const indexNumber: Number = ToInteger_Inline(index);
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
  return ClampToIndexRange(indexNumber, limit);
}

// Clamps given signed indexNumber to the provided range [0, limit]:
// return min(max(index, 0), limit)
@export
macro ClampToIndexRange(indexNumber: Number, limit: uintptr): uintptr {
  typeswitch (indexNumber) {
    case (indexSmi: Smi): {
      if (indexSmi < 0) return 0;
      const index: uintptr = Unsigned(Convert<intptr>(indexSmi));
      if (index >= limit) return limit;
      return index;
    }
    case (indexHeapNumber: HeapNumber): {
1484
      assert(IsNumberNormalized(indexHeapNumber));
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
      const indexDouble: float64 = Convert<float64>(indexHeapNumber);
      // NaNs must already be handled by ClampToIndexRange() version
      // above accepting JSAny indices.
      assert(!Float64IsNaN(indexDouble));
      if (indexDouble <= 0) return 0;

      const maxIndexDouble: float64 = Convert<float64>(limit);
      assert(maxIndexDouble <= kMaxSafeInteger);
      if (indexDouble >= maxIndexDouble) return limit;

      return ChangeFloat64ToUintPtr(indexDouble);
    }
  }
}

1500
extern builtin ObjectToString(Context, JSAny): String;
1501
extern builtin StringRepeat(Context, String, Number): String;
1502

1503
@export
1504
struct KeyValuePair {
1505 1506
  key: JSAny;
  value: JSAny;
1507
}
1508 1509 1510

// Macro definitions for compatibility that expose functionality to the CSA
// using "legacy" APIs. In Torque code, these should not be used.
1511
@export
1512
macro IsFastJSArray(o: Object, context: Context): bool {
1513 1514 1515
  // Long-term, it's likely not a good idea to have this slow-path test here,
  // since it fundamentally breaks the type system.
  if (IsForceSlowPath()) return false;
1516 1517 1518
  return Is<FastJSArray>(o);
}

1519 1520 1521
@export
macro BranchIfFastJSArray(o: Object, context: Context): never labels True,
    False {
1522 1523 1524 1525 1526
  if (IsFastJSArray(o, context)) {
    goto True;
  } else {
    goto False;
  }
1527 1528
}

1529 1530 1531
@export
macro BranchIfFastJSArrayForRead(o: Object, context: Context):
    never labels True, False {
1532 1533
  // Long-term, it's likely not a good idea to have this slow-path test here,
  // since it fundamentally breaks the type system.
1534 1535 1536 1537 1538 1539
  if (IsForceSlowPath()) goto False;
  if (Is<FastJSArrayForRead>(o)) {
    goto True;
  } else {
    goto False;
  }
1540 1541
}

1542
@export
1543 1544 1545
macro IsFastJSArrayWithNoCustomIteration(context: Context, o: Object): bool {
  return Is<FastJSArrayWithNoCustomIteration>(o);
}
1546

1547 1548 1549 1550 1551 1552
@export
macro IsFastJSArrayForReadWithNoCustomIteration(context: Context, o: Object):
    bool {
  return Is<FastJSArrayForReadWithNoCustomIteration>(o);
}

1553
extern transitioning runtime
1554
CreateDataProperty(implicit context: Context)(JSReceiver, JSAny, JSAny);
1555

1556 1557 1558
extern transitioning runtime SetOwnPropertyIgnoreAttributes(
    implicit context: Context)(JSObject, String, JSAny, Smi);

1559
namespace runtime {
1560 1561
extern runtime
GetDerivedMap(Context, JSFunction, JSReceiver): Map;
1562
}
1563
extern macro IsDeprecatedMap(Map): bool;
1564

1565
transitioning builtin FastCreateDataProperty(implicit context: Context)(
1566
    receiver: JSReceiver, key: JSAny, value: JSAny): Object {
1567
  try {
1568
    const array = Cast<FastJSArray>(receiver) otherwise Slow;
1569 1570 1571
    const index: Smi = Cast<Smi>(key) otherwise goto Slow;
    if (index < 0 || index > array.length) goto Slow;
    const isAppend = index == array.length;
1572 1573 1574 1575 1576 1577 1578 1579 1580

    if (isAppend) {
      // Fast append only works on fast elements kind and with writable length.
      const kind = EnsureArrayPushable(array.map) otherwise Slow;
      array::EnsureWriteableFastElements(array);

      // We may have to transition a.
      // For now, if transition is required, jump away to slow.
      if (IsFastSmiElementsKind(kind)) {
1581 1582
        BuildAppendJSArray(ElementsKind::HOLEY_SMI_ELEMENTS, array, value)
            otherwise Slow;
1583
      } else if (IsDoubleElementsKind(kind)) {
1584
        BuildAppendJSArray(ElementsKind::HOLEY_DOUBLE_ELEMENTS, array, value)
1585 1586
            otherwise Slow;
      } else {
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603
        assert(IsFastSmiOrTaggedElementsKind(kind));
        BuildAppendJSArray(ElementsKind::HOLEY_ELEMENTS, array, value)
            otherwise Slow;
      }
    } else {
      // Non-appending element store.
      const kind = array.map.elements_kind;
      array::EnsureWriteableFastElements(array);

      // We may have to transition a.
      // For now, if transition is required, jump away to slow.
      if (IsFastSmiElementsKind(kind)) {
        const smiValue = Cast<Smi>(value) otherwise Slow;
        const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
        elements[index] = smiValue;
      } else if (IsDoubleElementsKind(kind)) {
        const numberValue = Cast<Number>(value) otherwise Slow;
1604 1605 1606 1607
        const doubleElements = Cast<FixedDoubleArray>(array.elements)
            otherwise unreachable;
        doubleElements[index] = numberValue;
      } else {
1608
        assert(IsFastSmiOrTaggedElementsKind(kind));
1609 1610 1611 1612
        const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
        elements[index] = value;
      }
    }
1613
  } label Slow {
1614 1615 1616 1617
    CreateDataProperty(receiver, key, value);
  }
  return Undefined;
}
Shiyu Zhang's avatar
Shiyu Zhang committed
1618

1619
macro VerifiedUnreachable(): never {
1620
  static_assert(false);
1621 1622
  unreachable;
}
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649

macro Float64IsSomeInfinity(value: float64): bool {
  if (value == V8_INFINITY) {
    return true;
  }
  return value == (Convert<float64>(0) - V8_INFINITY);
}

@export
macro IsIntegerOrSomeInfinity(o: Object): bool {
  typeswitch (o) {
    case (Smi): {
      return true;
    }
    case (hn: HeapNumber): {
      if (Float64IsSomeInfinity(Convert<float64>(hn))) {
        return true;
      }
      return IsInteger(hn);
    }
    case (Object): {
      return false;
    }
  }
}

builtin CheckNumberInRange(implicit context: Context)(
1650
    value: Number, min: Number, max: Number, nodeId: Smi): Undefined {
1651 1652 1653
  if (IsIntegerOrSomeInfinity(value) && min <= value && value <= max) {
    return Undefined;
  } else {
1654
    Print('Range type assertion failed! (value/min/max/nodeId)');
1655 1656 1657
    Print(value);
    Print(min);
    Print(max);
1658
    Print(nodeId);
1659 1660 1661
    unreachable;
  }
}
1662

1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
// Assert that the objects satisfy SameValue or are both the hole.
builtin CheckSameObject(implicit context: Context)(
    lhs: Object, rhs: Object): Undefined {
  typeswitch (lhs) {
    case (TheHole): {
      if (rhs == TheHole) return Undefined;
    }
    case (a: JSAny): {
      typeswitch (rhs) {
        case (b: JSAny): {
          if (SameValue(a, b)) return Undefined;
        }
        case (Object): {
        }
      }
    }
    case (Object): {
    }
  }
  Print('Distinct or unexpected values in CheckSameObject');
  unreachable;
}

1686
macro ReplaceTheHoleWithUndefined(o: JSAny|TheHole): JSAny {
1687 1688 1689 1690 1691 1692 1693 1694 1695
  typeswitch (o) {
    case (TheHole): {
      return Undefined;
    }
    case (a: JSAny): {
      return a;
    }
  }
}
1696 1697

extern macro DecodeScopeInfoHasContextExtension(intptr): intptr;
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711

struct ConstantIterator<T: type> {
  macro Empty(): bool {
    return false;
  }
  macro Next(): T labels _NoMore {
    return this.value;
  }

  value: T;
}
macro ConstantIterator<T: type>(value: T): ConstantIterator<T> {
  return ConstantIterator{value};
}
1712 1713 1714 1715 1716 1717

extern macro FeedbackIteratorSizeFor(constexpr int32): intptr;
extern macro FeedbackIteratorMapIndexForEntry(constexpr int32): intptr;
extern macro FeedbackIteratorHandlerIndexForEntry(constexpr int32): intptr;
extern operator '[]' macro LoadWeakFixedArrayElement(
    WeakFixedArray, intptr): MaybeObject;