base.tq 70.2 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
type Tagged generates 'TNode<MaybeObject>' constexpr 'MaybeObject';
type StrongTagged extends Tagged
31
    generates 'TNode<Object>' constexpr 'Object';
32
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
// The Smi value zero, which is often used as null for HeapObject types.
type Zero extends PositiveSmi;
48 49
// A tagged value represented by an all-zero bitpattern.
type TaggedZeroPattern extends TaggedIndex;
50

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

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

61 62 63 64 65 66 67
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);
}
68

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

73 74 75
// TODO(turbofan): 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.
76 77 78

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

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

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

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

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

116 117 118
type Simd128 generates 'TNode<Simd128T>';
type I8X16 extends Simd128 generates 'TNode<I8x16T>';

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
// Represents a std::function which produces the generated TNode type of T.
// Useful for passing values to and from CSA code that uses LazyNode<T>, which
// is a typedef for std::function<TNode<T>()>. Can be created with %MakeLazy and
// accessed with RunLazy.
type Lazy<T: type>;

// Makes a Lazy. The first parameter is the name of a macro, which is looked up
// in the context where %MakeLazy is called, as a workaround for the fact that
// macros can't be used as values directly. The other parameters are saved and
// passed to the macro when somebody runs the resulting Lazy object. Torque
// syntax doesn't allow for arbitrary-length generic macros, but the internals
// support any number of parameters, so if you need more parameters, feel free
// to add additional declarations here.
intrinsic %MakeLazy<T: type>(getter: constexpr string): Lazy<T>;
intrinsic %MakeLazy<T: type, A1: type>(
    getter: constexpr string, arg1: A1): Lazy<T>;
intrinsic %MakeLazy<T: type, A1: type, A2: type>(
    getter: constexpr string, arg1: A1, arg2: A2): Lazy<T>;
intrinsic %MakeLazy<T: type, A1: type, A2: type, A3: type>(
    getter: constexpr string, arg1: A1, arg2: A2, arg3: A3): Lazy<T>;

// Executes a Lazy and returns the result. The CSA-side definition is a
// template, but Torque doesn't understand how to use templates for extern
// macros, so just add whatever overload definitions you need here.
extern macro RunLazy(Lazy<Smi>): Smi;

145
// A Smi value containing a bitfield struct as its integer data.
146
@useParentTypeChecker type SmiTagged<T : type extends uint31> extends Smi;
147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
// 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};

169 170 171 172 173 174 175 176 177 178 179 180 181
@doNotGenerateCast
@abstract
extern class JSPrototype extends JSObject generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSObjectPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSRegExpPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSPromisePrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
182 183 184
extern class JSTypedArrayPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
extern class JSSetPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSIteratorPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSArrayIteratorPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSMapIteratorPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSSetIteratorPrototype extends JSPrototype
    generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSStringIteratorPrototype extends JSPrototype
    generates 'TNode<JSObject>';

203 204 205
// 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.
206
@doNotGenerateCast
207 208 209 210 211 212 213 214 215 216 217
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;
218

219
type RawPtr generates 'TNode<RawPtrT>' constexpr 'Address';
220
type RawPtr<To: type> extends RawPtr;
221 222
type ExternalPointer
    generates 'TNode<ExternalPointerT>' constexpr 'ExternalPointer_t';
223
extern class Code extends HeapObject;
224
type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>';
225

226 227
type Number = Smi|HeapNumber;
type Numeric = Number|BigInt;
228

229 230 231 232
extern class ObjectBoilerplateDescription extends FixedArray;
extern class ClosureFeedbackCellArray extends FixedArray;
extern class ScriptContextTable extends FixedArray;

233 234
type LayoutDescriptor extends ByteArray
    generates 'TNode<LayoutDescriptor>';
235
extern class TransitionArray extends WeakFixedArray;
236

237 238 239
extern operator '.length_intptr' macro LoadAndUntagWeakFixedArrayLength(
    WeakFixedArray): intptr;

240
type InstanceType extends uint16 constexpr 'InstanceType';
241

242
type NoSharedNameSentinel extends Smi;
243

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

247 248 249
// A Foreign object whose raw pointer is not allowed to be null.
type NonNullForeign extends Foreign;

250
// A function built with InstantiateFunction for the public API.
251
type CallableApiObject extends JSObject;
252 253 254 255

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

256
type Callable = JSFunction|JSBoundFunction|CallableJSProxy|CallableApiObject;
257

258 259
type WriteBarrierMode
    generates 'TNode<Int32T>' constexpr 'WriteBarrierMode';
260

261 262 263 264
extern enum UpdateFeedbackMode { kOptionalFeedback, kGuaranteedFeedback }
extern operator '==' macro UpdateFeedbackModeEqual(
    constexpr UpdateFeedbackMode, constexpr UpdateFeedbackMode): constexpr bool;

265 266
extern enum CallFeedbackContent extends int32 { kTarget, kReceiver }

267
extern enum UnicodeEncoding { UTF16, UTF32 }
268

269
// Promise constants
270 271 272 273 274
extern enum PromiseState extends int31 constexpr 'Promise::PromiseState' {
  kPending,
  kFulfilled,
  kRejected
}
275

Tobias Tebbi's avatar
Tobias Tebbi committed
276 277
const kTaggedSize: constexpr int31 generates 'kTaggedSize';
const kDoubleSize: constexpr int31 generates 'kDoubleSize';
278 279
const kVariableSizeSentinel:
    constexpr int31 generates 'kVariableSizeSentinel';
280

Tobias Tebbi's avatar
Tobias Tebbi committed
281
const kSmiTagSize: constexpr int31 generates 'kSmiTagSize';
282
const kHeapObjectTag: constexpr int31 generates 'kHeapObjectTag';
Tobias Tebbi's avatar
Tobias Tebbi committed
283
const V8_INFINITY: constexpr float64 generates 'V8_INFINITY';
284
const MINUS_V8_INFINITY: constexpr float64 generates '-V8_INFINITY';
285

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
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,
  ...
}

