• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be:
3// Context found in the LICENSE file.
4
5#include 'src/builtins/builtins-regexp-gen.h'
6#include 'src/builtins/builtins-utils-gen.h'
7#include 'src/builtins/builtins.h'
8#include 'src/codegen/code-factory.h'
9#include 'src/heap/factory-inl.h'
10#include 'src/objects/arguments.h'
11#include 'src/objects/bigint.h'
12#include 'src/objects/call-site-info.h'
13#include 'src/objects/elements-kind.h'
14#include 'src/objects/free-space.h'
15#include 'src/objects/js-function.h'
16#include 'src/objects/js-generator.h'
17#include 'src/objects/js-promise.h'
18#include 'src/objects/js-regexp-string-iterator.h'
19#include 'src/objects/js-shadow-realms.h'
20#include 'src/objects/js-struct.h'
21#include 'src/objects/js-weak-refs.h'
22#include 'src/objects/objects.h'
23#include 'src/objects/source-text-module.h'
24#include 'src/objects/synthetic-module.h'
25#include 'src/objects/template-objects.h'
26#include 'src/torque/runtime-support.h'
27
28type void;
29type never;
30
31type IntegerLiteral constexpr 'IntegerLiteral';
32
33type Tagged generates 'TNode<MaybeObject>' constexpr 'MaybeObject';
34type StrongTagged extends Tagged
35    generates 'TNode<Object>' constexpr 'Object';
36type Smi extends StrongTagged generates 'TNode<Smi>' constexpr 'Smi';
37type TaggedIndex extends StrongTagged
38    generates 'TNode<TaggedIndex>' constexpr 'TaggedIndex';
39// A possibly cleared weak pointer with a bit pattern that distinguishes it from
40// strong HeapObject pointers and Smi values.
41type WeakHeapObject extends Tagged;
42type Weak<T : type extends HeapObject> extends WeakHeapObject;
43
44type Object = Smi|HeapObject;
45type MaybeObject = Smi|HeapObject|WeakHeapObject;
46
47// A Smi that is greater than or equal to 0. See TaggedIsPositiveSmi.
48type PositiveSmi extends Smi;
49
50// The Smi value zero, which is often used as null for HeapObject types.
51type Zero extends PositiveSmi;
52// A tagged value represented by an all-zero bitpattern.
53type TaggedZeroPattern extends TaggedIndex;
54
55// A value with the size of Tagged which may contain arbitrary data.
56type Uninitialized extends Tagged;
57
58extern macro MakeWeak(HeapObject): WeakHeapObject;
59extern macro GetHeapObjectAssumeWeak(MaybeObject): HeapObject labels IfCleared;
60extern macro GetHeapObjectIfStrong(MaybeObject): HeapObject labels IfNotStrong;
61extern macro IsWeakOrCleared(MaybeObject): bool;
62extern macro IsWeakReferenceToObject(MaybeObject, Object): bool;
63extern macro IsStrong(MaybeObject): bool;
64
65macro StrongToWeak<T: type>(x: T): Weak<T> {
66  return %RawDownCast<Weak<T>>(MakeWeak(x));
67}
68macro WeakToStrong<T: type>(x: Weak<T>): T labels ClearedWeakPointer {
69  const x = GetHeapObjectAssumeWeak(x) otherwise ClearedWeakPointer;
70  return %RawDownCast<T>(x);
71}
72
73// Defined to coincide with https://tc39.es/ecma262/#sec-ispropertykey
74// Doesn't include PrivateSymbol.
75type PropertyKey = String|PublicSymbol;
76
77// TODO(turbofan): PrivateSymbol is only exposed to JavaScript through the
78// debugger API. We should reconsider this and try not to expose it at all. Then
79// JSAny would not need to contain it.
80
81// A JavaScript primitive value as defined in
82// https://tc39.es/ecma262/#sec-primitive-value.
83type JSPrimitive = Numeric|String|Symbol|Boolean|Null|Undefined;
84
85// A user-exposed JavaScript value, as opposed to V8-internal values like
86// TheHole or FixedArray.
87type JSAny = JSReceiver|JSPrimitive;
88
89type JSAnyNotNumeric = String|Symbol|Boolean|Null|Undefined|JSReceiver;
90type JSAnyNotNumber = BigInt|JSAnyNotNumeric;
91
92// This is the intersection of JSAny and HeapObject.
93type JSAnyNotSmi = JSAnyNotNumber|HeapNumber;
94
95type int32 generates 'TNode<Int32T>' constexpr 'int32_t';
96type uint32 generates 'TNode<Uint32T>' constexpr 'uint32_t';
97type int31 extends int32
98    generates 'TNode<Int32T>' constexpr 'int31_t';
99type uint31 extends uint32
100    generates 'TNode<Uint32T>' constexpr 'uint32_t';
101type int16 extends int31
102    generates 'TNode<Int16T>' constexpr 'int16_t';
103type uint16 extends uint31
104    generates 'TNode<Uint16T>' constexpr 'uint16_t';
105type int8 extends int16 generates 'TNode<Int8T>' constexpr 'int8_t';
106type uint8 extends uint16
107    generates 'TNode<Uint8T>' constexpr 'uint8_t';
108type char8 extends uint8 constexpr 'char';
109type char16 extends uint16 constexpr 'char16_t';
110type int64 generates 'TNode<Int64T>' constexpr 'int64_t';
111type uint64 generates 'TNode<Uint64T>' constexpr 'uint64_t';
112type intptr generates 'TNode<IntPtrT>' constexpr 'intptr_t';
113type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t';
114type float32 generates 'TNode<Float32T>' constexpr 'float';
115type float64 generates 'TNode<Float64T>' constexpr 'double';
116type bool generates 'TNode<BoolT>' constexpr 'bool';
117type bint generates 'TNode<BInt>' constexpr 'BInt';
118type string constexpr 'const char*';
119
120type Simd128 generates 'TNode<Simd128T>';
121type I8X16 extends Simd128 generates 'TNode<I8x16T>';
122
123// Represents a std::function which produces the generated TNode type of T.
124// Useful for passing values to and from CSA code that uses LazyNode<T>, which
125// is a typedef for std::function<TNode<T>()>. Can be created with %MakeLazy and
126// accessed with RunLazy.
127type Lazy<T: type>;
128
129// Makes a Lazy. The first parameter is the name of a macro, which is looked up
130// in the context where %MakeLazy is called, as a workaround for the fact that
131// macros can't be used as values directly. The other parameters are saved and
132// passed to the macro when somebody runs the resulting Lazy object. Torque
133// syntax doesn't allow for arbitrary-length generic macros, but the internals
134// support any number of parameters, so if you need more parameters, feel free
135// to add additional declarations here.
136intrinsic %MakeLazy<T: type>(getter: constexpr string): Lazy<T>;
137intrinsic %MakeLazy<T: type, A1: type>(
138    getter: constexpr string, arg1: A1): Lazy<T>;
139intrinsic %MakeLazy<T: type, A1: type, A2: type>(
140    getter: constexpr string, arg1: A1, arg2: A2): Lazy<T>;
141intrinsic %MakeLazy<T: type, A1: type, A2: type, A3: type>(
142    getter: constexpr string, arg1: A1, arg2: A2, arg3: A3): Lazy<T>;
143
144// Executes a Lazy and returns the result. The CSA-side definition is a
145// template, but Torque doesn't understand how to use templates for extern
146// macros, so just add whatever overload definitions you need here.
147extern macro RunLazy(Lazy<Smi>): Smi;
148extern macro RunLazy(Lazy<JSAny>): JSAny;
149
150// A Smi value containing a bitfield struct as its integer data.
151@useParentTypeChecker type SmiTagged<T : type extends uint31> extends Smi;
152
153// WARNING: The memory representation (i.e., in class fields and arrays) of
154// float64_or_hole is just a float64 that may be the hole-representing
155// signalling NaN bit-pattern. So it's memory size is that of float64 and
156// loading and storing float64_or_hole emits special code.
157struct float64_or_hole {
158  macro Value(): float64 labels IfHole {
159    if (this.is_hole) {
160      goto IfHole;
161    }
162    return this.value;
163  }
164  macro ValueUnsafeAssumeNotHole(): float64 {
165    dcheck(!this.is_hole);
166    return this.value;
167  }
168
169  is_hole: bool;
170  value: float64;
171}
172const kDoubleHole: float64_or_hole = float64_or_hole{is_hole: true, value: 0};
173
174@doNotGenerateCast
175@abstract
176extern class JSPrototype extends JSObject generates 'TNode<JSObject>';
177@doNotGenerateCast
178extern class JSObjectPrototype extends JSPrototype
179    generates 'TNode<JSObject>';
180@doNotGenerateCast
181extern class JSRegExpPrototype extends JSPrototype
182    generates 'TNode<JSObject>';
183@doNotGenerateCast
184extern class JSPromisePrototype extends JSPrototype
185    generates 'TNode<JSObject>';
186@doNotGenerateCast
187extern class JSTypedArrayPrototype extends JSPrototype
188    generates 'TNode<JSObject>';
189@doNotGenerateCast
190extern class JSSetPrototype extends JSPrototype
191    generates 'TNode<JSObject>';
192@doNotGenerateCast
193extern class JSIteratorPrototype extends JSPrototype
194    generates 'TNode<JSObject>';
195@doNotGenerateCast
196extern class JSArrayIteratorPrototype extends JSPrototype
197    generates 'TNode<JSObject>';
198@doNotGenerateCast
199extern class JSMapIteratorPrototype extends JSPrototype
200    generates 'TNode<JSObject>';
201@doNotGenerateCast
202extern class JSSetIteratorPrototype extends JSPrototype
203    generates 'TNode<JSObject>';
204@doNotGenerateCast
205extern class JSStringIteratorPrototype extends JSPrototype
206    generates 'TNode<JSObject>';
207
208// The HashTable inheritance hierarchy doesn't actually look like this in C++
209// because it uses some class templates that we can't yet (and may never)
210// express in Torque, but this is the expected organization of instance types.
211@doNotGenerateCast
212extern class HashTable extends FixedArray generates 'TNode<FixedArray>';
213extern class OrderedHashMap extends HashTable;
214extern class OrderedHashSet extends HashTable;
215extern class OrderedNameDictionary extends HashTable;
216extern class NameToIndexHashTable extends HashTable;
217extern class RegisteredSymbolTable extends HashTable;
218extern class NameDictionary extends HashTable;
219extern class GlobalDictionary extends HashTable;
220extern class SimpleNumberDictionary extends HashTable;
221extern class EphemeronHashTable extends HashTable;
222type ObjectHashTable extends HashTable
223    generates 'TNode<ObjectHashTable>' constexpr 'ObjectHashTable';
224extern class NumberDictionary extends HashTable;
225
226type RawPtr generates 'TNode<RawPtrT>' constexpr 'Address';
227type RawPtr<To: type> extends RawPtr;
228type ExternalPointer
229    generates 'TNode<ExternalPointerT>' constexpr 'ExternalPointer_t';
230extern class Code extends HeapObject;
231type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>';
232
233type Number = Smi|HeapNumber;
234type Numeric = Number|BigInt;
235
236extern class ObjectBoilerplateDescription extends FixedArray;
237extern class ClosureFeedbackCellArray extends FixedArray;
238extern class ScriptContextTable extends FixedArray;
239
240extern class TransitionArray extends WeakFixedArray;
241
242extern operator '.length_intptr' macro LoadAndUntagWeakFixedArrayLength(
243    WeakFixedArray): intptr;
244
245type InstanceType extends uint16 constexpr 'InstanceType';
246
247type NoSharedNameSentinel extends Smi;
248
249// Specialized types. The following three type definitions don't correspond to
250// actual C++ classes, but have Is... methods that check additional constraints.
251
252// A Foreign object whose raw pointer is not allowed to be null.
253type NonNullForeign extends Foreign;
254
255// A function built with InstantiateFunction for the public API.
256type CallableApiObject extends JSObject;
257
258// A JSProxy with the callable bit set.
259type CallableJSProxy extends JSProxy;
260
261type Callable = JSFunction|JSBoundFunction|JSWrappedFunction|CallableJSProxy|
262    CallableApiObject;
263
264type WriteBarrierMode
265    generates 'TNode<Int32T>' constexpr 'WriteBarrierMode';
266
267extern enum UpdateFeedbackMode { kOptionalFeedback, kGuaranteedFeedback }
268extern operator '==' macro UpdateFeedbackModeEqual(
269    constexpr UpdateFeedbackMode, constexpr UpdateFeedbackMode): constexpr bool;
270
271extern enum CallFeedbackContent extends int32 { kTarget, kReceiver }
272
273extern enum UnicodeEncoding { UTF16, UTF32 }
274
275// Promise constants
276extern enum PromiseState extends int31 constexpr 'Promise::PromiseState' {
277  kPending,
278  kFulfilled,
279  kRejected
280}
281
282const kTaggedSize: constexpr int31 generates 'kTaggedSize';
283const kDoubleSize: constexpr int31 generates 'kDoubleSize';
284const kVariableSizeSentinel:
285    constexpr int31 generates 'kVariableSizeSentinel';
286
287const kSmiTagSize: constexpr int31 generates 'kSmiTagSize';
288const kHeapObjectTag: constexpr int31 generates 'kHeapObjectTag';
289const V8_INFINITY: constexpr float64 generates 'V8_INFINITY';
290const MINUS_V8_INFINITY: constexpr float64 generates '-V8_INFINITY';
291
292extern enum ElementsKind extends int32 {
293  NO_ELEMENTS,
294
295  PACKED_SMI_ELEMENTS,
296  HOLEY_SMI_ELEMENTS,
297  PACKED_ELEMENTS,
298  HOLEY_ELEMENTS,
299  PACKED_DOUBLE_ELEMENTS,
300  HOLEY_DOUBLE_ELEMENTS,
301  LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND,
302  DICTIONARY_ELEMENTS,
303
304  UINT8_ELEMENTS,
305  INT8_ELEMENTS,
306  UINT16_ELEMENTS,
307  INT16_ELEMENTS,
308  UINT32_ELEMENTS,
309  INT32_ELEMENTS,
310  FLOAT32_ELEMENTS,
311  FLOAT64_ELEMENTS,
312  UINT8_CLAMPED_ELEMENTS,
313  BIGUINT64_ELEMENTS,
314  BIGINT64_ELEMENTS,
315  RAB_GSAB_UINT8_ELEMENTS,
316  RAB_GSAB_INT8_ELEMENTS,
317  RAB_GSAB_UINT16_ELEMENTS,
318  RAB_GSAB_INT16_ELEMENTS,
319  RAB_GSAB_UINT32_ELEMENTS,
320  RAB_GSAB_INT32_ELEMENTS,
321  RAB_GSAB_FLOAT32_ELEMENTS,
322  RAB_GSAB_FLOAT64_ELEMENTS,
323  RAB_GSAB_UINT8_CLAMPED_ELEMENTS,
324  RAB_GSAB_BIGUINT64_ELEMENTS,
325  RAB_GSAB_BIGINT64_ELEMENTS,
326  // TODO(torque): Allow duplicate enum values.
327  // FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
328  // FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
329  ...
330}
331
332const kFirstFixedTypedArrayElementsKind: constexpr ElementsKind =
333    ElementsKind::UINT8_ELEMENTS;
334const kFirstRabGsabFixedTypedArrayElementsKind: constexpr ElementsKind =
335    ElementsKind::RAB_GSAB_UINT8_ELEMENTS;
336
337extern enum AllocationFlag extends int32
338constexpr 'CodeStubAssembler::AllocationFlag' {
339  kNone,
340  kDoubleAlignment,
341  kPretenured,
342  kAllowLargeObjectAllocation
343}
344
345extern enum SlackTrackingMode
346constexpr 'CodeStubAssembler::SlackTrackingMode' {
347  kWithSlackTracking,
348  kNoSlackTracking
349}
350
351extern enum ExtractFixedArrayFlag
352constexpr 'CodeStubAssembler::ExtractFixedArrayFlag' {
353  kFixedDoubleArrays,
354  kAllFixedArrays,
355  kFixedArrays,
356  ...
357}
358
359extern enum InitializationMode
360constexpr 'CodeStubAssembler::InitializationMode' {
361  kUninitialized,
362  kInitializeToZero,
363  kInitializeToNull
364}
365
366const kBigIntMaxLength: constexpr intptr generates 'BigInt::kMaxLength';
367
368extern enum MessageTemplate {
369  kAllPromisesRejected,
370  kInvalidArrayBufferLength,
371  kInvalidArrayLength,
372  kInvalidIndex,
373  kNotConstructor,
374  kNotGeneric,
375  kCalledNonCallable,
376  kCalledOnNullOrUndefined,
377  kCannotConvertToPrimitive,
378  kProtoObjectOrNull,
379  kInvalidOffset,
380  kInvalidTypedArrayLength,
381  kIteratorSymbolNonCallable,
382  kIteratorValueNotAnObject,
383  kNotIterable,
384  kReduceNoInitial,
385  kFirstArgumentNotRegExp,
386  kBigIntMixedTypes,
387  kTypedArrayTooShort,
388  kTypedArrayTooLargeToSort,
389  kInvalidCountValue,
390  kConstructorNotFunction,
391  kSymbolToString,
392  kPropertyNotFunction,
393  kBigIntTooBig,
394  kNotTypedArray,
395  kDetachedOperation,
396  kBadSortComparisonFunction,
397  kIncompatibleMethodReceiver,
398  kInvalidDataViewAccessorOffset,
399  kTypedArraySetOffsetOutOfBounds,
400  kInvalidArgument,
401  kInvalidRegExpExecResult,
402  kRegExpNonRegExp,
403  kRegExpNonObject,
404  kPromiseNonCallable,
405  kPromiseNewTargetUndefined,
406  kResolverNotAFunction,
407  kTooManyElementsInPromiseCombinator,
408  kToRadixFormatRange,
409  kCalledOnNonObject,
410  kRegExpGlobalInvokedOnNonGlobal,
411  kProxyNonObject,
412  kProxyRevoked,
413  kProxyTrapReturnedFalsishFor,
414  kProxyPrivate,
415  kProxyIsExtensibleInconsistent,
416  kProxyPreventExtensionsExtensible,
417  kProxyTrapReturnedFalsish,
418  kProxyGetPrototypeOfInvalid,
419  kProxyGetPrototypeOfNonExtensible,
420  kProxySetPrototypeOfNonExtensible,
421  kProxyDeletePropertyNonExtensible,
422  kUndefinedOrNullToObject,
423  kWeakRefsCleanupMustBeCallable,
424  kWasmTrapUnreachable,
425  kWasmTrapMemOutOfBounds,
426  kWasmTrapUnalignedAccess,
427  kWasmTrapDivByZero,
428  kWasmTrapDivUnrepresentable,
429  kWasmTrapRemByZero,
430  kWasmTrapFloatUnrepresentable,
431  kWasmTrapFuncSigMismatch,
432  kWasmTrapDataSegmentOutOfBounds,
433  kWasmTrapElemSegmentDropped,
434  kWasmTrapTableOutOfBounds,
435  kWasmTrapRethrowNull,
436  kWasmTrapNullDereference,
437  kWasmTrapIllegalCast,
438  kWasmTrapArrayOutOfBounds,
439  kWasmTrapArrayTooLarge,
440  kWeakRefsRegisterTargetAndHoldingsMustNotBeSame,
441  kInvalidWeakRefsRegisterTarget,
442  kInvalidWeakRefsUnregisterToken,
443  kInvalidWeakRefsWeakRefConstructorTarget,
444  ...
445}
446
447extern enum PropertyAttributes extends int31 {
448  NONE,
449  READ_ONLY,
450  DONT_ENUM,
451  DONT_DELETE,
452  ALL_ATTRIBUTES_MASK,
453  FROZEN,
454  ...
455}
456
457const kArrayBufferMaxByteLength:
458    constexpr uintptr generates 'JSArrayBuffer::kMaxByteLength';
459const kTypedArrayMaxLength:
460    constexpr uintptr generates 'JSTypedArray::kMaxLength';
461const kMaxTypedArrayInHeap:
462    constexpr int31 generates 'JSTypedArray::kMaxSizeInHeap';
463// CSA does not support 64-bit types on 32-bit platforms so as a workaround the
464// kMaxSafeIntegerUint64 is defined as uintptr and allowed to be used only
465// inside if constexpr (Is64()) i.e. on 64-bit architectures.
466const kMaxSafeIntegerUint64: constexpr uintptr
467    generates 'CodeStubAssembler::MaxSafeIntegerUintPtr()';
468const kMaxSafeInteger: constexpr float64 generates 'kMaxSafeInteger';
469const kMaxUInt32Double: constexpr float64 generates 'kMaxUInt32Double';
470const kSmiMaxValue: constexpr uintptr generates 'kSmiMaxValue';
471const kSmiMax: uintptr = kSmiMaxValue;
472// TODO(v8:8996): Use uintptr version instead and drop this one.
473const kStringMaxLength: constexpr int31 generates 'String::kMaxLength';
474const kStringMaxLengthUintptr:
475    constexpr uintptr generates 'String::kMaxLength';
476const kFixedArrayMaxLength:
477    constexpr int31 generates 'FixedArray::kMaxLength';
478const kFixedDoubleArrayMaxLength:
479    constexpr int31 generates 'FixedDoubleArray::kMaxLength';
480const kObjectAlignmentMask: constexpr intptr
481    generates 'kObjectAlignmentMask';
482const kMinAddedElementsCapacity:
483    constexpr int31 generates 'JSObject::kMinAddedElementsCapacity';
484const kMaxCopyElements:
485    constexpr int31 generates 'JSArray::kMaxCopyElements';
486const kMaxRegularHeapObjectSize: constexpr int31
487    generates 'kMaxRegularHeapObjectSize';
488
489const kMaxNewSpaceFixedArrayElements: constexpr int31
490    generates 'FixedArray::kMaxRegularLength';
491
492extern enum PrimitiveType { kString, kBoolean, kSymbol, kNumber }
493
494const kNameDictionaryInitialCapacity:
495    constexpr int32 generates 'NameDictionary::kInitialCapacity';
496const kSwissNameDictionaryInitialCapacity:
497    constexpr int32 generates 'SwissNameDictionary::kInitialCapacity';
498
499const kWasmArrayHeaderSize:
500    constexpr int32 generates 'WasmArray::kHeaderSize';
501
502const kHeapObjectHeaderSize:
503    constexpr int32 generates 'HeapObject::kHeaderSize';
504
505type TheHole extends Oddball;
506type Null extends Oddball;
507type Undefined extends Oddball;
508type True extends Oddball;
509type False extends Oddball;
510type Exception extends Oddball;
511type EmptyString extends String;
512type Boolean = True|False;
513
514type NumberOrUndefined = Number|Undefined;
515
516extern macro DefaultStringConstant(): String;
517extern macro EmptyStringConstant(): EmptyString;
518extern macro ErrorsStringConstant(): String;
519extern macro FalseConstant(): False;
520extern macro Int32FalseConstant(): bool;
521extern macro Int32TrueConstant(): bool;
522extern macro IteratorSymbolConstant(): PublicSymbol;
523extern macro LengthStringConstant(): String;
524extern macro MatchSymbolConstant(): Symbol;
525extern macro MessageStringConstant(): String;
526extern macro NanConstant(): NaN;
527extern macro NameStringConstant(): String;
528extern macro NullConstant(): Null;
529extern macro NumberStringConstant(): String;
530extern macro ReturnStringConstant(): String;
531extern macro SearchSymbolConstant(): Symbol;
532extern macro StringStringConstant(): String;
533extern macro TheHoleConstant(): TheHole;
534extern macro ToPrimitiveSymbolConstant(): PublicSymbol;
535extern macro ToStringStringConstant(): String;
536extern macro TrueConstant(): True;
537extern macro UndefinedConstant(): Undefined;
538extern macro ValueOfStringConstant(): String;
539extern macro WasmWrappedObjectSymbolConstant(): Symbol;
540
541const TheHole: TheHole = TheHoleConstant();
542const Null: Null = NullConstant();
543const Undefined: Undefined = UndefinedConstant();
544const True: True = TrueConstant();
545const False: False = FalseConstant();
546const kEmptyString: EmptyString = EmptyStringConstant();
547const kLengthString: String = LengthStringConstant();
548const kMessageString: String = MessageStringConstant();
549const kReturnString: String = ReturnStringConstant();
550
551const kNaN: NaN = NanConstant();
552const kZero: Zero = %RawDownCast<Zero>(SmiConstant(0));
553const kZeroBitPattern: TaggedZeroPattern = %RawDownCast<TaggedZeroPattern>(
554    Convert<Tagged>(BitcastWordToTaggedSigned(Convert<intptr>(0))));
555
556const true: constexpr bool generates 'true';
557const false: constexpr bool generates 'false';
558
559extern enum LanguageMode extends bool { kStrict, kSloppy }
560type LanguageModeSmi extends Smi;
561
562const SKIP_WRITE_BARRIER:
563    constexpr WriteBarrierMode generates 'SKIP_WRITE_BARRIER';
564const UNSAFE_SKIP_WRITE_BARRIER:
565    constexpr WriteBarrierMode generates 'UNSAFE_SKIP_WRITE_BARRIER';
566
567extern transitioning macro AllocateJSIteratorResult(implicit context: Context)(
568    JSAny, Boolean): JSObject;
569
570extern class Filler extends HeapObject generates 'TNode<HeapObject>';
571
572// Various logical subclasses of JSObject, which have their own instance types
573// but not their own class definitions:
574
575// Like JSObject, but created from API function.
576@apiExposedInstanceTypeValue(0x422)
577@doNotGenerateCast
578extern class JSApiObject extends JSObjectWithEmbedderSlots
579    generates 'TNode<JSObject>';
580
581// TODO(gsathya): This only exists to make JSApiObject instance type into a
582// range.
583@apiExposedInstanceTypeValue(0x80A)
584@doNotGenerateCast
585@highestInstanceTypeWithinParentClassRange
586extern class JSLastDummyApiObject extends JSApiObject
587    generates 'TNode<JSObject>';
588
589// Like JSApiObject, but requires access checks and/or has interceptors.
590@apiExposedInstanceTypeValue(0x410)
591extern class JSSpecialApiObject extends JSSpecialObject
592    generates 'TNode<JSSpecialObject>';
593extern class JSContextExtensionObject extends JSObject
594    generates 'TNode<JSObject>';
595extern class JSError extends JSObject generates 'TNode<JSObject>';
596
597extern macro Is64(): constexpr bool;
598
599extern macro SelectBooleanConstant(bool): Boolean;
600
601extern macro Print(constexpr string): void;
602extern macro Print(constexpr string, Object): void;
603extern macro Comment(constexpr string): void;
604extern macro Print(Object): void;
605extern macro DebugBreak(): void;
606
607// ES6 7.1.4 ToInteger ( argument )
608transitioning macro ToIntegerImpl(implicit context: Context)(input: JSAny):
609    Number {
610  let input = input;
611
612  while (true) {
613    typeswitch (input) {
614      case (s: Smi): {
615        return s;
616      }
617      case (hn: HeapNumber): {
618        let value = Convert<float64>(hn);
619        if (Float64IsNaN(value)) return SmiConstant(0);
620        value = math::Float64Trunc(value);
621        // ToInteger normalizes -0 to +0.
622        if (value == 0) return SmiConstant(0);
623        const result = ChangeFloat64ToTagged(value);
624        dcheck(IsNumberNormalized(result));
625        return result;
626      }
627      case (a: JSAnyNotNumber): {
628        input = conversion::NonNumberToNumber(a);
629      }
630    }
631  }
632  unreachable;
633}
634
635transitioning builtin ToInteger(implicit context: Context)(input: JSAny):
636    Number {
637  return ToIntegerImpl(input);
638}
639
640@export
641transitioning macro ToInteger_Inline(implicit context: Context)(input: JSAny):
642    Number {
643  typeswitch (input) {
644    case (s: Smi): {
645      return s;
646    }
647    case (JSAny): {
648      return ToInteger(input);
649    }
650  }
651}
652
653extern enum BigIntHandling extends int32
654constexpr 'CodeStubAssembler::BigIntHandling' { kConvertToNumber, kThrow }
655
656extern transitioning macro ToNumber(implicit context: Context)(
657    JSAny, constexpr BigIntHandling): Number;
658
659extern transitioning macro ToLength_Inline(implicit context: Context)(JSAny):
660    Number;
661extern transitioning macro ToNumber_Inline(implicit context: Context)(JSAny):
662    Number;
663extern transitioning macro ToString_Inline(implicit context: Context)(JSAny):
664    String;
665extern transitioning macro ToThisString(implicit context: Context)(
666    JSAny, String): String;
667extern transitioning macro ToThisValue(implicit context: Context)(
668    JSAny, constexpr PrimitiveType, constexpr string): JSAny;
669extern transitioning macro GetProperty(implicit context: Context)(
670    JSAny, JSAny): JSAny;
671extern transitioning builtin SetProperty(implicit context: Context)(
672    JSAny, JSAny, JSAny): JSAny;
673extern transitioning builtin SetPropertyIgnoreAttributes(
674    implicit context: Context)(JSObject, String, JSAny, Smi): JSAny;
675extern transitioning builtin CreateDataProperty(implicit context: Context)(
676    JSAny, JSAny, JSAny): JSAny;
677extern transitioning builtin DeleteProperty(implicit context: Context)(
678    JSAny, JSAny | PrivateSymbol, LanguageModeSmi): Boolean;
679extern transitioning builtin HasProperty(implicit context: Context)(
680    JSAny, JSAny): Boolean;
681extern transitioning macro HasProperty_Inline(implicit context: Context)(
682    JSReceiver, JSAny): Boolean;
683extern builtin LoadIC(
684    Context, JSAny, JSAny, TaggedIndex, FeedbackVector): JSAny;
685
686extern macro SetPropertyStrict(Context, Object, Object, Object): Object;
687
688extern macro ThrowRangeError(implicit context: Context)(
689    constexpr MessageTemplate): never;
690extern macro ThrowRangeError(implicit context: Context)(
691    constexpr MessageTemplate, Object): never;
692extern macro ThrowTypeError(implicit context: Context)(
693    constexpr MessageTemplate): never;
694extern macro ThrowTypeError(implicit context: Context)(
695    constexpr MessageTemplate, constexpr string): never;
696extern macro ThrowTypeError(implicit context: Context)(
697    constexpr MessageTemplate, Object): never;
698extern macro ThrowTypeError(implicit context: Context)(
699    constexpr MessageTemplate, Object, Object): never;
700extern macro ThrowTypeError(implicit context: Context)(
701    constexpr MessageTemplate, Object, Object, Object): never;
702extern transitioning runtime ThrowTypeErrorIfStrict(implicit context: Context)(
703    Smi, Object, Object): void;
704extern transitioning runtime ThrowIteratorError(implicit context: Context)(
705    JSAny): never;
706extern transitioning runtime ThrowCalledNonCallable(implicit context: Context)(
707    JSAny): never;
708
709extern transitioning macro ThrowIfNotJSReceiver(implicit context: Context)(
710    JSAny, constexpr MessageTemplate, constexpr string): void;
711
712extern macro ArraySpeciesCreate(Context, JSAny, Number): JSReceiver;
713extern macro ArrayCreate(implicit context: Context)(Number): JSArray;
714extern macro BuildAppendJSArray(
715    constexpr ElementsKind, FastJSArray, JSAny): void labels Bailout;
716
717extern macro EnsureArrayPushable(implicit context: Context)(Map): ElementsKind
718    labels Bailout;
719// TODO: Reduce duplication once varargs are supported in macros.
720extern macro Construct(implicit context: Context)(Constructor): JSReceiver;
721extern macro Construct(implicit context: Context)(
722    Constructor, JSAny): JSReceiver;
723extern macro Construct(implicit context: Context)(
724    Constructor, JSAny, JSAny): JSReceiver;
725extern macro Construct(implicit context: Context)(
726    Constructor, JSAny, JSAny, JSAny): JSReceiver;
727extern macro ConstructWithTarget(implicit context: Context)(
728    Constructor, JSReceiver): JSReceiver;
729extern macro ConstructWithTarget(implicit context: Context)(
730    Constructor, JSReceiver, JSAny): JSReceiver;
731extern macro SpeciesConstructor(implicit context: Context)(
732    JSAny, JSReceiver): JSReceiver;
733
734extern macro ConstructorBuiltinsAssembler::IsDictionaryMap(Map): bool;
735extern macro CodeStubAssembler::AllocateNameDictionary(constexpr int32):
736    NameDictionary;
737extern macro CodeStubAssembler::AllocateOrderedNameDictionary(constexpr int32):
738    OrderedNameDictionary;
739extern macro CodeStubAssembler::AllocateSwissNameDictionary(constexpr int32):
740    SwissNameDictionary;
741
742extern builtin ToObject(Context, JSAny): JSReceiver;
743extern macro ToObject_Inline(Context, JSAny): JSReceiver;
744extern macro IsUndefined(Object): bool;
745extern macro IsNullOrUndefined(Object): bool;
746extern macro IsString(HeapObject): bool;
747extern transitioning builtin NonPrimitiveToPrimitive_String(
748    Context, JSAny): JSPrimitive;
749extern transitioning builtin NonPrimitiveToPrimitive_Default(
750    Context, JSAny): JSPrimitive;
751
752transitioning macro ToPrimitiveDefault(implicit context: Context)(v: JSAny):
753    JSPrimitive {
754  typeswitch (v) {
755    case (v: JSReceiver): {
756      return NonPrimitiveToPrimitive_Default(context, v);
757    }
758    case (v: JSPrimitive): {
759      return v;
760    }
761  }
762}
763
764extern transitioning runtime NormalizeElements(Context, JSObject): void;
765extern transitioning runtime TransitionElementsKindWithKind(
766    Context, JSObject, Smi): void;
767
768extern macro LoadBufferObject(RawPtr, constexpr int32): Object;
769extern macro LoadBufferPointer(RawPtr, constexpr int32): RawPtr;
770extern macro LoadBufferSmi(RawPtr, constexpr int32): Smi;
771extern macro LoadBufferIntptr(RawPtr, constexpr int32): intptr;
772
773extern runtime StringEqual(Context, String, String): Oddball;
774extern builtin StringLessThan(Context, String, String): Boolean;
775extern macro StringCharCodeAt(String, uintptr): char16;
776extern macro StringFromSingleCharCode(char8): String;
777extern macro StringFromSingleCharCode(char16): String;
778
779extern macro NumberToString(Number): String;
780extern macro StringToNumber(String): Number;
781extern transitioning macro NonNumberToNumber(implicit context: Context)(
782    JSAnyNotNumber): Number;
783extern transitioning macro NonNumberToNumeric(implicit context: Context)(
784    JSAnyNotNumber): Numeric;
785
786extern macro Equal(JSAny, JSAny, Context): Boolean;
787macro Equal(implicit context: Context)(left: JSAny, right: JSAny): Boolean {
788  return Equal(left, right);
789}
790
791extern macro StrictEqual(JSAny, JSAny): Boolean;
792extern macro SmiLexicographicCompare(Smi, Smi): Smi;
793
794extern runtime ReThrowWithMessage(
795    Context, JSAny, TheHole | JSMessageObject): never;
796extern runtime Throw(implicit context: Context)(JSAny): never;
797extern runtime ThrowInvalidStringLength(Context): never;
798
799extern operator '==' macro WordEqual(RawPtr, RawPtr): bool;
800extern operator '!=' macro WordNotEqual(RawPtr, RawPtr): bool;
801extern operator '+' macro RawPtrAdd(RawPtr, intptr): RawPtr;
802extern operator '+' macro RawPtrAdd(intptr, RawPtr): RawPtr;
803
804extern operator '<' macro Int32LessThan(int32, int32): bool;
805extern operator '<' macro Uint32LessThan(uint32, uint32): bool;
806extern operator '>' macro Int32GreaterThan(int32, int32): bool;
807extern operator '>' macro Uint32GreaterThan(uint32, uint32): bool;
808extern operator '<=' macro Int32LessThanOrEqual(int32, int32): bool;
809extern operator '<=' macro Uint32LessThanOrEqual(uint32, uint32): bool;
810extern operator '>=' macro Int32GreaterThanOrEqual(int32, int32): bool;
811extern operator '>=' macro Uint32GreaterThanOrEqual(uint32, uint32): bool;
812
813extern operator '==' macro SmiEqual(Smi, Smi): bool;
814extern operator '!=' macro SmiNotEqual(Smi, Smi): bool;
815extern operator '<' macro SmiLessThan(Smi, Smi): bool;
816extern operator '<=' macro SmiLessThanOrEqual(Smi, Smi): bool;
817extern operator '>' macro SmiGreaterThan(Smi, Smi): bool;
818extern operator '>=' macro SmiGreaterThanOrEqual(Smi, Smi): bool;
819
820extern operator '==' macro ElementsKindEqual(
821    constexpr ElementsKind, constexpr ElementsKind): constexpr bool;
822extern operator '==' macro ElementsKindEqual(ElementsKind, ElementsKind): bool;
823operator '!=' macro ElementsKindNotEqual(
824    k1: ElementsKind, k2: ElementsKind): bool {
825  return !ElementsKindEqual(k1, k2);
826}
827extern macro IsElementsKindLessThanOrEqual(
828    ElementsKind, constexpr ElementsKind): bool;
829extern macro IsElementsKindGreaterThan(
830    ElementsKind, constexpr ElementsKind): bool;
831extern macro IsElementsKindGreaterThanOrEqual(
832    ElementsKind, constexpr ElementsKind): bool;
833extern macro IsElementsKindInRange(
834    ElementsKind, constexpr ElementsKind, constexpr ElementsKind): bool;
835
836extern macro IsFastElementsKind(constexpr ElementsKind): constexpr bool;
837extern macro IsDoubleElementsKind(constexpr ElementsKind): constexpr bool;
838
839extern macro IsFastAliasedArgumentsMap(implicit context: Context)(Map): bool;
840extern macro IsSlowAliasedArgumentsMap(implicit context: Context)(Map): bool;
841extern macro IsSloppyArgumentsMap(implicit context: Context)(Map): bool;
842extern macro IsStrictArgumentsMap(implicit context: Context)(Map): bool;
843extern macro IsTuple2Map(Map): bool;
844
845extern macro SmiAbove(Smi, Smi): bool;
846
847extern operator '==' macro WordEqual(intptr, intptr): bool;
848extern operator '==' macro WordEqual(uintptr, uintptr): bool;
849extern operator '!=' macro WordNotEqual(intptr, intptr): bool;
850extern operator '!=' macro WordNotEqual(uintptr, uintptr): bool;
851extern operator '<' macro IntPtrLessThan(intptr, intptr): bool;
852extern operator '<' macro UintPtrLessThan(uintptr, uintptr): bool;
853extern operator '>' macro IntPtrGreaterThan(intptr, intptr): bool;
854extern operator '>' macro UintPtrGreaterThan(uintptr, uintptr): bool;
855extern operator '<=' macro IntPtrLessThanOrEqual(intptr, intptr): bool;
856extern operator '<=' macro UintPtrLessThanOrEqual(uintptr, uintptr): bool;
857extern operator '>=' macro IntPtrGreaterThanOrEqual(intptr, intptr): bool;
858extern operator '>=' macro UintPtrGreaterThanOrEqual(uintptr, uintptr): bool;
859extern operator '~' macro WordNot(intptr): intptr;
860extern operator '~' macro WordNot(uintptr): uintptr;
861extern operator '~' macro Word64Not(uint64): uint64;
862extern operator '~' macro Word64Not(int64): int64;
863extern operator '~' macro ConstexprWordNot(constexpr intptr): constexpr intptr;
864extern operator '~' macro ConstexprWordNot(constexpr uintptr):
865    constexpr uintptr;
866
867extern operator '==' macro Float64Equal(float64, float64): bool;
868extern operator '!=' macro Float64NotEqual(float64, float64): bool;
869extern operator '>' macro Float64GreaterThan(float64, float64): bool;
870extern operator '>=' macro Float64GreaterThanOrEqual(float64, float64): bool;
871extern operator '<' macro Float64LessThan(float64, float64): bool;
872extern operator '<=' macro Float64LessThanOrEqual(float64, float64): bool;
873
874extern macro BranchIfNumberEqual(Number, Number): never
875    labels Taken, NotTaken;
876operator '==' macro IsNumberEqual(a: Number, b: Number): bool {
877  BranchIfNumberEqual(a, b) otherwise return true, return false;
878}
879operator '!=' macro IsNumberNotEqual(a: Number, b: Number): bool {
880  return !(a == b);
881}
882extern macro BranchIfNumberLessThan(Number, Number): never
883    labels Taken, NotTaken;
884operator '<' macro NumberIsLessThan(a: Number, b: Number): bool {
885  BranchIfNumberLessThan(a, b) otherwise return true, return false;
886}
887extern macro BranchIfNumberLessThanOrEqual(Number, Number): never
888    labels Taken, NotTaken;
889operator '<=' macro NumberIsLessThanOrEqual(a: Number, b: Number): bool {
890  BranchIfNumberLessThanOrEqual(a, b) otherwise return true, return false;
891}
892
893operator '>' macro NumberIsGreaterThan(a: Number, b: Number): bool {
894  return b < a;
895}
896operator '>=' macro NumberIsGreaterThanOrEqual(a: Number, b: Number): bool {
897  return b <= a;
898}
899
900extern macro BranchIfFloat64IsNaN(float64): never
901    labels Taken, NotTaken;
902macro Float64IsNaN(n: float64): bool {
903  BranchIfFloat64IsNaN(n) otherwise return true, return false;
904}
905
906// The type of all tagged values that can safely be compared with TaggedEqual.
907@if(V8_ENABLE_WEBASSEMBLY)
908type TaggedWithIdentity = JSReceiver | FixedArrayBase | Oddball | Map |
909    WeakCell | Context | EmptyString | Symbol | WasmInternalFunction;
910@ifnot(V8_ENABLE_WEBASSEMBLY)
911type TaggedWithIdentity = JSReceiver | FixedArrayBase | Oddball | Map |
912    WeakCell | Context | EmptyString | Symbol;
913
914extern operator '==' macro TaggedEqual(TaggedWithIdentity, Object): bool;
915extern operator '==' macro TaggedEqual(Object, TaggedWithIdentity): bool;
916extern operator '==' macro TaggedEqual(
917    TaggedWithIdentity, TaggedWithIdentity): bool;
918extern operator '==' macro TaggedEqual(WeakHeapObject, WeakHeapObject): bool;
919extern operator '!=' macro TaggedNotEqual(TaggedWithIdentity, Object): bool;
920extern operator '!=' macro TaggedNotEqual(Object, TaggedWithIdentity): bool;
921extern operator '!=' macro TaggedNotEqual(
922    TaggedWithIdentity, TaggedWithIdentity): bool;
923extern operator '!=' macro TaggedNotEqual(WeakHeapObject, WeakHeapObject): bool;
924// Do not overload == and != if it is unclear if object identity is the right
925// equality.
926extern macro TaggedEqual(MaybeObject, MaybeObject): bool;
927extern macro TaggedNotEqual(MaybeObject, MaybeObject): bool;
928
929extern operator '+' macro SmiAdd(Smi, Smi): Smi;
930extern operator '-' macro SmiSub(Smi, Smi): Smi;
931extern operator '&' macro SmiAnd(Smi, Smi): Smi;
932extern operator '|' macro SmiOr(Smi, Smi): Smi;
933extern operator '<<' macro SmiShl(Smi, constexpr int31): Smi;
934extern operator '>>' macro SmiSar(Smi, constexpr int31): Smi;
935
936extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
937extern operator '+' macro ConstexprIntPtrAdd(
938    constexpr intptr, constexpr intptr): constexpr intptr;
939extern operator '+' macro ConstexprUintPtrAdd(
940    constexpr uintptr, constexpr uintptr): constexpr intptr;
941extern operator '+' macro Int64Add(int64, int64): int64;
942extern operator '-' macro IntPtrSub(intptr, intptr): intptr;
943extern operator '-' macro Int64Sub(int64, int64): int64;
944extern operator '*' macro IntPtrMul(intptr, intptr): intptr;
945extern operator '*' macro Int64Mul(int64, int64): int64;
946extern operator '/' macro IntPtrDiv(intptr, intptr): intptr;
947extern operator '/' macro Int64Div(int64, int64): int64;
948extern operator '<<' macro WordShl(intptr, intptr): intptr;
949extern operator '>>' macro WordSar(intptr, intptr): intptr;
950extern operator '&' macro WordAnd(intptr, intptr): intptr;
951extern operator '|' macro WordOr(intptr, intptr): intptr;
952
953extern operator '+' macro UintPtrAdd(uintptr, uintptr): uintptr;
954extern operator '+' macro Uint64Add(uint64, uint64): uint64;
955extern operator '-' macro UintPtrSub(uintptr, uintptr): uintptr;
956extern operator '-' macro Uint64Sub(uint64, uint64): uint64;
957extern operator '*' macro Uint64Mul(uint64, uint64): uint64;
958extern operator '<<' macro WordShl(uintptr, uintptr): uintptr;
959extern operator '>>>' macro WordShr(uintptr, uintptr): uintptr;
960extern operator '&' macro WordAnd(uintptr, uintptr): uintptr;
961extern operator '|' macro WordOr(uintptr, uintptr): uintptr;
962
963extern operator '+' macro Int32Add(int32, int32): int32;
964extern operator '+' macro Uint32Add(uint32, uint32): uint32;
965extern operator '+' macro ConstexprUint32Add(
966    constexpr uint32, constexpr int32): constexpr uint32;
967extern operator '+' macro ConstexprInt31Add(
968    constexpr int31, constexpr int31): constexpr int31;
969extern operator '+' macro ConstexprInt32Add(
970    constexpr int32, constexpr int32): constexpr int32;
971extern operator '*' macro ConstexprInt31Mul(
972    constexpr int31, constexpr int31): constexpr int31;
973extern operator '-' macro Int32Sub(int16, int16): int32;
974extern operator '-' macro Int32Sub(int32, int32): int32;
975extern operator '-' macro Uint32Sub(uint32, uint32): uint32;
976extern operator '*' macro Int32Mul(int32, int32): int32;
977extern operator '*' macro Uint32Mul(uint32, uint32): uint32;
978extern operator '/' macro Int32Div(int32, int32): int32;
979extern operator '%' macro Int32Mod(int32, int32): int32;
980extern operator '&' macro Word32And(int32, int32): int32;
981extern operator '&' macro Word32And(uint32, uint32): uint32;
982extern operator '==' macro
983ConstexprInt31Equal(constexpr int31, constexpr int31): constexpr bool;
984extern operator '!=' macro
985ConstexprInt31NotEqual(constexpr int31, constexpr int31): constexpr bool;
986extern operator '==' macro
987ConstexprUint32Equal(constexpr uint32, constexpr uint32): constexpr bool;
988extern operator '!=' macro
989ConstexprUint32NotEqual(constexpr uint32, constexpr uint32): constexpr bool;
990extern operator '>=' macro
991ConstexprInt31GreaterThanEqual(
992    constexpr int31, constexpr int31): constexpr bool;
993extern operator '==' macro ConstexprInt32Equal(
994    constexpr int32, constexpr int32): constexpr bool;
995extern operator '!=' macro ConstexprInt32NotEqual(
996    constexpr int32, constexpr int32): constexpr bool;
997
998// IntegerLiteral overloads
999extern macro ConstexprIntegerLiteralToInt31(constexpr IntegerLiteral):
1000    constexpr int31;
1001extern macro ConstexprIntegerLiteralToInt32(constexpr IntegerLiteral):
1002    constexpr int32;
1003extern macro ConstexprIntegerLiteralToUint32(constexpr IntegerLiteral):
1004    constexpr uint32;
1005extern macro ConstexprIntegerLiteralToUint64(constexpr IntegerLiteral):
1006    constexpr uint64;
1007extern macro ConstexprIntegerLiteralToIntptr(constexpr IntegerLiteral):
1008    constexpr intptr;
1009extern macro ConstexprIntegerLiteralToUintptr(constexpr IntegerLiteral):
1010    constexpr uintptr;
1011extern macro ConstexprIntegerLiteralToInt8(constexpr IntegerLiteral):
1012    constexpr int8;
1013extern macro ConstexprIntegerLiteralToUint8(constexpr IntegerLiteral):
1014    constexpr uint8;
1015extern macro ConstexprIntegerLiteralToFloat64(constexpr IntegerLiteral):
1016    constexpr float64;
1017
1018extern operator '==' macro ConstexprIntegerLiteralEqual(
1019    constexpr IntegerLiteral, constexpr IntegerLiteral): constexpr bool;
1020extern operator '+' macro ConstexprIntegerLiteralAdd(
1021    constexpr IntegerLiteral,
1022    constexpr IntegerLiteral): constexpr IntegerLiteral;
1023extern operator '<<' macro ConstexprIntegerLiteralLeftShift(
1024    constexpr IntegerLiteral,
1025    constexpr IntegerLiteral): constexpr IntegerLiteral;
1026extern operator '|' macro ConstexprIntegerLiteralBitwiseOr(
1027    constexpr IntegerLiteral,
1028    constexpr IntegerLiteral): constexpr IntegerLiteral;
1029
1030extern operator '==' macro Word32Equal(int32, int32): bool;
1031extern operator '==' macro Word32Equal(uint32, uint32): bool;
1032extern operator '!=' macro Word32NotEqual(int32, int32): bool;
1033extern operator '!=' macro Word32NotEqual(uint32, uint32): bool;
1034extern operator '>>>' macro Word32Shr(uint32, uint32): uint32;
1035extern operator '>>' macro Word32Sar(int32, int32): int32;
1036extern operator '<<' macro Word32Shl(int32, int32): int32;
1037extern operator '<<' macro Word32Shl(uint32, uint32): uint32;
1038extern operator '|' macro Word32Or(int32, int32): int32;
1039extern operator '|' macro Word32Or(uint32, uint32): uint32;
1040extern operator '&' macro Word32And(bool, bool): bool;
1041extern operator '|' macro Word32Or(bool, bool): bool;
1042extern operator '==' macro Word32Equal(bool, bool): bool;
1043extern operator '!=' macro Word32NotEqual(bool, bool): bool;
1044extern operator '|' macro ConstexprWord32Or(
1045    constexpr int32, constexpr int32): constexpr int32;
1046extern operator '^' macro Word32Xor(int32, int32): int32;
1047extern operator '^' macro Word32Xor(uint32, uint32): uint32;
1048extern operator '<<' macro ConstexprWord32Shl(
1049    constexpr uint32, constexpr int32): uint32;
1050
1051extern operator '==' macro Word64Equal(int64, int64): bool;
1052extern operator '==' macro Word64Equal(uint64, uint64): bool;
1053extern operator '!=' macro Word64NotEqual(int64, int64): bool;
1054extern operator '!=' macro Word64NotEqual(uint64, uint64): bool;
1055extern operator '>>>' macro Word64Shr(uint64, uint64): uint64;
1056extern operator '>>' macro Word64Sar(int64, int64): int64;
1057extern operator '<<' macro Word64Shl(int64, int64): int64;
1058extern operator '<<' macro Word64Shl(uint64, uint64): uint64;
1059extern operator '|' macro Word64Or(int64, int64): int64;
1060extern operator '|' macro Word64Or(uint64, uint64): uint64;
1061extern operator '&' macro Word64And(uint64, uint64): uint64;
1062extern operator '^' macro Word64Xor(int64, int64): int64;
1063extern operator '^' macro Word64Xor(uint64, uint64): uint64;
1064
1065extern operator '+' macro Float64Add(float64, float64): float64;
1066extern operator '-' macro Float64Sub(float64, float64): float64;
1067extern operator '*' macro Float64Mul(float64, float64): float64;
1068extern operator '/' macro Float64Div(float64, float64): float64;
1069extern operator '%' macro Float64Mod(float64, float64): float64;
1070
1071extern operator '+' macro NumberAdd(Number, Number): Number;
1072extern operator '-' macro NumberSub(Number, Number): Number;
1073extern macro NumberMin(Number, Number): Number;
1074extern macro NumberMax(Number, Number): Number;
1075macro Min(x: Number, y: Number): Number {
1076  return NumberMin(x, y);
1077}
1078macro Max(x: Number, y: Number): Number {
1079  return NumberMax(x, y);
1080}
1081
1082extern macro TryIntPtrAdd(intptr, intptr): intptr labels Overflow;
1083extern macro TryIntPtrSub(intptr, intptr): intptr labels Overflow;
1084extern macro TryInt32Mul(int32, int32): int32 labels Overflow;
1085
1086extern operator '<' macro ConstexprUintPtrLessThan(
1087    constexpr uintptr, constexpr uintptr): constexpr bool;
1088extern operator '<<' macro ConstexprUintPtrShl(
1089    constexpr uintptr, constexpr int31): constexpr uintptr;
1090extern operator '>>>' macro ConstexprUintPtrShr(
1091    constexpr uintptr, constexpr int31): constexpr uintptr;
1092
1093extern macro SmiMax(Smi, Smi): Smi;
1094extern macro SmiMin(Smi, Smi): Smi;
1095extern macro SmiMul(Smi, Smi): Number;
1096extern macro SmiMod(Smi, Smi): Number;
1097
1098extern macro IntPtrMax(intptr, intptr): intptr;
1099extern macro IntPtrMin(intptr, intptr): intptr;
1100extern macro UintPtrMin(uintptr, uintptr): uintptr;
1101
1102extern operator '!' macro ConstexprBoolNot(constexpr bool): constexpr bool;
1103extern operator '!' macro Word32BinaryNot(bool): bool;
1104extern operator '!' macro IsFalse(Boolean): bool;
1105
1106extern operator '==' macro
1107ConstexprInt31Equal(
1108    constexpr InstanceType, constexpr InstanceType): constexpr bool;
1109extern operator '-' macro ConstexprUint32Sub(
1110    constexpr InstanceType, constexpr InstanceType): constexpr int32;
1111extern operator '-' macro ConstexprInt32Sub(
1112    constexpr int32, constexpr int32): constexpr int32;
1113
1114extern operator '.instanceType' macro LoadInstanceType(HeapObject):
1115    InstanceType;
1116
1117operator '.length_uintptr' macro LoadJSArrayLengthAsUintPtr(array: JSArray):
1118    uintptr {
1119  return Convert<uintptr>(array.length);
1120}
1121
1122extern operator '.length_intptr' macro LoadStringLengthAsWord(String): intptr;
1123operator '.length_uintptr' macro LoadStringLengthAsUintPtr(s: String): uintptr {
1124  return Unsigned(s.length_intptr);
1125}
1126extern operator '.length_uint32' macro LoadStringLengthAsWord32(String): uint32;
1127extern operator '.length_smi' macro LoadStringLengthAsSmi(String): Smi;
1128
1129extern builtin StringAdd_CheckNone(implicit context: Context)(
1130    String, String): String;
1131operator '+' macro StringAdd(implicit context: Context)(
1132    a: String, b: String): String {
1133  return StringAdd_CheckNone(a, b);
1134}
1135
1136operator '==' macro PromiseStateEquals(
1137    s1: PromiseState, s2: PromiseState): bool {
1138  return Word32Equal(s1, s2);
1139}
1140
1141extern macro CountLeadingZeros64(uint64): int64;
1142extern macro CountTrailingZeros32(uint32): int32;
1143extern macro CountTrailingZeros64(uint64): int64;
1144
1145extern macro TaggedIsSmi(Object): bool;
1146extern macro TaggedIsNotSmi(Object): bool;
1147extern macro TaggedIsPositiveSmi(Object): bool;
1148extern macro IsValidPositiveSmi(intptr): bool;
1149
1150extern macro IsInteger(JSAny): bool;
1151extern macro IsInteger(HeapNumber): bool;
1152
1153extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
1154extern macro ChangeInt32ToTagged(int32): Number;
1155extern macro ChangeUint32ToTagged(uint32): Number;
1156extern macro ChangeUintPtrToFloat64(uintptr): float64;
1157extern macro ChangeUintPtrToTagged(uintptr): Number;
1158extern macro Unsigned(int64): uint64;
1159extern macro Unsigned(int32): uint32;
1160extern macro Unsigned(int16): uint16;
1161extern macro Unsigned(int8): uint8;
1162extern macro Unsigned(intptr): uintptr;
1163extern macro Unsigned(RawPtr): uintptr;
1164extern macro Signed(uint64): int64;
1165extern macro Signed(uint32): int32;
1166extern macro Signed(uint16): int16;
1167extern macro Signed(uint8): int8;
1168extern macro Signed(uintptr): intptr;
1169extern macro Signed(RawPtr): intptr;
1170extern macro TruncateIntPtrToInt32(intptr): int32;
1171extern macro TruncateInt64ToInt32(int64): int32;
1172extern macro SmiTag(intptr): Smi;
1173extern macro SmiFromInt32(int32): Smi;
1174extern macro SmiFromUint32(uint32): Smi;
1175extern macro SmiFromIntPtr(intptr): Smi;
1176extern macro SmiUntag(Smi): intptr;
1177macro SmiUntag<T: type>(value: SmiTagged<T>): T {
1178  return %RawDownCast<T>(Unsigned(SmiToInt32(Convert<Smi>(value))));
1179}
1180macro SmiTag<T : type extends uint31>(value: T): SmiTagged<T> {
1181  return %RawDownCast<SmiTagged<T>>(SmiFromUint32(value));
1182}
1183extern macro SmiToInt32(Smi): int32;
1184extern macro SmiToFloat64(Smi): float64;
1185extern macro TaggedIndexToIntPtr(TaggedIndex): intptr;
1186extern macro IntPtrToTaggedIndex(intptr): TaggedIndex;
1187extern macro TaggedIndexToSmi(TaggedIndex): Smi;
1188extern macro SmiToTaggedIndex(Smi): TaggedIndex;
1189extern macro RoundIntPtrToFloat64(intptr): float64;
1190extern macro IntPtrRoundUpToPowerOfTwo32(intptr): intptr;
1191extern macro ChangeFloat32ToFloat64(float32): float64;
1192extern macro ChangeNumberToFloat64(Number): float64;
1193extern macro ChangeNumberToUint32(Number): uint32;
1194extern macro ChangeTaggedNonSmiToInt32(implicit context: Context)(JSAnyNotSmi):
1195    int32;
1196extern macro ChangeTaggedToFloat64(implicit context: Context)(JSAny): float64;
1197extern macro ChangeFloat64ToTagged(float64): Number;
1198extern macro ChangeFloat64ToUintPtr(float64): uintptr;
1199extern macro ChangeFloat64ToIntPtr(float64): intptr;
1200extern macro ChangeBoolToInt32(bool): int32;
1201extern macro ChangeInt32ToFloat64(int32): float64;
1202extern macro ChangeInt32ToIntPtr(int32): intptr;    // Sign-extends.
1203extern macro ChangeUint32ToWord(uint32): uintptr;   // Doesn't sign-extend.
1204extern macro ChangeInt32ToInt64(int32): intptr;     // Sign-extends.
1205extern macro ChangeUint32ToUint64(uint32): uint64;  // Doesn't sign-extend.
1206extern macro LoadNativeContext(Context): NativeContext;
1207extern macro TruncateFloat64ToFloat32(float64): float32;
1208extern macro TruncateHeapNumberValueToWord32(HeapNumber): int32;
1209extern macro LoadJSArrayElementsMap(constexpr ElementsKind, NativeContext): Map;
1210extern macro LoadJSArrayElementsMap(ElementsKind, NativeContext): Map;
1211extern macro NumberConstant(constexpr float64): Number;
1212extern macro NumberConstant(constexpr int32): Number;
1213extern macro NumberConstant(constexpr uint32): Number;
1214extern macro IntPtrConstant(constexpr int31): intptr;
1215extern macro IntPtrConstant(constexpr int32): intptr;
1216extern macro Uint16Constant(constexpr uint16): uint16;
1217extern macro Int32Constant(constexpr int31): int31;
1218extern macro Int32Constant(constexpr int32): int32;
1219macro Int32Constant(i: constexpr IntegerLiteral): int32 {
1220  return Int32Constant(ConstexprIntegerLiteralToInt32(i));
1221}
1222extern macro Int64Constant(constexpr int64): int64;
1223extern macro Uint64Constant(constexpr uint64): uint64;
1224extern macro Float64Constant(constexpr int32): float64;
1225extern macro Float64Constant(constexpr float64): float64;
1226extern macro Float64Constant(constexpr IntegerLiteral): float64;
1227extern macro SmiConstant(constexpr int31): Smi;
1228extern macro SmiConstant(constexpr Smi): Smi;
1229extern macro SmiConstant(constexpr MessageTemplate): Smi;
1230extern macro SmiConstant(constexpr bool): Smi;
1231extern macro SmiConstant(constexpr uint32): Smi;
1232macro SmiConstant(il: constexpr IntegerLiteral): Smi {
1233  return SmiConstant(ConstexprIntegerLiteralToInt31(il));
1234}
1235extern macro BoolConstant(constexpr bool): bool;
1236extern macro StringConstant(constexpr string): String;
1237extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot;
1238extern macro IntPtrConstant(constexpr intptr): intptr;
1239macro IntPtrConstant(il: constexpr IntegerLiteral): intptr {
1240  return IntPtrConstant(ConstexprIntegerLiteralToIntptr(il));
1241}
1242extern macro PointerConstant(constexpr RawPtr): RawPtr;
1243extern macro SingleCharacterStringConstant(constexpr string): String;
1244extern macro Float64SilenceNaN(float64): float64;
1245
1246extern macro BitcastWordToTaggedSigned(intptr): Smi;
1247extern macro BitcastWordToTaggedSigned(uintptr): Smi;
1248extern macro BitcastWordToTagged(intptr): Object;
1249extern macro BitcastWordToTagged(uintptr): Object;
1250extern macro BitcastTaggedToWord(Object): intptr;
1251extern macro BitcastTaggedToWordForTagAndSmiBits(Tagged): intptr;
1252
1253extern macro FixedArrayMapConstant(): Map;
1254extern macro FixedDoubleArrayMapConstant(): Map;
1255extern macro FixedCOWArrayMapConstant(): Map;
1256extern macro EmptyByteArrayConstant(): ByteArray;
1257extern macro EmptyFixedArrayConstant(): EmptyFixedArray;
1258extern macro PromiseCapabilityMapConstant(): Map;
1259extern macro OneByteStringMapConstant(): Map;
1260extern macro StringMapConstant(): Map;
1261
1262const kFixedArrayMap: Map = FixedArrayMapConstant();
1263const kFixedDoubleArrayMap: Map = FixedDoubleArrayMapConstant();
1264const kCOWMap: Map = FixedCOWArrayMapConstant();
1265const kEmptyByteArray: ByteArray = EmptyByteArrayConstant();
1266const kEmptyFixedArray: EmptyFixedArray = EmptyFixedArrayConstant();
1267const kPromiseCapabilityMap: Map = PromiseCapabilityMapConstant();
1268// The map of a non-internalized internal SeqOneByteString.
1269const kOneByteStringMap: Map = OneByteStringMapConstant();
1270// The map of a non-internalized internal SeqTwoByteString.
1271const kStringMap: Map = StringMapConstant();
1272
1273macro OutOfBounds<T: type, X: type>(index: T, length: X): bool {
1274  return UintPtrGreaterThanOrEqual(
1275      Convert<uintptr>(Convert<intptr>(index)),
1276      Convert<uintptr>(Convert<intptr>(length)));
1277}
1278
1279extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
1280    bool;
1281extern macro IsNoElementsProtectorCellInvalid(): bool;
1282extern macro IsArrayIteratorProtectorCellInvalid(): bool;
1283extern macro IsArraySpeciesProtectorCellInvalid(): bool;
1284extern macro IsIsConcatSpreadableProtectorCellInvalid(): bool;
1285extern macro IsTypedArraySpeciesProtectorCellInvalid(): bool;
1286extern macro IsPromiseSpeciesProtectorCellInvalid(): bool;
1287extern macro IsMockArrayBufferAllocatorFlag(): bool;
1288extern macro HasBuiltinSubclassingFlag(): bool;
1289extern macro IsPrototypeTypedArrayPrototype(implicit context: Context)(Map):
1290    bool;
1291
1292extern operator '.data_ptr' macro LoadJSTypedArrayDataPtr(JSTypedArray): RawPtr;
1293
1294extern operator '.elements_kind' macro LoadMapElementsKind(Map): ElementsKind;
1295extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray):
1296    ElementsKind;
1297
1298extern operator '.length' macro LoadFastJSArrayLength(FastJSArray): Smi;
1299operator '.length=' macro StoreFastJSArrayLength(
1300    array: FastJSArray, length: Smi): void {
1301  const array: JSArray = array;
1302  array.length = length;
1303}
1304
1305extern macro GetNumberDictionaryNumberOfElements(NumberDictionary): Smi;
1306
1307extern macro LoadConstructorOrBackPointer(Map): Object;
1308
1309extern macro BasicLoadNumberDictionaryElement(NumberDictionary, intptr): JSAny
1310    labels NotData, IfHole;
1311
1312extern macro IsFastElementsKind(ElementsKind): bool;
1313extern macro IsDoubleElementsKind(ElementsKind): bool;
1314extern macro IsFastSmiOrTaggedElementsKind(ElementsKind): bool;
1315extern macro IsFastSmiElementsKind(ElementsKind): bool;
1316extern macro IsHoleyFastElementsKind(ElementsKind): bool;
1317
1318macro FastHoleyElementsKind(kind: ElementsKind): ElementsKind {
1319  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
1320    return ElementsKind::HOLEY_SMI_ELEMENTS;
1321  } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) {
1322    return ElementsKind::HOLEY_DOUBLE_ELEMENTS;
1323  }
1324  dcheck(kind == ElementsKind::PACKED_ELEMENTS);
1325  return ElementsKind::HOLEY_ELEMENTS;
1326}
1327
1328macro AllowDoubleElements(kind: ElementsKind): ElementsKind {
1329  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
1330    return ElementsKind::PACKED_DOUBLE_ELEMENTS;
1331  } else if (kind == ElementsKind::HOLEY_SMI_ELEMENTS) {
1332    return ElementsKind::HOLEY_DOUBLE_ELEMENTS;
1333  }
1334  return kind;
1335}
1336
1337macro AllowNonNumberElements(kind: ElementsKind): ElementsKind {
1338  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
1339    return ElementsKind::PACKED_ELEMENTS;
1340  } else if (kind == ElementsKind::HOLEY_SMI_ELEMENTS) {
1341    return ElementsKind::HOLEY_ELEMENTS;
1342  } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) {
1343    return ElementsKind::PACKED_ELEMENTS;
1344  } else if (kind == ElementsKind::HOLEY_DOUBLE_ELEMENTS) {
1345    return ElementsKind::HOLEY_ELEMENTS;
1346  }
1347  return kind;
1348}
1349
1350macro GetObjectFunction(implicit context: Context)(): JSFunction {
1351  return *NativeContextSlot(ContextSlot::OBJECT_FUNCTION_INDEX);
1352}
1353macro GetArrayFunction(implicit context: Context)(): JSFunction {
1354  return *NativeContextSlot(ContextSlot::ARRAY_FUNCTION_INDEX);
1355}
1356macro GetArrayBufferFunction(implicit context: Context)(): Constructor {
1357  return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_FUN_INDEX);
1358}
1359macro GetArrayBufferNoInitFunction(implicit context: Context)(): JSFunction {
1360  return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_NOINIT_FUN_INDEX);
1361}
1362macro GetFastPackedElementsJSArrayMap(implicit context: Context)(): Map {
1363  return *NativeContextSlot(ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
1364}
1365macro GetFastPackedSmiElementsJSArrayMap(implicit context: Context)(): Map {
1366  return *NativeContextSlot(
1367      ContextSlot::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX);
1368}
1369macro GetProxyRevocableResultMap(implicit context: Context)(): Map {
1370  return *NativeContextSlot(ContextSlot::PROXY_REVOCABLE_RESULT_MAP_INDEX);
1371}
1372macro GetIteratorResultMap(implicit context: Context)(): Map {
1373  return *NativeContextSlot(ContextSlot::ITERATOR_RESULT_MAP_INDEX);
1374}
1375macro GetInitialStringIteratorMap(implicit context: Context)(): Map {
1376  return *NativeContextSlot(ContextSlot::INITIAL_STRING_ITERATOR_MAP_INDEX);
1377}
1378macro GetReflectApply(implicit context: Context)(): Callable {
1379  return *NativeContextSlot(ContextSlot::REFLECT_APPLY_INDEX);
1380}
1381macro GetRegExpLastMatchInfo(implicit context: Context)(): RegExpMatchInfo {
1382  return *NativeContextSlot(ContextSlot::REGEXP_LAST_MATCH_INFO_INDEX);
1383}
1384macro GetStrictArgumentsMap(implicit context: Context)(): Map {
1385  return *NativeContextSlot(ContextSlot::STRICT_ARGUMENTS_MAP_INDEX);
1386}
1387macro GetSloppyArgumentsMap(implicit context: Context)(): Map {
1388  return *NativeContextSlot(ContextSlot::SLOPPY_ARGUMENTS_MAP_INDEX);
1389}
1390macro GetFastAliasedArgumentsMap(implicit context: Context)(): Map {
1391  return *NativeContextSlot(ContextSlot::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
1392}
1393macro GetWeakCellMap(implicit context: Context)(): Map {
1394  return %GetClassMapConstant<WeakCell>();
1395}
1396macro GetPrototypeApplyFunction(implicit context: Context)(): JSFunction {
1397  return *NativeContextSlot(ContextSlot::FUNCTION_PROTOTYPE_APPLY_INDEX);
1398}
1399
1400// Call(Context, Target, Receiver, ...Args)
1401// TODO(joshualitt): Assuming the context parameter is for throwing when Target
1402//                   is non-callable, then we should make it an implicit
1403//                   parameter.
1404extern transitioning macro Call(Context, JSAny, JSAny): JSAny;
1405extern transitioning macro Call(Context, JSAny, JSAny, JSAny): JSAny;
1406extern transitioning macro Call(Context, JSAny, JSAny, JSAny, JSAny): JSAny;
1407extern transitioning macro Call(
1408    Context, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1409extern transitioning macro Call(
1410    Context, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1411extern transitioning macro Call(
1412    Context, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1413
1414extern macro TransitionElementsKind(
1415    JSObject, Map, constexpr ElementsKind,
1416    constexpr ElementsKind): void labels Bailout;
1417extern macro PerformStackCheck(implicit context: Context)(): void;
1418
1419extern macro Typeof(JSAny): String;
1420
1421// Return true iff number is NaN.
1422macro NumberIsNaN(number: Number): bool {
1423  typeswitch (number) {
1424    case (Smi): {
1425      return false;
1426    }
1427    case (hn: HeapNumber): {
1428      const value: float64 = Convert<float64>(hn);
1429      return value != value;
1430    }
1431  }
1432}
1433
1434extern macro GotoIfForceSlowPath(): void labels Taken;
1435macro IsForceSlowPath(): bool {
1436  GotoIfForceSlowPath() otherwise return true;
1437  return false;
1438}
1439
1440extern macro BranchIfToBooleanIsTrue(JSAny): never
1441    labels Taken, NotTaken;
1442extern macro BranchIfToBooleanIsFalse(JSAny): never
1443    labels Taken, NotTaken;
1444
1445macro ToBoolean(obj: JSAny): bool {
1446  BranchIfToBooleanIsTrue(obj) otherwise return true, return false;
1447}
1448
1449@export
1450macro RequireObjectCoercible(implicit context: Context)(
1451    value: JSAny, name: constexpr string): JSAny {
1452  if (IsNullOrUndefined(value)) {
1453    ThrowTypeError(MessageTemplate::kCalledOnNullOrUndefined, name);
1454  }
1455  return value;
1456}
1457
1458extern macro BranchIfSameValue(JSAny, JSAny): never labels Taken, NotTaken;
1459macro SameValue(a: JSAny, b: JSAny): bool {
1460  BranchIfSameValue(a, b) otherwise return true, return false;
1461}
1462
1463// Does "if (index1 + index2 > limit) goto IfOverflow" in an uintptr overflow
1464// friendly way where index1 and index2 are in [0, kMaxSafeInteger] range.
1465macro CheckIntegerIndexAdditionOverflow(
1466    index1: uintptr, index2: uintptr, limit: uintptr): void labels IfOverflow {
1467  if constexpr (Is64()) {
1468    dcheck(index1 <= kMaxSafeIntegerUint64);
1469    dcheck(index2 <= kMaxSafeIntegerUint64);
1470    // Given that both index1 and index2 are in a safe integer range the
1471    // addition can't overflow.
1472    if (index1 + index2 > limit) goto IfOverflow;
1473  } else {
1474    // Uintptr range is "smaller" than [0, kMaxSafeInteger] range, so
1475    // "index1 + index2" may overflow, so we check the condition in the
1476    // following way "if (index1 > limit - index2) goto IfOverflow" and check
1477    // that "limit - index2" does not underflow.
1478    const index1Limit = limit - index2;
1479    if (index1 > index1Limit) goto IfOverflow;
1480    // Handle potential index1Limit underflow.
1481    if (index1Limit > limit) goto IfOverflow;
1482  }
1483}
1484
1485// TODO(turbofan): Define enum here once they appear in Torque.
1486//
1487// The value is a SafeInteger that fits into uintptr range, so no bounds checks
1488// are necessary.
1489const kModeValueIsSafeIntegerUintPtr: constexpr int31 = 0;
1490// The value is a SafeInteger that may not fit into uintptr range, so only
1491// uintptr bounds check is necessary.
1492const kModeValueIsSafeInteger: constexpr int31 = 1;
1493// The value is can be whatever non-NaN number, all checks are necessary.
1494const kModeValueIsAnyNumber: constexpr int31 = 2;
1495
1496macro TryNumberToUintPtr(valueNumber: Number, kMode: constexpr int31):
1497    uintptr labels IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow {
1498  typeswitch (valueNumber) {
1499    case (valueSmi: Smi): {
1500      if (kMode == kModeValueIsAnyNumber) {
1501        if (valueSmi < 0) goto IfLessThanZero;
1502      } else {
1503        dcheck(valueSmi >= 0);
1504      }
1505      const value: uintptr = Unsigned(Convert<intptr>(valueSmi));
1506      // Positive Smi values definitely fit into both [0, kMaxSafeInteger] and
1507      // [0, kMaxUintPtr] ranges.
1508      return value;
1509    }
1510    case (valueHeapNumber: HeapNumber): {
1511      dcheck(IsNumberNormalized(valueHeapNumber));
1512      const valueDouble: float64 = Convert<float64>(valueHeapNumber);
1513      // NaNs must be handled outside.
1514      dcheck(!Float64IsNaN(valueDouble));
1515      if (kMode == kModeValueIsAnyNumber) {
1516        if (valueDouble < 0) goto IfLessThanZero;
1517      } else {
1518        dcheck(valueDouble >= 0);
1519      }
1520
1521      if constexpr (Is64()) {
1522        // On 64-bit architectures uintptr range is bigger than safe integer
1523        // range.
1524        if (kMode == kModeValueIsAnyNumber) {
1525          if (valueDouble > kMaxSafeInteger) goto IfSafeIntegerOverflow;
1526        } else {
1527          dcheck(valueDouble <= kMaxSafeInteger);
1528        }
1529      } else {
1530        // On 32-bit architectures uintptr range is smaller than safe integer
1531        // range.
1532        if (kMode == kModeValueIsAnyNumber ||
1533            kMode == kModeValueIsSafeInteger) {
1534          if (valueDouble > kMaxUInt32Double) goto IfUIntPtrOverflow;
1535        } else {
1536          dcheck(valueDouble <= kMaxUInt32Double);
1537        }
1538      }
1539      return ChangeFloat64ToUintPtr(valueDouble);
1540    }
1541  }
1542}
1543
1544@export
1545macro ChangeUintPtrNumberToUintPtr(value: Number): uintptr {
1546  try {
1547    return TryNumberToUintPtr(value, kModeValueIsSafeIntegerUintPtr)
1548        otherwise InvalidValue, InvalidValue, InvalidValue;
1549  } label InvalidValue {
1550    unreachable;
1551  }
1552}
1553
1554@export
1555macro ChangeSafeIntegerNumberToUintPtr(value: Number):
1556    uintptr labels IfUIntPtrOverflow {
1557  try {
1558    return TryNumberToUintPtr(value, kModeValueIsSafeInteger)
1559        otherwise InvalidValue, IfUIntPtrOverflow, InvalidValue;
1560  } label InvalidValue {
1561    unreachable;
1562  }
1563}
1564
1565transitioning macro ToUintPtr(implicit context: Context)(value: JSAny):
1566    uintptr labels IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow {
1567  if (value == Undefined) return 0;
1568  const indexNumber = ToInteger_Inline(value);
1569  return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
1570      otherwise IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow;
1571}
1572
1573// https://tc39.github.io/ecma262/#sec-toindex
1574// Unlike ToIndex from the spec this implementation triggers IfRangeError if
1575// the result is bigger than min(kMaxUIntPtr, kMaxSafeInteger).
1576// We can do this because all callers do a range checks against uintptr length
1577// anyway and throw a RangeError in case of out-of-bounds index.
1578@export
1579transitioning macro ToIndex(implicit context: Context)(value: JSAny):
1580    uintptr labels IfRangeError {
1581  if (value == Undefined) return 0;
1582  const indexNumber = ToInteger_Inline(value);
1583  // Less than 0 case, uintptr range overflow and safe integer range overflow
1584  // imply IfRangeError.
1585  return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
1586      otherwise IfRangeError, IfRangeError, IfRangeError;
1587}
1588
1589transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny):
1590    Number {
1591  try {
1592    typeswitch (o) {
1593      case (a: JSArray): {
1594        return a.length;
1595      }
1596      case (a: JSStrictArgumentsObject): {
1597        goto ToLength(a.length);
1598      }
1599      case (a: JSSloppyArgumentsObject): {
1600        goto ToLength(a.length);
1601      }
1602      case (JSAny): deferred {
1603        goto ToLength(GetProperty(o, kLengthString));
1604      }
1605    }
1606  } label ToLength(length: JSAny) deferred {
1607    return ToLength_Inline(length);
1608  }
1609}
1610
1611transitioning macro GetMethod(implicit context: Context)(
1612    o: JSAny, name: AnyName): Callable labels IfNullOrUndefined,
1613    IfMethodNotCallable(JSAny) {
1614  const value = GetProperty(o, name);
1615  // TODO(v8:9933): Consider checking for null/undefined after checking for
1616  // callable because the latter seems to be more common.
1617  if (value == Undefined || value == Null) goto IfNullOrUndefined;
1618  return Cast<Callable>(value)
1619      otherwise goto IfMethodNotCallable(value);
1620}
1621
1622transitioning macro GetMethod(implicit context: Context)(
1623    o: JSAny, name: String): Callable labels IfNullOrUndefined {
1624  try {
1625    return GetMethod(o, name) otherwise IfNullOrUndefined, IfMethodNotCallable;
1626  } label IfMethodNotCallable(value: JSAny) deferred {
1627    ThrowTypeError(MessageTemplate::kPropertyNotFunction, value, name, o);
1628  }
1629}
1630
1631transitioning macro GetMethod(implicit context: Context)(
1632    o: JSAny, name: constexpr string): Callable labels IfNullOrUndefined {
1633  return GetMethod(o, StringConstant(name)) otherwise IfNullOrUndefined;
1634}
1635
1636transitioning macro GetMethod(implicit context: Context)(
1637    o: JSAny, symbol: Symbol): Callable labels IfNullOrUndefined {
1638  const value = GetProperty(o, symbol);
1639  if (value == Undefined || value == Null) goto IfNullOrUndefined;
1640  return Cast<Callable>(value)
1641      otherwise ThrowTypeError(
1642      MessageTemplate::kPropertyNotFunction, value, symbol, o);
1643}
1644
1645extern macro IsOneByteStringInstanceType(InstanceType): bool;
1646
1647// After converting an index to an integer, calculate a relative index:
1648// return index < 0 ? max(length + index, 0) : min(index, length)
1649@export
1650transitioning macro ConvertToRelativeIndex(implicit context: Context)(
1651    index: JSAny, length: uintptr): uintptr {
1652  const indexNumber: Number = ToInteger_Inline(index);
1653  return ConvertToRelativeIndex(indexNumber, length);
1654}
1655
1656// Calculate a relative index:
1657// return index < 0 ? max(length + index, 0) : min(index, length)
1658@export
1659macro ConvertToRelativeIndex(indexNumber: Number, length: uintptr): uintptr {
1660  typeswitch (indexNumber) {
1661    case (indexSmi: Smi): {
1662      const indexIntPtr: intptr = Convert<intptr>(indexSmi);
1663      // The logic is implemented using unsigned types.
1664      if (indexIntPtr < 0) {
1665        const relativeIndex: uintptr = Unsigned(indexIntPtr) + length;
1666        return relativeIndex < length ? relativeIndex : 0;
1667
1668      } else {
1669        const relativeIndex: uintptr = Unsigned(indexIntPtr);
1670        return relativeIndex < length ? relativeIndex : length;
1671      }
1672    }
1673    case (indexHeapNumber: HeapNumber): {
1674      dcheck(IsNumberNormalized(indexHeapNumber));
1675      const indexDouble: float64 = Convert<float64>(indexHeapNumber);
1676      // NaNs must already be handled by ConvertToRelativeIndex() version
1677      // above accepting JSAny indices.
1678      dcheck(!Float64IsNaN(indexDouble));
1679      const lengthDouble: float64 = Convert<float64>(length);
1680      dcheck(lengthDouble <= kMaxSafeInteger);
1681      if (indexDouble < 0) {
1682        const relativeIndex: float64 = lengthDouble + indexDouble;
1683        return relativeIndex > 0 ? ChangeFloat64ToUintPtr(relativeIndex) : 0;
1684
1685      } else {
1686        return ChangeFloat64ToUintPtr(
1687            indexDouble < lengthDouble ? indexDouble : lengthDouble);
1688      }
1689    }
1690  }
1691}
1692
1693// After converting an index to a signed integer, clamps it to the provided
1694// range [0, limit]:
1695// return min(max(index, 0), limit)
1696@export
1697transitioning macro ClampToIndexRange(implicit context: Context)(
1698    index: JSAny, limit: uintptr): uintptr {
1699  const indexNumber: Number = ToInteger_Inline(index);
1700  return ClampToIndexRange(indexNumber, limit);
1701}
1702
1703// Clamps given signed indexNumber to the provided range [0, limit]:
1704// return min(max(index, 0), limit)
1705@export
1706macro ClampToIndexRange(indexNumber: Number, limit: uintptr): uintptr {
1707  typeswitch (indexNumber) {
1708    case (indexSmi: Smi): {
1709      if (indexSmi < 0) return 0;
1710      const index: uintptr = Unsigned(Convert<intptr>(indexSmi));
1711      if (index >= limit) return limit;
1712      return index;
1713    }
1714    case (indexHeapNumber: HeapNumber): {
1715      dcheck(IsNumberNormalized(indexHeapNumber));
1716      const indexDouble: float64 = Convert<float64>(indexHeapNumber);
1717      // NaNs must already be handled by ClampToIndexRange() version
1718      // above accepting JSAny indices.
1719      dcheck(!Float64IsNaN(indexDouble));
1720      if (indexDouble <= 0) return 0;
1721
1722      const maxIndexDouble: float64 = Convert<float64>(limit);
1723      dcheck(maxIndexDouble <= kMaxSafeInteger);
1724      if (indexDouble >= maxIndexDouble) return limit;
1725
1726      return ChangeFloat64ToUintPtr(indexDouble);
1727    }
1728  }
1729}
1730
1731extern builtin ObjectToString(Context, JSAny): String;
1732extern builtin StringRepeat(Context, String, Number): String;
1733
1734@export
1735struct KeyValuePair {
1736  key: JSAny;
1737  value: JSAny;
1738}
1739
1740// Macro definitions for compatibility that expose functionality to the CSA
1741// using "legacy" APIs. In Torque code, these should not be used.
1742@export
1743macro IsFastJSArray(o: Object, context: Context): bool {
1744  // Long-term, it's likely not a good idea to have this slow-path test here,
1745  // since it fundamentally breaks the type system.
1746  if (IsForceSlowPath()) return false;
1747  return Is<FastJSArray>(o);
1748}
1749
1750@export
1751macro BranchIfFastJSArray(o: Object, context: Context): never labels True,
1752    False {
1753  if (IsFastJSArray(o, context)) {
1754    goto True;
1755  } else {
1756    goto False;
1757  }
1758}
1759
1760@export
1761macro BranchIfFastJSArrayForRead(o: Object, context: Context):
1762    never labels True, False {
1763  // Long-term, it's likely not a good idea to have this slow-path test here,
1764  // since it fundamentally breaks the type system.
1765  if (IsForceSlowPath()) goto False;
1766  if (Is<FastJSArrayForRead>(o)) {
1767    goto True;
1768  } else {
1769    goto False;
1770  }
1771}
1772
1773@export
1774macro IsFastJSArrayWithNoCustomIteration(context: Context, o: Object): bool {
1775  return Is<FastJSArrayWithNoCustomIteration>(o);
1776}
1777
1778@export
1779macro IsFastJSArrayForReadWithNoCustomIteration(context: Context, o: Object):
1780    bool {
1781  return Is<FastJSArrayForReadWithNoCustomIteration>(o);
1782}
1783
1784extern transitioning runtime
1785CreateDataProperty(implicit context: Context)(JSReceiver, JSAny, JSAny): void;
1786
1787extern transitioning runtime SetOwnPropertyIgnoreAttributes(
1788    implicit context: Context)(JSObject, String, JSAny, Smi): void;
1789
1790namespace runtime {
1791extern runtime
1792GetDerivedMap(Context, JSFunction, JSReceiver, JSAny): Map;
1793}
1794extern macro IsDeprecatedMap(Map): bool;
1795
1796transitioning builtin FastCreateDataProperty(implicit context: Context)(
1797    receiver: JSReceiver, key: JSAny, value: JSAny): Object {
1798  try {
1799    const array = Cast<FastJSArray>(receiver) otherwise Slow;
1800    const index: Smi = Cast<Smi>(key) otherwise goto Slow;
1801    if (index < 0 || index > array.length) goto Slow;
1802    const isAppend = index == array.length;
1803
1804    if (isAppend) {
1805      // Fast append only works on fast elements kind and with writable length.
1806      const kind = EnsureArrayPushable(array.map) otherwise Slow;
1807      array::EnsureWriteableFastElements(array);
1808
1809      // We may have to transition a.
1810      // For now, if transition is required, jump away to slow.
1811      if (IsFastSmiElementsKind(kind)) {
1812        BuildAppendJSArray(ElementsKind::HOLEY_SMI_ELEMENTS, array, value)
1813            otherwise Slow;
1814      } else if (IsDoubleElementsKind(kind)) {
1815        BuildAppendJSArray(ElementsKind::HOLEY_DOUBLE_ELEMENTS, array, value)
1816            otherwise Slow;
1817      } else {
1818        dcheck(IsFastSmiOrTaggedElementsKind(kind));
1819        BuildAppendJSArray(ElementsKind::HOLEY_ELEMENTS, array, value)
1820            otherwise Slow;
1821      }
1822    } else {
1823      // Non-appending element store.
1824      const kind = array.map.elements_kind;
1825      array::EnsureWriteableFastElements(array);
1826
1827      // We may have to transition a.
1828      // For now, if transition is required, jump away to slow.
1829      if (IsFastSmiElementsKind(kind)) {
1830        const smiValue = Cast<Smi>(value) otherwise Slow;
1831        const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
1832        elements[index] = smiValue;
1833      } else if (IsDoubleElementsKind(kind)) {
1834        const numberValue = Cast<Number>(value) otherwise Slow;
1835        const doubleElements = Cast<FixedDoubleArray>(array.elements)
1836            otherwise unreachable;
1837        doubleElements[index] = numberValue;
1838      } else {
1839        dcheck(IsFastSmiOrTaggedElementsKind(kind));
1840        const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
1841        elements[index] = value;
1842      }
1843    }
1844  } label Slow {
1845    CreateDataProperty(receiver, key, value);
1846  }
1847  return Undefined;
1848}
1849
1850macro VerifiedUnreachable(): never {
1851  static_assert(false);
1852  unreachable;
1853}
1854
1855macro Float64IsSomeInfinity(value: float64): bool {
1856  if (value == V8_INFINITY) {
1857    return true;
1858  }
1859  return value == (Convert<float64>(0) - V8_INFINITY);
1860}
1861
1862macro IsIntegerOrSomeInfinity(o: Object): bool {
1863  typeswitch (o) {
1864    case (Smi): {
1865      return true;
1866    }
1867    case (hn: HeapNumber): {
1868      if (Float64IsSomeInfinity(Convert<float64>(hn))) {
1869        return true;
1870      }
1871      return IsInteger(hn);
1872    }
1873    case (Object): {
1874      return false;
1875    }
1876  }
1877}
1878
1879// Assert that the objects satisfy SameValue or are both the hole.
1880builtin CheckSameObject(implicit context: Context)(
1881    lhs: Object, rhs: Object): Undefined {
1882  typeswitch (lhs) {
1883    case (TheHole): {
1884      if (rhs == TheHole) return Undefined;
1885    }
1886    case (a: JSAny): {
1887      typeswitch (rhs) {
1888        case (b: JSAny): {
1889          if (SameValue(a, b)) return Undefined;
1890        }
1891        case (Object): {
1892        }
1893      }
1894    }
1895    case (Object): {
1896    }
1897  }
1898  Print('Distinct or unexpected values in CheckSameObject');
1899  unreachable;
1900}
1901
1902macro ReplaceTheHoleWithUndefined(o: JSAny|TheHole): JSAny {
1903  typeswitch (o) {
1904    case (TheHole): {
1905      return Undefined;
1906    }
1907    case (a: JSAny): {
1908      return a;
1909    }
1910  }
1911}
1912
1913extern macro DecodeScopeInfoHasContextExtension(intptr): intptr;
1914
1915struct ConstantIterator<T: type> {
1916  macro Empty(): bool {
1917    return false;
1918  }
1919  macro Next(): T labels _NoMore {
1920    return this.value;
1921  }
1922
1923  value: T;
1924}
1925macro ConstantIterator<T: type>(value: T): ConstantIterator<T> {
1926  return ConstantIterator{value};
1927}
1928
1929extern macro FeedbackIteratorEntrySize(): intptr;
1930extern macro FeedbackIteratorHandlerOffset(): intptr;
1931extern operator '[]' macro LoadWeakFixedArrayElement(
1932    WeakFixedArray, intptr): MaybeObject;
1933
1934extern operator '[]' macro LoadUint8Ptr(RawPtr<uint8>, intptr): uint8;
1935
1936extern enum HashFieldType extends uint32 constexpr 'Name::HashFieldType' {
1937  kHash,
1938  kIntegerIndex,
1939  kForwardingIndex,
1940  kEmpty
1941}
1942
1943operator '==' macro HashFieldTypeEquals(
1944    s1: HashFieldType, s2: HashFieldType): bool {
1945  return Word32Equal(s1, s2);
1946}
1947
1948const kNoHashSentinel:
1949    constexpr int32 generates 'PropertyArray::kNoHashSentinel';
1950extern macro LoadNameHash(Name): uint32;
1951
1952extern macro LoadSimd128(intptr): Simd128;
1953extern macro I8x16BitMask(I8X16): int32;
1954extern macro I8x16Eq(I8X16, I8X16): I8X16;
1955extern macro I8x16Splat(int32): I8X16;
1956