312 313
extern enum AllocationFlag extends int32
constexpr 'CodeStubAssembler::AllocationFlag' {
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
  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 {
337
  kAllPromisesRejected,
338 339
  kInvalidArrayBufferLength,
  kInvalidArrayLength,
340
  kInvalidIndex,
341
  kNotConstructor,
342
  kNotGeneric,
343 344
  kCalledNonCallable,
  kCalledOnNullOrUndefined,
345
  kCannotConvertToPrimitive,
346 347 348 349 350 351 352 353 354 355
  kProtoObjectOrNull,
  kInvalidOffset,
  kInvalidTypedArrayLength,
  kIteratorSymbolNonCallable,
  kIteratorValueNotAnObject,
  kNotIterable,
  kReduceNoInitial,
  kFirstArgumentNotRegExp,
  kBigIntMixedTypes,
  kTypedArrayTooShort,
356
  kTypedArrayTooLargeToSort,
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
  kInvalidCountValue,
  kConstructorNotFunction,
  kSymbolToString,
  kPropertyNotFunction,
  kBigIntTooBig,
  kNotTypedArray,
  kDetachedOperation,
  kBadSortComparisonFunction,
  kIncompatibleMethodReceiver,
  kInvalidDataViewAccessorOffset,
  kTypedArraySetOffsetOutOfBounds,
  kInvalidArgument,
  kInvalidRegExpExecResult,
  kRegExpNonRegExp,
  kRegExpNonObject,
  kPromiseNonCallable,
  kNotAPromise,
  kResolverNotAFunction,
375
  kTooManyElementsInPromiseCombinator,
376 377 378 379 380 381 382 383 384 385 386 387 388 389
  kToRadixFormatRange,
  kCalledOnNonObject,
  kRegExpGlobalInvokedOnNonGlobal,
  kProxyNonObject,
  kProxyRevoked,
  kProxyTrapReturnedFalsishFor,
  kProxyPrivate,
  kProxyIsExtensibleInconsistent,
  kProxyPreventExtensionsExtensible,
  kProxyTrapReturnedFalsish,
  kProxyGetPrototypeOfInvalid,
  kProxyGetPrototypeOfNonExtensible,
  kProxySetPrototypeOfNonExtensible,
  kProxyDeletePropertyNonExtensible,
390
  kUndefinedOrNullToObject,
391
  kWeakRefsCleanupMustBeCallable,
392 393 394 395 396 397 398 399 400 401
  kWasmTrapUnreachable,
  kWasmTrapMemOutOfBounds,
  kWasmTrapUnalignedAccess,
  kWasmTrapDivByZero,
  kWasmTrapDivUnrepresentable,
  kWasmTrapRemByZero,
  kWasmTrapFloatUnrepresentable,
  kWasmTrapFuncSigMismatch,
  kWasmTrapDataSegmentDropped,
  kWasmTrapElemSegmentDropped,
402
  kWasmTrapTableOutOfBounds,
403
  kWasmTrapRethrowNull,
404
  kWasmTrapNullDereference,
405
  kWasmTrapIllegalCast,
406
  kWasmTrapArrayOutOfBounds,
407 408 409
  kWeakRefsRegisterTargetAndHoldingsMustNotBeSame,
  kWeakRefsRegisterTargetMustBeObject,
  kWeakRefsUnregisterTokenMustBeObject,
410
  kWeakRefsWeakRefConstructorTargetMustBeObject,
411 412
  ...
}
413

414 415 416 417 418 419 420 421 422 423
extern enum PropertyAttributes extends int31 {
  NONE,
  READ_ONLY,
  DONT_ENUM,
  DONT_DELETE,
  ALL_ATTRIBUTES_MASK,
  FROZEN,
  ...
}

424 425
const kArrayBufferMaxByteLength:
    constexpr uintptr generates 'JSArrayBuffer::kMaxByteLength';
426 427
const kTypedArrayMaxLength:
    constexpr uintptr generates 'JSTypedArray::kMaxLength';
428 429
const kMaxTypedArrayInHeap:
    constexpr int31 generates 'JSTypedArray::kMaxSizeInHeap';
430 431 432 433
// 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
434
    generates 'CodeStubAssembler::MaxSafeIntegerUintPtr()';
435
const kMaxSafeInteger: constexpr float64 generates 'kMaxSafeInteger';
436
const kMaxUInt32Double: constexpr float64 generates 'kMaxUInt32Double';
437
const kSmiMaxValue: constexpr uintptr generates 'kSmiMaxValue';
438
const kSmiMax: uintptr = kSmiMaxValue;
439
// TODO(v8:8996): Use uintptr version instead and drop this one.
440
const kStringMaxLength: constexpr int31 generates 'String::kMaxLength';
441 442
const kStringMaxLengthUintptr:
    constexpr uintptr generates 'String::kMaxLength';
443 444
const kFixedArrayMaxLength:
    constexpr int31 generates 'FixedArray::kMaxLength';
445 446
const kFixedDoubleArrayMaxLength:
    constexpr int31 generates 'FixedDoubleArray::kMaxLength';
447 448
const kObjectAlignmentMask: constexpr intptr
    generates 'kObjectAlignmentMask';
449 450 451 452
const kMinAddedElementsCapacity:
    constexpr int31 generates 'JSObject::kMinAddedElementsCapacity';
const kMaxCopyElements:
    constexpr int31 generates 'JSArray::kMaxCopyElements';
453 454 455 456 457 458
const kMaxRegularHeapObjectSize: constexpr int31
    generates 'kMaxRegularHeapObjectSize';

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

459
extern enum PrimitiveType { kString, kBoolean, kSymbol, kNumber }
460

461 462
const kNameDictionaryInitialCapacity:
    constexpr int32 generates 'NameDictionary::kInitialCapacity';
463 464
const kSwissNameDictionaryInitialCapacity:
    constexpr int32 generates 'SwissNameDictionary::kInitialCapacity';
465

466 467 468
const kWasmArrayHeaderSize:
    constexpr int32 generates 'WasmArray::kHeaderSize';

469 470 471
const kHeapObjectHeaderSize:
    constexpr int32 generates 'HeapObject::kHeaderSize';

472
const kDictModePrototypes:
473
    constexpr bool generates 'V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL';
474

475
type TheHole extends Oddball;
476 477 478 479
type Null extends Oddball;
type Undefined extends Oddball;
type True extends Oddball;
type False extends Oddball;
480
type Exception extends Oddball;
481
type EmptyString extends String;
482
type Boolean = True|False;
483

484
type NumberOrUndefined = Number|Undefined;
485

486
extern macro DefaultStringConstant(): String;
487
extern macro EmptyStringConstant(): EmptyString;
488
extern macro ErrorsStringConstant(): String;
489
extern macro FalseConstant(): False;
490
extern macro Int32FalseConstant(): bool;
491 492
extern macro Int32TrueConstant(): bool;
extern macro IteratorSymbolConstant(): PublicSymbol;
493
extern macro LengthStringConstant(): String;
494
extern macro MatchSymbolConstant(): Symbol;
495
extern macro MessageStringConstant(): String;
496
extern macro NanConstant(): NaN;
497
extern macro NameStringConstant(): String;
498
extern macro NullConstant(): Null;
499
extern macro NumberStringConstant(): String;
500
extern macro ReturnStringConstant(): String;
501
extern macro SearchSymbolConstant(): Symbol;
502
extern macro StringStringConstant(): String;
503
extern macro TheHoleConstant(): TheHole;
504 505
extern macro ToPrimitiveSymbolConstant(): PublicSymbol;
extern macro ToStringStringConstant(): String;
506 507
extern macro TrueConstant(): True;
extern macro UndefinedConstant(): Undefined;
508
extern macro ValueOfStringConstant(): String;
509
extern macro WasmWrappedObjectSymbolConstant(): Symbol;
510

511
const TheHole: TheHole = TheHoleConstant();
512 513 514 515
const Null: Null = NullConstant();
const Undefined: Undefined = UndefinedConstant();
const True: True = TrueConstant();
const False: False = FalseConstant();
516
const kEmptyString: EmptyString = EmptyStringConstant();
517
const kLengthString: String = LengthStringConstant();
518
const kMessageString: String = MessageStringConstant();
519 520
const kReturnString: String = ReturnStringConstant();

521
const kNaN: NaN = NanConstant();
522
const kZero: Zero = %RawDownCast<Zero>(SmiConstant(0));
523 524
const kZeroBitPattern: TaggedZeroPattern = %RawDownCast<TaggedZeroPattern>(
    Convert<Tagged>(BitcastWordToTaggedSigned(Convert<intptr>(0))));
525

526 527 528
const true: constexpr bool generates 'true';
const false: constexpr bool generates 'false';

529 530
extern enum LanguageMode extends bool { kStrict, kSloppy }
type LanguageModeSmi extends Smi;
531

532 533
const SKIP_WRITE_BARRIER:
    constexpr WriteBarrierMode generates 'SKIP_WRITE_BARRIER';
534 535
const UNSAFE_SKIP_WRITE_BARRIER:
    constexpr WriteBarrierMode generates 'UNSAFE_SKIP_WRITE_BARRIER';
536

537
extern transitioning macro AllocateJSIteratorResult(implicit context: Context)(
538
    JSAny, Boolean): JSObject;
539

540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
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>';

556 557
extern macro Is64(): constexpr bool;

558 559
extern macro SelectBooleanConstant(bool): Boolean;

560 561
extern macro Print(constexpr string);
extern macro Print(constexpr string, Object);
562
extern macro Comment(constexpr string);
563 564
extern macro Print(Object);
extern macro DebugBreak();
565 566

// ES6 7.1.4 ToInteger ( argument )
567
transitioning macro ToIntegerImpl(implicit context: Context)(input: JSAny):
568
    Number {
569 570 571 572 573 574 575 576 577 578 579
  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);
580 581
        // ToInteger normalizes -0 to +0.
        if (value == 0.0) return SmiConstant(0);
582
        const result = ChangeFloat64ToTagged(value);
583
        assert(IsNumberNormalized(result));
584 585
        return result;
      }
586 587
      case (a: JSAnyNotNumber): {
        input = conversion::NonNumberToNumber(a);
588 589 590 591 592 593
      }
    }
  }
  unreachable;
}

594
transitioning builtin ToInteger(implicit context: Context)(input: JSAny):
595
    Number {
596
  return ToIntegerImpl(input);
597 598 599
}

@export
600
transitioning macro ToInteger_Inline(implicit context: Context)(input: JSAny):
601 602 603 604 605
    Number {
  typeswitch (input) {
    case (s: Smi): {
      return s;
    }
606 607
    case (JSAny): {
      return ToInteger(input);
608 609 610 611
    }
  }
}

612 613 614 615 616 617
extern enum BigIntHandling extends int32
constexpr 'CodeStubAssembler::BigIntHandling' { kConvertToNumber, kThrow }

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

618 619 620 621 622 623
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;
624
extern transitioning macro ToThisString(implicit context: Context)(
625
    JSAny, String): String;
626
extern transitioning macro ToThisValue(implicit context: Context)(
627
    JSAny, constexpr PrimitiveType, constexpr string): JSAny;
628
extern transitioning macro GetProperty(implicit context: Context)(
629
    JSAny, JSAny): JSAny;
630
extern transitioning builtin SetProperty(implicit context: Context)(
631
    JSAny, JSAny, JSAny): JSAny;
632 633
extern transitioning builtin SetPropertyIgnoreAttributes(
    implicit context: Context)(JSObject, String, JSAny, Smi): JSAny;
634
extern transitioning builtin SetPropertyInLiteral(implicit context: Context)(
635
    JSAny, JSAny, JSAny): JSAny;
636
extern transitioning builtin DeleteProperty(implicit context: Context)(
637
    JSAny, JSAny | PrivateSymbol, LanguageModeSmi): Boolean;
638
extern transitioning builtin HasProperty(implicit context: Context)(
639
    JSAny, JSAny): Boolean;
640
extern transitioning macro HasProperty_Inline(implicit context: Context)(
641
    JSReceiver, JSAny): Boolean;
642 643
extern builtin LoadIC(
    Context, JSAny, JSAny, TaggedIndex, FeedbackVector): JSAny;
644

645 646
extern macro SetPropertyStrict(Context, Object, Object, Object): Object;

647 648 649 650 651 652 653 654 655 656
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;
657 658
extern macro ThrowTypeError(implicit context: Context)(
    constexpr MessageTemplate, Object, Object): never;
659 660
extern macro ThrowTypeError(implicit context: Context)(
    constexpr MessageTemplate, Object, Object, Object): never;
661 662
extern transitioning runtime ThrowTypeErrorIfStrict(implicit context: Context)(
    Smi, Object, Object): void;
663 664
extern transitioning runtime ThrowCalledNonCallable(implicit context: Context)(
    JSAny): never;
665

666 667 668
extern transitioning macro ThrowIfNotJSReceiver(implicit context: Context)(
    JSAny, constexpr MessageTemplate, constexpr string): void;

669
extern macro ArraySpeciesCreate(Context, JSAny, Number): JSReceiver;
670
extern macro ArrayCreate(implicit context: Context)(Number): JSArray;
671
extern macro BuildAppendJSArray(
672
    constexpr ElementsKind, FastJSArray, JSAny): void labels Bailout;
673

674
extern macro EnsureArrayPushable(implicit context: Context)(Map): ElementsKind
675
    labels Bailout;
676
// TODO: Reduce duplication once varargs are supported in macros.
677
extern macro Construct(implicit context: Context)(Constructor): JSReceiver;
678
extern macro Construct(implicit context: Context)(
679
    Constructor, JSAny): JSReceiver;
680
extern macro Construct(implicit context: Context)(
681
    Constructor, JSAny, JSAny): JSReceiver;
682
extern macro Construct(implicit context: Context)(
683
    Constructor, JSAny, JSAny, JSAny): JSReceiver;
684 685 686
extern macro ConstructWithTarget(implicit context: Context)(
    Constructor, JSReceiver): JSReceiver;
extern macro ConstructWithTarget(implicit context: Context)(
687
    Constructor, JSReceiver, JSAny): JSReceiver;
688
extern macro SpeciesConstructor(implicit context: Context)(
689
    JSAny, JSReceiver): JSReceiver;
690

691 692 693
extern macro ConstructorBuiltinsAssembler::IsDictionaryMap(Map): bool;
extern macro CodeStubAssembler::AllocateNameDictionary(constexpr int32):
    NameDictionary;
694 695
extern macro CodeStubAssembler::AllocateOrderedNameDictionary(constexpr int32):
    OrderedNameDictionary;
696 697
extern macro CodeStubAssembler::AllocateSwissNameDictionary(constexpr int32):
    SwissNameDictionary;
698

699 700
extern builtin ToObject(Context, JSAny): JSReceiver;
extern macro ToObject_Inline(Context, JSAny): JSReceiver;
701
extern macro IsUndefined(Object): bool;
702
extern macro IsNullOrUndefined(Object): bool;
703
extern macro IsString(HeapObject): bool;
Shiyu Zhang's avatar
Shiyu Zhang committed
704
extern transitioning builtin NonPrimitiveToPrimitive_String(
705
    Context, JSAny): JSPrimitive;
706
extern transitioning builtin NonPrimitiveToPrimitive_Default(
707 708 709 710 711 712 713 714 715 716 717 718 719
    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;
    }
  }
}
720

721 722 723
extern transitioning runtime NormalizeElements(Context, JSObject);
extern transitioning runtime TransitionElementsKindWithKind(
    Context, JSObject, Smi);
724

725 726 727
extern macro LoadBufferObject(RawPtr, constexpr int32): Object;
extern macro LoadBufferPointer(RawPtr, constexpr int32): RawPtr;
extern macro LoadBufferSmi(RawPtr, constexpr int32): Smi;
728
extern macro LoadBufferIntptr(RawPtr, constexpr int32): intptr;
729

730
extern runtime StringEqual(Context, String, String): Oddball;
731
extern builtin StringLessThan(Context, String, String): Boolean;
732 733 734
extern macro StringCharCodeAt(String, uintptr): char16;
extern macro StringFromSingleCharCode(char8): String;
extern macro StringFromSingleCharCode(char16): String;
735

736 737
extern macro NumberToString(Number): String;
extern macro StringToNumber(String): Number;
738 739 740 741
extern transitioning macro NonNumberToNumber(implicit context: Context)(
    JSAnyNotNumber): Number;
extern transitioning macro NonNumberToNumeric(implicit context: Context)(
    JSAnyNotNumber): Numeric;
742

743 744 745 746 747
extern macro Equal(JSAny, JSAny, Context): Boolean;
macro Equal(implicit context: Context)(left: JSAny, right: JSAny): Boolean {
  return Equal(left, right);
}

748
extern macro StrictEqual(JSAny, JSAny): Boolean;
749
extern macro SmiLexicographicCompare(Smi, Smi): Smi;
750
extern runtime ReThrow(Context, JSAny): never;
751
extern runtime Throw(implicit context: Context)(JSAny): never;
752
extern runtime ThrowInvalidStringLength(Context): never;
753

754 755
extern operator '==' macro WordEqual(RawPtr, RawPtr): bool;
extern operator '!=' macro WordNotEqual(RawPtr, RawPtr): bool;
756 757
extern operator '+' macro RawPtrAdd(RawPtr, intptr): RawPtr;
extern operator '+' macro RawPtrAdd(intptr, RawPtr): RawPtr;
758

759
extern operator '<' macro Int32LessThan(int32, int32): bool;
760
extern operator '<' macro Uint32LessThan(uint32, uint32): bool;
761
extern operator '>' macro Int32GreaterThan(int32, int32): bool;
762
extern operator '>' macro Uint32GreaterThan(uint32, uint32): bool;
763
extern operator '<=' macro Int32LessThanOrEqual(int32, int32): bool;
764
extern operator '<=' macro Uint32LessThanOrEqual(uint32, uint32): bool;
765
extern operator '>=' macro Int32GreaterThanOrEqual(int32, int32): bool;
766
extern operator '>=' macro Uint32GreaterThanOrEqual(uint32, uint32): bool;
767

768 769 770 771 772 773
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;
774

775 776
extern operator '==' macro ElementsKindEqual(
    constexpr ElementsKind, constexpr ElementsKind): constexpr bool;
777
extern operator '==' macro ElementsKindEqual(ElementsKind, ElementsKind): bool;
778 779 780 781
operator '!=' macro ElementsKindNotEqual(
    k1: ElementsKind, k2: ElementsKind): bool {
  return !ElementsKindEqual(k1, k2);
}
782 783 784 785
extern macro IsElementsKindLessThanOrEqual(
    ElementsKind, constexpr ElementsKind): bool;
extern macro IsElementsKindGreaterThan(
    ElementsKind, constexpr ElementsKind): bool;
786 787 788
extern macro IsElementsKindInRange(
    ElementsKind, constexpr ElementsKind, constexpr ElementsKind): bool;

789
extern macro IsFastElementsKind(constexpr ElementsKind): constexpr bool;
790
extern macro IsDoubleElementsKind(constexpr ElementsKind): constexpr bool;
791

792 793 794 795
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;
796
extern macro IsTuple2Map(Map): bool;
797

798
extern macro SmiAbove(Smi, Smi): bool;
799

800
extern operator '==' macro WordEqual(intptr, intptr): bool;
801
extern operator '==' macro WordEqual(uintptr, uintptr): bool;
802
extern operator '!=' macro WordNotEqual(intptr, intptr): bool;
803
extern operator '!=' macro WordNotEqual(uintptr, uintptr): bool;
804
extern operator '<' macro IntPtrLessThan(intptr, intptr): bool;
805
extern operator '<' macro UintPtrLessThan(uintptr, uintptr): bool;
806
extern operator '>' macro IntPtrGreaterThan(intptr, intptr): bool;
807
extern operator '>' macro UintPtrGreaterThan(uintptr, uintptr): bool;
808
extern operator '<=' macro IntPtrLessThanOrEqual(intptr, intptr): bool;
809
extern operator '<=' macro UintPtrLessThanOrEqual(uintptr, uintptr): bool;
810
extern operator '>=' macro IntPtrGreaterThanOrEqual(intptr, intptr): bool;
811
extern operator '>=' macro UintPtrGreaterThanOrEqual(uintptr, uintptr): bool;
812 813
extern operator '~' macro WordNot(intptr): intptr;
extern operator '~' macro WordNot(uintptr): uintptr;
814 815
extern operator '~' macro Word64Not(uint64): uint64;
extern operator '~' macro Word64Not(int64): int64;
816 817 818
extern operator '~' macro ConstexprWordNot(constexpr intptr): constexpr intptr;
extern operator '~' macro ConstexprWordNot(constexpr uintptr):
    constexpr uintptr;
819

820
extern operator '==' macro Float64Equal(float64, float64): bool;
821
extern operator '!=' macro Float64NotEqual(float64, float64): bool;
822
extern operator '>' macro Float64GreaterThan(float64, float64): bool;
823
extern operator '>=' macro Float64GreaterThanOrEqual(float64, float64): bool;
824
extern operator '<' macro Float64LessThan(float64, float64): bool;
825
extern operator '<=' macro Float64LessThanOrEqual(float64, float64): bool;
826

827
extern macro BranchIfNumberEqual(Number, Number): never
828
    labels Taken, NotTaken;
829
operator '==' macro IsNumberEqual(a: Number, b: Number): bool {
830
  BranchIfNumberEqual(a, b) otherwise return true, return false;
831
}
832
operator '!=' macro IsNumberNotEqual(a: Number, b: Number): bool {
833
  return !(a == b);
834
}
835
extern macro BranchIfNumberLessThan(Number, Number): never
836
    labels Taken, NotTaken;
837 838 839 840
operator '<' macro NumberIsLessThan(a: Number, b: Number): bool {
  BranchIfNumberLessThan(a, b) otherwise return true, return false;
}
extern macro BranchIfNumberLessThanOrEqual(Number, Number): never
841
    labels Taken, NotTaken;
842 843 844
operator '<=' macro NumberIsLessThanOrEqual(a: Number, b: Number): bool {
  BranchIfNumberLessThanOrEqual(a, b) otherwise return true, return false;
}
845

846 847 848 849 850 851
operator '>' macro NumberIsGreaterThan(a: Number, b: Number): bool {
  return b < a;
}
operator '>=' macro NumberIsGreaterThanOrEqual(a: Number, b: Number): bool {
  return b <= a;
}
852

853 854 855
extern macro BranchIfFloat64IsNaN(float64): never
    labels Taken, NotTaken;
macro Float64IsNaN(n: float64): bool {
856
  BranchIfFloat64IsNaN(n) otherwise return true, return false;
857 858
}

859
// The type of all tagged values that can safely be compared with TaggedEqual.
860
type TaggedWithIdentity =
861
    JSReceiver|FixedArrayBase|Oddball|Map|WeakCell|Context|EmptyString;
862

863 864 865
extern operator '==' macro TaggedEqual(TaggedWithIdentity, Object): bool;
extern operator '==' macro TaggedEqual(Object, TaggedWithIdentity): bool;
extern operator '==' macro TaggedEqual(
866
    TaggedWithIdentity, TaggedWithIdentity): bool;
867
extern operator '==' macro TaggedEqual(WeakHeapObject, WeakHeapObject): bool;
868 869 870
extern operator '!=' macro TaggedNotEqual(TaggedWithIdentity, Object): bool;
extern operator '!=' macro TaggedNotEqual(Object, TaggedWithIdentity): bool;
extern operator '!=' macro TaggedNotEqual(
871
    TaggedWithIdentity, TaggedWithIdentity): bool;
872
extern operator '!=' macro TaggedNotEqual(WeakHeapObject, WeakHeapObject): bool;
873 874
// Do not overload == and != if it is unclear if object identity is the right
// equality.
875 876
extern macro TaggedEqual(MaybeObject, MaybeObject): bool;
extern macro TaggedNotEqual(MaybeObject, MaybeObject): bool;
877 878 879

extern operator '+' macro SmiAdd(Smi, Smi): Smi;
extern operator '-' macro SmiSub(Smi, Smi): Smi;
880
extern operator '&' macro SmiAnd(Smi, Smi): Smi;
881 882
extern operator '|' macro SmiOr(Smi, Smi): Smi;
extern operator '<<' macro SmiShl(Smi, constexpr int31): Smi;
883
extern operator '>>' macro SmiSar(Smi, constexpr int31): Smi;
884 885

extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
886 887 888 889
extern operator '+' macro ConstexprIntPtrAdd(
    constexpr intptr, constexpr intptr): constexpr intptr;
extern operator '+' macro ConstexprUintPtrAdd(
    constexpr uintptr, constexpr uintptr): constexpr intptr;
890
extern operator '+' macro Int64Add(int64, int64): int64;
891
extern operator '-' macro IntPtrSub(intptr, intptr): intptr;
892
extern operator '-' macro Int64Sub(int64, int64): int64;
893
extern operator '*' macro IntPtrMul(intptr, intptr): intptr;
894
extern operator '*' macro Int64Mul(int64, int64): int64;
895
extern operator '/' macro IntPtrDiv(intptr, intptr): intptr;
896
extern operator '/' macro Int64Div(int64, int64): int64;
897
extern operator '<<' macro WordShl(intptr, intptr): intptr;
898
extern operator '>>' macro WordSar(intptr, intptr): intptr;
899
extern operator '&' macro WordAnd(intptr, intptr): intptr;
900 901 902
extern operator '|' macro WordOr(intptr, intptr): intptr;

extern operator '+' macro UintPtrAdd(uintptr, uintptr): uintptr;
903
extern operator '+' macro Uint64Add(uint64, uint64): uint64;
904
extern operator '-' macro UintPtrSub(uintptr, uintptr): uintptr;
905 906
extern operator '-' macro Uint64Sub(uint64, uint64): uint64;
extern operator '*' macro Uint64Mul(uint64, uint64): uint64;
907
extern operator '<<' macro WordShl(uintptr, uintptr): uintptr;
Tobias Tebbi's avatar
Tobias Tebbi committed
908 909 910
extern operator '>>>' macro WordShr(uintptr, uintptr): uintptr;
extern operator '&' macro WordAnd(uintptr, uintptr): uintptr;
extern operator '|' macro WordOr(uintptr, uintptr): uintptr;
911

Tobias Tebbi's avatar
Tobias Tebbi committed
912
extern operator '+' macro Int32Add(int32, int32): int32;
913
extern operator '+' macro Uint32Add(uint32, uint32): uint32;
Tobias Tebbi's avatar
Tobias Tebbi committed
914 915 916 917
extern operator '+' macro ConstexprUint32Add(
    constexpr uint32, constexpr int32): constexpr uint32;
extern operator '+' macro ConstexprInt31Add(
    constexpr int31, constexpr int31): constexpr int31;
918 919
extern operator '+' macro ConstexprInt32Add(
    constexpr int32, constexpr int32): constexpr int32;
Tobias Tebbi's avatar
Tobias Tebbi committed
920 921
extern operator '*' macro ConstexprInt31Mul(
    constexpr int31, constexpr int31): constexpr int31;
922 923
extern operator '-' macro Int32Sub(int16, int16): int32;
extern operator '-' macro Int32Sub(uint16, uint16): int32;
Tobias Tebbi's avatar
Tobias Tebbi committed
924
extern operator '-' macro Int32Sub(int32, int32): int32;
925
extern operator '-' macro Uint32Sub(uint32, uint32): uint32;
Tobias Tebbi's avatar
Tobias Tebbi committed
926
extern operator '*' macro Int32Mul(int32, int32): int32;
927
extern operator '*' macro Uint32Mul(uint32, uint32): uint32;
Tobias Tebbi's avatar
Tobias Tebbi committed
928 929 930 931 932 933 934 935
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;
936 937 938 939
extern operator '==' macro
ConstexprUint32Equal(constexpr uint32, constexpr uint32): constexpr bool;
extern operator '!=' macro
ConstexprUint32NotEqual(constexpr uint32, constexpr uint32): constexpr bool;
Tobias Tebbi's avatar
Tobias Tebbi committed
940 941 942
extern operator '>=' macro
ConstexprInt31GreaterThanEqual(
    constexpr int31, constexpr int31): constexpr bool;
943 944 945 946
extern operator '==' macro ConstexprInt32Equal(
    constexpr int32, constexpr int32): constexpr bool;
extern operator '!=' macro ConstexprInt32NotEqual(
    constexpr int32, constexpr int32): constexpr bool;
947

Tobias Tebbi's avatar
Tobias Tebbi committed
948 949 950 951 952
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;
953
extern operator '>>' macro Word32Sar(int32, int32): int32;
Tobias Tebbi's avatar
Tobias Tebbi committed
954 955 956 957 958 959 960 961
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;
962 963
extern operator '|' macro ConstexprWord32Or(
    constexpr int32, constexpr int32): constexpr int32;
964 965
extern operator '^' macro Word32Xor(int32, int32): int32;
extern operator '^' macro Word32Xor(uint32, uint32): uint32;
966 967
extern operator '<<' macro ConstexprWord32Shl(
    constexpr uint32, constexpr int32): uint32;
968

969 970 971 972 973 974 975 976 977 978 979
extern operator '==' macro Word64Equal(int64, int64): bool;
extern operator '==' macro Word64Equal(uint64, uint64): bool;
extern operator '!=' macro Word64NotEqual(int64, int64): bool;
extern operator '!=' macro Word64NotEqual(uint64, uint64): bool;
extern operator '>>>' macro Word64Shr(uint64, uint64): uint64;
extern operator '>>' macro Word64Sar(int64, int64): int64;
extern operator '<<' macro Word64Shl(int64, int64): int64;
extern operator '<<' macro Word64Shl(uint64, uint64): uint64;
extern operator '|' macro Word64Or(int64, int64): int64;
extern operator '|' macro Word64Or(uint64, uint64): uint64;
extern operator '&' macro Word64And(uint64, uint64): uint64;
980 981
extern operator '^' macro Word64Xor(int64, int64): int64;
extern operator '^' macro Word64Xor(uint64, uint64): uint64;
982

Tobias Tebbi's avatar
Tobias Tebbi committed
983 984 985 986
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;
987
extern operator '%' macro Float64Mod(float64, float64): float64;
988

Tobias Tebbi's avatar
Tobias Tebbi committed
989 990 991 992 993 994
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);
995
}
Tobias Tebbi's avatar
Tobias Tebbi committed
996 997
macro Max(x: Number, y: Number): Number {
  return NumberMax(x, y);
998 999
}

Tobias Tebbi's avatar
Tobias Tebbi committed
1000 1001 1002
extern macro TryIntPtrAdd(intptr, intptr): intptr labels Overflow;
extern macro TryIntPtrSub(intptr, intptr): intptr labels Overflow;
extern macro TryInt32Mul(int32, int32): int32 labels Overflow;
1003

Tobias Tebbi's avatar
Tobias Tebbi committed
1004 1005 1006 1007 1008 1009
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;
1010

Tobias Tebbi's avatar
Tobias Tebbi committed
1011 1012 1013 1014
extern macro SmiMax(Smi, Smi): Smi;
extern macro SmiMin(Smi, Smi): Smi;
extern macro SmiMul(Smi, Smi): Number;
extern macro SmiMod(Smi, Smi): Number;
1015

Tobias Tebbi's avatar
Tobias Tebbi committed
1016 1017 1018
extern macro IntPtrMax(intptr, intptr): intptr;
extern macro IntPtrMin(intptr, intptr): intptr;
extern macro UintPtrMin(uintptr, uintptr): uintptr;
1019

Tobias Tebbi's avatar
Tobias Tebbi committed
1020 1021 1022
extern operator '!' macro ConstexprBoolNot(constexpr bool): constexpr bool;
extern operator '!' macro Word32BinaryNot(bool): bool;
extern operator '!' macro IsFalse(Boolean): bool;
1023

1024 1025 1026 1027 1028
extern operator '==' macro
ConstexprInt31Equal(
    constexpr InstanceType, constexpr InstanceType): constexpr bool;
extern operator '-' macro ConstexprUint32Sub(
    constexpr InstanceType, constexpr InstanceType): constexpr int32;
1029 1030
extern operator '-' macro ConstexprInt32Sub(
    constexpr int32, constexpr int32): constexpr int32;
1031

Tobias Tebbi's avatar
Tobias Tebbi committed
1032 1033
extern operator '.instanceType' macro LoadInstanceType(HeapObject):
    InstanceType;
1034

Tobias Tebbi's avatar
Tobias Tebbi committed
1035 1036 1037
operator '.length_uintptr' macro LoadJSArrayLengthAsUintPtr(array: JSArray):
    uintptr {
  return Convert<uintptr>(array.length);
1038 1039
}

Tobias Tebbi's avatar
Tobias Tebbi committed
1040 1041 1042
extern operator '.length_intptr' macro LoadStringLengthAsWord(String): intptr;
operator '.length_uintptr' macro LoadStringLengthAsUintPtr(s: String): uintptr {
  return Unsigned(s.length_intptr);
1043
}
Tobias Tebbi's avatar
Tobias Tebbi committed
1044 1045
extern operator '.length_uint32' macro LoadStringLengthAsWord32(String): uint32;
extern operator '.length_smi' macro LoadStringLengthAsSmi(String): Smi;
1046

Tobias Tebbi's avatar
Tobias Tebbi committed
1047 1048 1049 1050 1051
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);
1052 1053
}

Tobias Tebbi's avatar
Tobias Tebbi committed
1054 1055 1056
operator '==' macro PromiseStateEquals(
    s1: PromiseState, s2: PromiseState): bool {
  return Word32Equal(s1, s2);
1057 1058
}

1059
extern macro CountLeadingZeros64(uint64): int64;
1060
extern macro CountTrailingZeros32(uint32): int32;
1061 1062
extern macro CountTrailingZeros64(uint64): int64;

Tobias Tebbi's avatar
Tobias Tebbi committed
1063 1064 1065 1066
extern macro TaggedIsSmi(Object): bool;
extern macro TaggedIsNotSmi(Object): bool;
extern macro TaggedIsPositiveSmi(Object): bool;
extern macro IsValidPositiveSmi(intptr): bool;
1067

1068
extern macro IsInteger(JSAny): bool;
Tobias Tebbi's avatar
Tobias Tebbi committed
1069
extern macro IsInteger(HeapNumber): bool;
1070

1071
extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
1072 1073
extern macro ChangeInt32ToTagged(int32): Number;
extern macro ChangeUint32ToTagged(uint32): Number;
1074 1075
extern macro ChangeUintPtrToFloat64(uintptr): float64;
extern macro ChangeUintPtrToTagged(uintptr): Number;
1076
extern macro Unsigned(int64): uint64;
1077
extern macro Unsigned(int32): uint32;
1078 1079
extern macro Unsigned(int16): uint16;
extern macro Unsigned(int8): uint8;
1080
extern macro Unsigned(intptr): uintptr;
1081
extern macro Unsigned(RawPtr): uintptr;
1082
extern macro Signed(uint64): int64;
1083
extern macro Signed(uint32): int32;
1084 1085
extern macro Signed(uint16): int16;
extern macro Signed(uint8): int8;
1086
extern macro Signed(uintptr): intptr;
1087
extern macro Signed(RawPtr): intptr;
1088
extern macro TruncateIntPtrToInt32(intptr): int32;
1089
extern macro TruncateInt64ToInt32(int64): int32;
1090 1091
extern macro SmiTag(intptr): Smi;
extern macro SmiFromInt32(int32): Smi;
1092
extern macro SmiFromUint32(uint32): Smi;
1093
extern macro SmiFromIntPtr(intptr): Smi;
1094
extern macro SmiUntag(Smi): intptr;
1095 1096 1097
macro SmiUntag<T: type>(value: SmiTagged<T>): T {
  return %RawDownCast<T>(Unsigned(SmiToInt32(Convert<Smi>(value))));
}
1098 1099 1100
macro SmiTag<T : type extends uint31>(value: T): SmiTagged<T> {
  return %RawDownCast<SmiTagged<T>>(SmiFromUint32(value));
}
1101
extern macro SmiToInt32(Smi): int32;
1102
extern macro SmiToFloat64(Smi): float64;
1103 1104 1105 1106
extern macro TaggedIndexToIntPtr(TaggedIndex): intptr;
extern macro IntPtrToTaggedIndex(intptr): TaggedIndex;
extern macro TaggedIndexToSmi(TaggedIndex): Smi;
extern macro SmiToTaggedIndex(Smi): TaggedIndex;
1107
extern macro RoundIntPtrToFloat64(intptr): float64;
1108
extern macro IntPtrRoundUpToPowerOfTwo32(intptr): intptr;
1109 1110
extern macro ChangeFloat32ToFloat64(float32): float64;
extern macro ChangeNumberToFloat64(Number): float64;
1111
extern macro ChangeNumberToUint32(Number): uint32;
1112 1113 1114
extern macro ChangeTaggedNonSmiToInt32(implicit context: Context)(JSAnyNotSmi):
    int32;
extern macro ChangeTaggedToFloat64(implicit context: Context)(JSAny): float64;
1115
extern macro ChangeFloat64ToTagged(float64): Number;
1116
extern macro ChangeFloat64ToUintPtr(float64): uintptr;
1117
extern macro ChangeFloat64ToIntPtr(float64): intptr;
1118
extern macro ChangeBoolToInt32(bool): int32;
1119
extern macro ChangeInt32ToFloat64(int32): float64;
1120 1121 1122 1123
extern macro ChangeInt32ToIntPtr(int32): intptr;    // Sign-extends.
extern macro ChangeUint32ToWord(uint32): uintptr;   // Doesn't sign-extend.
extern macro ChangeInt32ToInt64(int32): intptr;     // Sign-extends.
extern macro ChangeUint32ToUint64(uint32): uint64;  // Doesn't sign-extend.
1124
extern macro LoadNativeContext(Context): NativeContext;
1125
extern macro TruncateFloat64ToFloat32(float64): float32;
1126
extern macro TruncateHeapNumberValueToWord32(HeapNumber): int32;
1127 1128
extern macro LoadJSArrayElementsMap(constexpr ElementsKind, NativeContext): Map;
extern macro LoadJSArrayElementsMap(ElementsKind, NativeContext): Map;
1129 1130
extern macro NumberConstant(constexpr float64): Number;
extern macro NumberConstant(constexpr int32): Number;
1131
extern macro NumberConstant(constexpr uint32): Number;
1132 1133
extern macro IntPtrConstant(constexpr int31): intptr;
extern macro IntPtrConstant(constexpr int32): intptr;
1134
extern macro Uint16Constant(constexpr uint16): uint16;
1135
extern macro Int32Constant(constexpr int31): int31;
1136
extern macro Int32Constant(constexpr int32): int32;
1137 1138
extern macro Int64Constant(constexpr int64): int64;
extern macro Uint64Constant(constexpr uint64): uint64;
1139
extern macro Float64Constant(constexpr int31): float64;
1140
extern macro Float64Constant(constexpr float64): float64;
1141
extern macro SmiConstant(constexpr int31): Smi;
1142
extern macro SmiConstant(constexpr Smi): Smi;
1143
extern macro SmiConstant(constexpr MessageTemplate): Smi;
1144 1145
extern macro SmiConstant(constexpr bool): Smi;
extern macro SmiConstant(constexpr uint32): Smi;
1146
extern macro BoolConstant(constexpr bool): bool;
1147
extern macro StringConstant(constexpr string): String;
1148
extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot;
1149
extern macro IntPtrConstant(constexpr intptr): intptr;
1150
extern macro PointerConstant(constexpr RawPtr): RawPtr;
1151
extern macro SingleCharacterStringConstant(constexpr string): String;
1152
extern macro Float64SilenceNaN(float64): float64;
1153

1154
extern macro BitcastWordToTaggedSigned(intptr): Smi;
1155
extern macro BitcastWordToTaggedSigned(uintptr): Smi;
1156
extern macro BitcastWordToTagged(intptr): Object;
1157
extern macro BitcastWordToTagged(uintptr): Object;
1158
extern macro BitcastTaggedToWord(Object): intptr;
1159
extern macro BitcastTaggedToWordForTagAndSmiBits(Tagged): intptr;
1160

1161
extern macro FixedArrayMapConstant(): Map;
1162
extern macro FixedDoubleArrayMapConstant(): Map;
1163 1164
extern macro FixedCOWArrayMapConstant(): Map;
extern macro EmptyByteArrayConstant(): ByteArray;
1165
extern macro EmptyFixedArrayConstant(): EmptyFixedArray;
1166
extern macro PromiseCapabilityMapConstant(): Map;
1167 1168
extern macro OneByteStringMapConstant(): Map;
extern macro StringMapConstant(): Map;
1169 1170

const kFixedArrayMap: Map = FixedArrayMapConstant();
1171
const kFixedDoubleArrayMap: Map = FixedDoubleArrayMapConstant();
1172 1173
const kCOWMap: Map = FixedCOWArrayMapConstant();
const kEmptyByteArray: ByteArray = EmptyByteArrayConstant();
1174
const kEmptyFixedArray: EmptyFixedArray = EmptyFixedArrayConstant();
1175
const kPromiseCapabilityMap: Map = PromiseCapabilityMapConstant();
1176 1177 1178 1179
// The map of a non-internalized internal SeqOneByteString.
const kOneByteStringMap: Map = OneByteStringMapConstant();
// The map of a non-internalized internal SeqTwoByteString.
const kStringMap: Map = StringMapConstant();
1180

1181 1182 1183 1184 1185 1186
macro OutOfBounds<T: type, X: type>(index: T, length: X): bool {
  return UintPtrGreaterThanOrEqual(
      Convert<uintptr>(Convert<intptr>(index)),
      Convert<uintptr>(Convert<intptr>(length)));
}

1187 1188
extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
    bool;
1189
extern macro IsNoElementsProtectorCellInvalid(): bool;
1190
extern macro IsArrayIteratorProtectorCellInvalid(): bool;
1191 1192 1193
extern macro IsArraySpeciesProtectorCellInvalid(): bool;
extern macro IsTypedArraySpeciesProtectorCellInvalid(): bool;
extern macro IsPromiseSpeciesProtectorCellInvalid(): bool;
1194
extern macro IsMockArrayBufferAllocatorFlag(): bool;
1195
extern macro HasBuiltinSubclassingFlag(): bool;
1196 1197
extern macro IsPrototypeTypedArrayPrototype(implicit context: Context)(Map):
    bool;
1198

1199
extern operator '.data_ptr' macro LoadJSTypedArrayDataPtr(JSTypedArray): RawPtr;
1200

1201
extern operator '.elements_kind' macro LoadMapElementsKind(Map): ElementsKind;
1202 1203
extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray):
    ElementsKind;
1204

1205
extern operator '.length' macro LoadFastJSArrayLength(FastJSArray): Smi;
1206 1207 1208 1209 1210
operator '.length=' macro StoreFastJSArrayLength(
    array: FastJSArray, length: Smi) {
  const array: JSArray = array;
  array.length = length;
}
1211

1212
extern macro GetNumberDictionaryNumberOfElements(NumberDictionary): Smi;
1213

1214 1215
extern macro LoadConstructorOrBackPointer(Map): Object;

1216
extern macro BasicLoadNumberDictionaryElement(NumberDictionary, intptr): JSAny
1217
    labels NotData, IfHole;
1218

1219
extern macro IsFastElementsKind(ElementsKind): bool;
1220
extern macro IsDoubleElementsKind(ElementsKind): bool;
1221 1222
extern macro IsFastSmiOrTaggedElementsKind(ElementsKind): bool;
extern macro IsFastSmiElementsKind(ElementsKind): bool;
1223
extern macro IsHoleyFastElementsKind(ElementsKind): bool;
1224

1225
macro FastHoleyElementsKind(kind: ElementsKind): ElementsKind {
1226 1227 1228 1229
  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
    return ElementsKind::HOLEY_SMI_ELEMENTS;
  } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) {
    return ElementsKind::HOLEY_DOUBLE_ELEMENTS;
1230
  }
1231 1232
  assert(kind == ElementsKind::PACKED_ELEMENTS);
  return ElementsKind::HOLEY_ELEMENTS;
1233 1234
}

1235
macro AllowDoubleElements(kind: ElementsKind): ElementsKind {
1236 1237 1238 1239
  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
    return ElementsKind::PACKED_DOUBLE_ELEMENTS;
  } else if (kind == ElementsKind::HOLEY_SMI_ELEMENTS) {
    return ElementsKind::HOLEY_DOUBLE_ELEMENTS;
1240 1241 1242 1243 1244
  }
  return kind;
}

macro AllowNonNumberElements(kind: ElementsKind): ElementsKind {
1245 1246 1247 1248 1249 1250 1251 1252
  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;
1253 1254 1255 1256
  }
  return kind;
}

1257
macro GetObjectFunction(implicit context: Context)(): JSFunction {
1258
  return *NativeContextSlot(ContextSlot::OBJECT_FUNCTION_INDEX);
1259
}
1260
macro GetArrayFunction(implicit context: Context)(): JSFunction {
1261
  return *NativeContextSlot(ContextSlot::ARRAY_FUNCTION_INDEX);
1262
}
1263
macro GetArrayBufferFunction(implicit context: Context)(): Constructor {
1264
  return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_FUN_INDEX);
1265
}
1266
macro GetArrayBufferNoInitFunction(implicit context: Context)(): JSFunction {
1267
  return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_NOINIT_FUN_INDEX);
1268
}
1269
macro GetFastPackedElementsJSArrayMap(implicit context: Context)(): Map {
1270
  return *NativeContextSlot(ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
1271
}
1272
macro GetFastPackedSmiElementsJSArrayMap(implicit context: Context)(): Map {
1273 1274
  return *NativeContextSlot(
      ContextSlot::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX);
1275
}
1276
macro GetProxyRevocableResultMap(implicit context: Context)(): Map {
1277
  return *NativeContextSlot(ContextSlot::PROXY_REVOCABLE_RESULT_MAP_INDEX);
1278
}
1279
macro GetIteratorResultMap(implicit context: Context)(): Map {
1280
  return *NativeContextSlot(ContextSlot::ITERATOR_RESULT_MAP_INDEX);
1281
}
1282
macro GetInitialStringIteratorMap(implicit context: Context)(): Map {
1283
  return *NativeContextSlot(ContextSlot::INITIAL_STRING_ITERATOR_MAP_INDEX);
1284
}
1285
macro GetReflectApply(implicit context: Context)(): Callable {
1286
  return *NativeContextSlot(ContextSlot::REFLECT_APPLY_INDEX);
1287 1288
}
macro GetRegExpLastMatchInfo(implicit context: Context)(): RegExpMatchInfo {
1289
  return *NativeContextSlot(ContextSlot::REGEXP_LAST_MATCH_INFO_INDEX);
1290
}
1291
macro GetStrictArgumentsMap(implicit context: Context)(): Map {
1292
  return *NativeContextSlot(ContextSlot::STRICT_ARGUMENTS_MAP_INDEX);
1293 1294
}
macro GetSloppyArgumentsMap(implicit context: Context)(): Map {
1295
  return *NativeContextSlot(ContextSlot::SLOPPY_ARGUMENTS_MAP_INDEX);
1296 1297
}
macro GetFastAliasedArgumentsMap(implicit context: Context)(): Map {
1298
  return *NativeContextSlot(ContextSlot::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
1299
}
1300 1301 1302
macro GetWeakCellMap(implicit context: Context)(): Map {
  return %GetClassMapConstant<WeakCell>();
}
1303 1304 1305
macro GetPrototypeApplyFunction(implicit context: Context)(): JSFunction {
  return *NativeContextSlot(ContextSlot::FUNCTION_PROTOTYPE_APPLY_INDEX);
}
1306

1307 1308 1309 1310 1311 1312 1313
// 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;
1314
extern transitioning macro Call(
1315
    Context, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1316
extern transitioning macro Call(
1317
    Context, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1318
extern transitioning macro Call(
1319
    Context, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny, JSAny): JSAny;
1320

1321
extern macro TransitionElementsKind(
1322 1323
    JSObject, Map, constexpr ElementsKind,
    constexpr ElementsKind): void labels Bailout;
1324
extern macro PerformStackCheck(implicit context: Context)(): void;
1325

1326
extern macro Typeof(JSAny): String;
1327

1328 1329
// Return true iff number is NaN.
macro NumberIsNaN(number: Number): bool {
1330 1331
  typeswitch (number) {
    case (Smi): {
1332
      return false;
1333 1334
    }
    case (hn: HeapNumber): {
1335
      const value: float64 = Convert<float64>(hn);
1336 1337
      return value != value;
    }
1338
  }
1339
}
1340

1341
extern macro GotoIfForceSlowPath() labels Taken;
1342 1343 1344 1345 1346
macro IsForceSlowPath(): bool {
  GotoIfForceSlowPath() otherwise return true;
  return false;
}

1347
extern macro BranchIfToBooleanIsTrue(JSAny): never
1348
    labels Taken, NotTaken;
1349
extern macro BranchIfToBooleanIsFalse(JSAny): never
1350
    labels Taken, NotTaken;
1351

1352
macro ToBoolean(obj: JSAny): bool {
1353
  BranchIfToBooleanIsTrue(obj) otherwise return true, return false;
1354
}
1355

1356 1357
@export
macro RequireObjectCoercible(implicit context: Context)(
1358
    value: JSAny, name: constexpr string): JSAny {
1359
  if (IsNullOrUndefined(value)) {
1360
    ThrowTypeError(MessageTemplate::kCalledOnNullOrUndefined, name);
1361 1362 1363 1364
  }
  return value;
}

1365 1366
extern macro BranchIfSameValue(JSAny, JSAny): never labels Taken, NotTaken;
macro SameValue(a: JSAny, b: JSAny): bool {
1367 1368
  BranchIfSameValue(a, b) otherwise return true, return false;
}
1369

1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
// 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;
  }
}

1392
// TODO(turbofan): Define enum here once they appear in Torque.
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
//
// 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));
1413 1414
      // Positive Smi values definitely fit into both [0, kMaxSafeInteger] and
      // [0, kMaxUintPtr] ranges.
1415
      return value;
1416
    }
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
    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);
      }
1427

1428
      if constexpr (Is64()) {
1429 1430 1431 1432 1433 1434 1435
        // On 64-bit architectures uintptr range is bigger than safe integer
        // range.
        if (kMode == kModeValueIsAnyNumber) {
          if (valueDouble > kMaxSafeInteger) goto IfSafeIntegerOverflow;
        } else {
          assert(valueDouble <= kMaxSafeInteger);
        }
1436
      } else {
1437 1438 1439 1440 1441 1442 1443 1444
        // 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);
        }
1445
      }
1446
      return ChangeFloat64ToUintPtr(valueDouble);
1447 1448
    }
  }
1449
}
1450

1451 1452 1453 1454 1455
@export
macro ChangeUintPtrNumberToUintPtr(value: Number): uintptr {
  try {
    return TryNumberToUintPtr(value, kModeValueIsSafeIntegerUintPtr)
        otherwise InvalidValue, InvalidValue, InvalidValue;
1456
  } label InvalidValue {
1457 1458 1459 1460
    unreachable;
  }
}

1461
@export
1462 1463 1464 1465 1466
macro ChangeSafeIntegerNumberToUintPtr(value: Number):
    uintptr labels IfUIntPtrOverflow {
  try {
    return TryNumberToUintPtr(value, kModeValueIsSafeInteger)
        otherwise InvalidValue, IfUIntPtrOverflow, InvalidValue;
1467
  } label InvalidValue {
1468 1469 1470 1471
    unreachable;
  }
}

1472 1473 1474
transitioning macro ToUintPtr(implicit context: Context)(value: JSAny):
    uintptr labels IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow {
  if (value == Undefined) return 0;
1475
  const indexNumber = ToInteger_Inline(value);
1476 1477 1478 1479
  return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
      otherwise IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow;
}

1480 1481 1482 1483 1484 1485 1486 1487 1488
// 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;
1489
  const indexNumber = ToInteger_Inline(value);
1490 1491 1492 1493 1494 1495
  // Less than 0 case, uintptr range overflow and safe integer range overflow
  // imply IfRangeError.
  return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
      otherwise IfRangeError, IfRangeError, IfRangeError;
}

1496
transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny):
1497
    Number {
1498
  try {
1499 1500 1501 1502
    typeswitch (o) {
      case (a: JSArray): {
        return a.length;
      }
1503 1504 1505 1506
      case (a: JSStrictArgumentsObject): {
        goto ToLength(a.length);
      }
      case (a: JSSloppyArgumentsObject): {
1507
        goto ToLength(a.length);
1508
      }
1509
      case (JSAny): deferred {
1510 1511 1512
        goto ToLength(GetProperty(o, kLengthString));
      }
    }
1513
  } label ToLength(length: JSAny) deferred {
1514
    return ToLength_Inline(length);
1515 1516
  }
}
1517

1518
transitioning macro GetMethod(implicit context: Context)(
1519 1520
    o: JSAny, name: AnyName): Callable labels IfNullOrUndefined,
    IfMethodNotCallable(JSAny) {
1521
  const value = GetProperty(o, name);
1522 1523
  // TODO(v8:9933): Consider checking for null/undefined after checking for
  // callable because the latter seems to be more common.
1524 1525
  if (value == Undefined || value == Null) goto IfNullOrUndefined;
  return Cast<Callable>(value)
1526 1527 1528 1529 1530 1531 1532
      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;
1533
  } label IfMethodNotCallable(value: JSAny) deferred {
1534
    ThrowTypeError(MessageTemplate::kPropertyNotFunction, value, name, o);
1535 1536 1537 1538 1539 1540
  }
}

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

1543 1544 1545 1546 1547
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)
1548 1549
      otherwise ThrowTypeError(
      MessageTemplate::kPropertyNotFunction, value, symbol, o);
1550 1551
}

1552
extern macro IsOneByteStringInstanceType(InstanceType): bool;
1553 1554 1555 1556 1557

// 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)(
1558
    index: JSAny, length: uintptr): uintptr {
1559
  const indexNumber: Number = ToInteger_Inline(index);
1560 1561 1562 1563 1564 1565
  return ConvertToRelativeIndex(indexNumber, length);
}

// Calculate a relative index:
// return index < 0 ? max(length + index, 0) : min(index, length)
@export
1566
macro ConvertToRelativeIndex(indexNumber: Number, length: uintptr): uintptr {
1567 1568 1569 1570 1571 1572
  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;
1573
        return relativeIndex < length ? relativeIndex : 0;
1574 1575 1576

      } else {
        const relativeIndex: uintptr = Unsigned(indexIntPtr);
1577
        return relativeIndex < length ? relativeIndex : length;
1578 1579 1580
      }
    }
    case (indexHeapNumber: HeapNumber): {
1581
      assert(IsNumberNormalized(indexHeapNumber));
1582 1583 1584
      const indexDouble: float64 = Convert<float64>(indexHeapNumber);
      // NaNs must already be handled by ConvertToRelativeIndex() version
      // above accepting JSAny indices.
1585
      assert(!Float64IsNaN(indexDouble));
1586 1587 1588 1589
      const lengthDouble: float64 = Convert<float64>(length);
      assert(lengthDouble <= kMaxSafeInteger);
      if (indexDouble < 0) {
        const relativeIndex: float64 = lengthDouble + indexDouble;
1590
        return relativeIndex > 0 ? ChangeFloat64ToUintPtr(relativeIndex) : 0;
1591 1592

      } else {
1593 1594
        return ChangeFloat64ToUintPtr(
            indexDouble < lengthDouble ? indexDouble : lengthDouble);
1595 1596 1597 1598
      }
    }
  }
}
1599

1600 1601 1602 1603 1604 1605
// 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 {
1606
  const indexNumber: Number = ToInteger_Inline(index);
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621
  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): {
1622
      assert(IsNumberNormalized(indexHeapNumber));
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637
      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);
    }
  }
}

1638
extern builtin ObjectToString(Context, JSAny): String;
1639
extern builtin StringRepeat(Context, String, Number): String;
1640

1641
@export
1642
struct KeyValuePair {
1643 1644
  key: JSAny;
  value: JSAny;
1645
}
1646 1647 1648

// Macro definitions for compatibility that expose functionality to the CSA
// using "legacy" APIs. In Torque code, these should not be used.
1649
@export
1650
macro IsFastJSArray(o: Object, context: Context): bool {
1651 1652 1653
  // 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;
1654 1655 1656
  return Is<FastJSArray>(o);
}

1657 1658 1659
@export
macro BranchIfFastJSArray(o: Object, context: Context): never labels True,
    False {
1660 1661 1662 1663 1664
  if (IsFastJSArray(o, context)) {
    goto True;
  } else {
    goto False;
  }
1665 1666
}

1667 1668 1669
@export
macro BranchIfFastJSArrayForRead(o: Object, context: Context):
    never labels True, False {
1670 1671
  // Long-term, it's likely not a good idea to have this slow-path test here,
  // since it fundamentally breaks the type system.
1672 1673 1674 1675 1676 1677
  if (IsForceSlowPath()) goto False;
  if (Is<FastJSArrayForRead>(o)) {
    goto True;
  } else {
    goto False;
  }
1678 1679
}

1680
@export
1681 1682 1683
macro IsFastJSArrayWithNoCustomIteration(context: Context, o: Object): bool {
  return Is<FastJSArrayWithNoCustomIteration>(o);
}
1684

1685 1686 1687 1688 1689 1690
@export
macro IsFastJSArrayForReadWithNoCustomIteration(context: Context, o: Object):
    bool {
  return Is<FastJSArrayForReadWithNoCustomIteration>(o);
}

1691
extern transitioning runtime
1692
CreateDataProperty(implicit context: Context)(JSReceiver, JSAny, JSAny);
1693

1694 1695 1696
extern transitioning runtime SetOwnPropertyIgnoreAttributes(
    implicit context: Context)(JSObject, String, JSAny, Smi);

1697
namespace runtime {
1698
extern runtime
1699
GetDerivedMap(Context, JSFunction, JSReceiver, JSAny): Map;
1700
}
1701
extern macro IsDeprecatedMap(Map): bool;
1702

1703
transitioning builtin FastCreateDataProperty(implicit context: Context)(
1704
    receiver: JSReceiver, key: JSAny, value: JSAny): Object {
1705
  try {
1706
    const array = Cast<FastJSArray>(receiver) otherwise Slow;
1707 1708 1709
    const index: Smi = Cast<Smi>(key) otherwise goto Slow;
    if (index < 0 || index > array.length) goto Slow;
    const isAppend = index == array.length;
1710 1711 1712 1713 1714 1715 1716 1717 1718

    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)) {
1719 1720
        BuildAppendJSArray(ElementsKind::HOLEY_SMI_ELEMENTS, array, value)
            otherwise Slow;
1721
      } else if (IsDoubleElementsKind(kind)) {
1722
        BuildAppendJSArray(ElementsKind::HOLEY_DOUBLE_ELEMENTS, array, value)
1723 1724
            otherwise Slow;
      } else {
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741
        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;
1742 1743 1744 1745
        const doubleElements = Cast<FixedDoubleArray>(array.elements)
            otherwise unreachable;
        doubleElements[index] = numberValue;
      } else {
1746
        assert(IsFastSmiOrTaggedElementsKind(kind));
1747 1748 1749 1750
        const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
        elements[index] = value;
      }
    }
1751
  } label Slow {
1752 1753 1754 1755
    CreateDataProperty(receiver, key, value);
  }
  return Undefined;
}
Shiyu Zhang's avatar
Shiyu Zhang committed
1756

1757
macro VerifiedUnreachable(): never {
1758
  static_assert(false);
1759 1760
  unreachable;
}
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787

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)(
1788
    value: Number, min: Number, max: Number, nodeId: Smi): Undefined {
1789 1790 1791
  if (IsIntegerOrSomeInfinity(value) && min <= value && value <= max) {
    return Undefined;
  } else {
1792
    Print('Range type assertion failed! (value/min/max/nodeId)');
1793 1794 1795
    Print(value);
    Print(min);
    Print(max);
1796
    Print(nodeId);
1797 1798 1799
    unreachable;
  }
}
1800

1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823
// 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;
}

1824
macro ReplaceTheHoleWithUndefined(o: JSAny|TheHole): JSAny {
1825 1826 1827 1828 1829 1830 1831 1832 1833
  typeswitch (o) {
    case (TheHole): {
      return Undefined;
    }
    case (a: JSAny): {
      return a;
    }
  }
}
1834 1835

extern macro DecodeScopeInfoHasContextExtension(intptr): intptr;
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849

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};
}
1850

1851 1852
extern macro FeedbackIteratorEntrySize(): intptr;
extern macro FeedbackIteratorHandlerOffset(): intptr;
1853 1854
extern operator '[]' macro LoadWeakFixedArrayElement(
    WeakFixedArray, intptr): MaybeObject;
1855 1856 1857 1858

const kNoHashSentinel:
    constexpr int32 generates 'PropertyArray::kNoHashSentinel';
extern macro LoadNameHash(Name): uint32;
1859 1860 1861 1862 1863

extern macro LoadSimd128(intptr): Simd128;
extern macro I8x16BitMask(I8X16): int32;
extern macro I8x16Eq(I8X16, I8X16): I8X16;
extern macro I8x16Splat(int32): I8X16;