11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci// Unfortunately, MutableSlice<> is currently not a subtype of ConstSlice. 61cb0ef41Sopenharmony_ci// This would require struct subtyping, which is not yet supported. 71cb0ef41Sopenharmony_citype MutableSlice<T: type> extends torque_internal::Slice<T, &T>; 81cb0ef41Sopenharmony_citype ConstSlice<T: type> extends torque_internal::Slice<T, const &T>; 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cimacro Subslice<T: type>(slice: ConstSlice<T>, start: intptr, length: intptr): 111cb0ef41Sopenharmony_ci ConstSlice<T>labels OutOfBounds { 121cb0ef41Sopenharmony_ci if (Unsigned(length) > Unsigned(slice.length)) goto OutOfBounds; 131cb0ef41Sopenharmony_ci if (Unsigned(start) > Unsigned(slice.length - length)) goto OutOfBounds; 141cb0ef41Sopenharmony_ci const offset = slice.offset + torque_internal::TimesSizeOf<T>(start); 151cb0ef41Sopenharmony_ci return torque_internal::unsafe::NewConstSlice<T>( 161cb0ef41Sopenharmony_ci slice.object, offset, length); 171cb0ef41Sopenharmony_ci} 181cb0ef41Sopenharmony_cimacro Subslice<T: type>(slice: MutableSlice<T>, start: intptr, length: intptr): 191cb0ef41Sopenharmony_ci MutableSlice<T>labels OutOfBounds { 201cb0ef41Sopenharmony_ci if (Unsigned(length) > Unsigned(slice.length)) goto OutOfBounds; 211cb0ef41Sopenharmony_ci if (Unsigned(start) > Unsigned(slice.length - length)) goto OutOfBounds; 221cb0ef41Sopenharmony_ci const offset = slice.offset + torque_internal::TimesSizeOf<T>(start); 231cb0ef41Sopenharmony_ci return torque_internal::unsafe::NewMutableSlice<T>( 241cb0ef41Sopenharmony_ci slice.object, offset, length); 251cb0ef41Sopenharmony_ci} 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cinamespace unsafe { 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_cimacro AddOffset<T: type>(ref: &T, offset: intptr): &T { 301cb0ef41Sopenharmony_ci return torque_internal::unsafe::NewReference<T>( 311cb0ef41Sopenharmony_ci ref.object, ref.offset + torque_internal::TimesSizeOf<T>(offset)); 321cb0ef41Sopenharmony_ci} 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_cimacro AddOffset<T: type>(ref: const &T, offset: intptr): const &T { 351cb0ef41Sopenharmony_ci return torque_internal::unsafe::NewReference<T>( 361cb0ef41Sopenharmony_ci ref.object, ref.offset + torque_internal::TimesSizeOf<T>(offset)); 371cb0ef41Sopenharmony_ci} 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci} // namespace unsafe 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_cinamespace torque_internal { 421cb0ef41Sopenharmony_ci// Unsafe is a marker that we require to be passed when calling internal APIs 431cb0ef41Sopenharmony_ci// that might lead to unsoundness when used incorrectly. Unsafe markers should 441cb0ef41Sopenharmony_ci// therefore not be instantiated anywhere outside of this namespace. 451cb0ef41Sopenharmony_cistruct Unsafe {} 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci// Size of a type in memory (on the heap). For class types, this is the size 481cb0ef41Sopenharmony_ci// of the pointer, not of the instance. 491cb0ef41Sopenharmony_ciintrinsic %SizeOf<T: type>(): constexpr int31; 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_cimacro TimesSizeOf<T: type>(i: intptr): intptr { 521cb0ef41Sopenharmony_ci return i * %SizeOf<T>(); 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cistruct Reference<T: type> { 561cb0ef41Sopenharmony_ci const object: HeapObject|TaggedZeroPattern; 571cb0ef41Sopenharmony_ci const offset: intptr; 581cb0ef41Sopenharmony_ci unsafeMarker: Unsafe; 591cb0ef41Sopenharmony_ci} 601cb0ef41Sopenharmony_citype ConstReference<T: type> extends Reference<T>; 611cb0ef41Sopenharmony_citype MutableReference<T: type> extends ConstReference<T>; 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_cinamespace unsafe { 641cb0ef41Sopenharmony_cimacro NewReference<T: type>( 651cb0ef41Sopenharmony_ci object: HeapObject|TaggedZeroPattern, offset: intptr):&T { 661cb0ef41Sopenharmony_ci return %RawDownCast<&T>( 671cb0ef41Sopenharmony_ci Reference<T>{object: object, offset: offset, unsafeMarker: Unsafe {}}); 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_cimacro NewOffHeapReference<T: type>(ptr: RawPtr<T>):&T { 701cb0ef41Sopenharmony_ci return %RawDownCast<&T>(Reference<T>{ 711cb0ef41Sopenharmony_ci object: kZeroBitPattern, 721cb0ef41Sopenharmony_ci offset: Convert<intptr>(Convert<RawPtr>(ptr)) + kHeapObjectTag, 731cb0ef41Sopenharmony_ci unsafeMarker: Unsafe {} 741cb0ef41Sopenharmony_ci }); 751cb0ef41Sopenharmony_ci} 761cb0ef41Sopenharmony_cimacro ReferenceCast<T: type, U: type>(ref:&U):&T { 771cb0ef41Sopenharmony_ci const ref = NewReference<T>(ref.object, ref.offset); 781cb0ef41Sopenharmony_ci UnsafeCast<T>(*ref); 791cb0ef41Sopenharmony_ci return ref; 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciextern macro GCUnsafeReferenceToRawPtr( 831cb0ef41Sopenharmony_ci HeapObject | TaggedZeroPattern, intptr): RawPtr; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci} // namespace unsafe 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_cistruct Slice<T: type, Reference: type> { 881cb0ef41Sopenharmony_ci macro TryAtIndex(index: intptr): Reference labels OutOfBounds { 891cb0ef41Sopenharmony_ci if (Convert<uintptr>(index) < Convert<uintptr>(this.length)) { 901cb0ef41Sopenharmony_ci return this.UncheckedAtIndex(index); 911cb0ef41Sopenharmony_ci } else { 921cb0ef41Sopenharmony_ci goto OutOfBounds; 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci macro UncheckedAtIndex(index: intptr): Reference { 961cb0ef41Sopenharmony_ci return unsafe::NewReference<T>( 971cb0ef41Sopenharmony_ci this.object, this.offset + TimesSizeOf<T>(index)); 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci macro AtIndex(index: intptr): Reference { 1011cb0ef41Sopenharmony_ci return this.TryAtIndex(index) otherwise unreachable; 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci macro AtIndex(index: uintptr): Reference { 1051cb0ef41Sopenharmony_ci return this.TryAtIndex(Convert<intptr>(index)) otherwise unreachable; 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci macro AtIndex(index: constexpr IntegerLiteral): Reference { 1091cb0ef41Sopenharmony_ci return this.AtIndex(FromConstexpr<uintptr>(index)); 1101cb0ef41Sopenharmony_ci } 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci macro AtIndex(index: constexpr int31): Reference { 1131cb0ef41Sopenharmony_ci const i: intptr = Convert<intptr>(index); 1141cb0ef41Sopenharmony_ci return this.TryAtIndex(i) otherwise unreachable; 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci macro AtIndex(index: Smi): Reference { 1181cb0ef41Sopenharmony_ci const i: intptr = Convert<intptr>(index); 1191cb0ef41Sopenharmony_ci return this.TryAtIndex(i) otherwise unreachable; 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci macro Iterator(): SliceIterator<T, Reference> { 1231cb0ef41Sopenharmony_ci const end = this.offset + TimesSizeOf<T>(this.length); 1241cb0ef41Sopenharmony_ci return SliceIterator<T, Reference>{ 1251cb0ef41Sopenharmony_ci object: this.object, 1261cb0ef41Sopenharmony_ci start: this.offset, 1271cb0ef41Sopenharmony_ci end: end, 1281cb0ef41Sopenharmony_ci unsafeMarker: Unsafe {} 1291cb0ef41Sopenharmony_ci }; 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci macro Iterator( 1321cb0ef41Sopenharmony_ci startIndex: intptr, endIndex: intptr): SliceIterator<T, Reference> { 1331cb0ef41Sopenharmony_ci check( 1341cb0ef41Sopenharmony_ci Convert<uintptr>(endIndex) <= Convert<uintptr>(this.length) && 1351cb0ef41Sopenharmony_ci Convert<uintptr>(startIndex) <= Convert<uintptr>(endIndex)); 1361cb0ef41Sopenharmony_ci const start = this.offset + TimesSizeOf<T>(startIndex); 1371cb0ef41Sopenharmony_ci const end = this.offset + TimesSizeOf<T>(endIndex); 1381cb0ef41Sopenharmony_ci return SliceIterator<T, Reference>{ 1391cb0ef41Sopenharmony_ci object: this.object, 1401cb0ef41Sopenharmony_ci start, 1411cb0ef41Sopenharmony_ci end, 1421cb0ef41Sopenharmony_ci unsafeMarker: Unsafe {} 1431cb0ef41Sopenharmony_ci }; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci // WARNING: This can return a raw pointer into the heap, which is not GC-safe. 1471cb0ef41Sopenharmony_ci macro GCUnsafeStartPointer(): RawPtr<T> { 1481cb0ef41Sopenharmony_ci return %RawDownCast<RawPtr<T>>( 1491cb0ef41Sopenharmony_ci unsafe::GCUnsafeReferenceToRawPtr(this.object, this.offset)); 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci const object: HeapObject|TaggedZeroPattern; 1531cb0ef41Sopenharmony_ci const offset: intptr; 1541cb0ef41Sopenharmony_ci const length: intptr; 1551cb0ef41Sopenharmony_ci unsafeMarker: Unsafe; 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_cinamespace unsafe { 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_cimacro NewMutableSlice<T: type>( 1611cb0ef41Sopenharmony_ci object: HeapObject|TaggedZeroPattern, offset: intptr, 1621cb0ef41Sopenharmony_ci length: intptr): MutableSlice<T> { 1631cb0ef41Sopenharmony_ci return %RawDownCast<MutableSlice<T>>(Slice<T, &T>{ 1641cb0ef41Sopenharmony_ci object: object, 1651cb0ef41Sopenharmony_ci offset: offset, 1661cb0ef41Sopenharmony_ci length: length, 1671cb0ef41Sopenharmony_ci unsafeMarker: Unsafe {} 1681cb0ef41Sopenharmony_ci }); 1691cb0ef41Sopenharmony_ci} 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_cimacro NewConstSlice<T: type>( 1721cb0ef41Sopenharmony_ci object: HeapObject|TaggedZeroPattern, offset: intptr, 1731cb0ef41Sopenharmony_ci length: intptr): ConstSlice<T> { 1741cb0ef41Sopenharmony_ci return %RawDownCast<ConstSlice<T>>(Slice<T, const &T>{ 1751cb0ef41Sopenharmony_ci object: object, 1761cb0ef41Sopenharmony_ci offset: offset, 1771cb0ef41Sopenharmony_ci length: length, 1781cb0ef41Sopenharmony_ci unsafeMarker: Unsafe {} 1791cb0ef41Sopenharmony_ci }); 1801cb0ef41Sopenharmony_ci} 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_cimacro NewOffHeapConstSlice<T: type>( 1831cb0ef41Sopenharmony_ci startPointer: RawPtr<T>, length: intptr): ConstSlice<T> { 1841cb0ef41Sopenharmony_ci return %RawDownCast<ConstSlice<T>>(Slice<T, const &T>{ 1851cb0ef41Sopenharmony_ci object: kZeroBitPattern, 1861cb0ef41Sopenharmony_ci offset: Convert<intptr>(Convert<RawPtr>(startPointer)) + kHeapObjectTag, 1871cb0ef41Sopenharmony_ci length: length, 1881cb0ef41Sopenharmony_ci unsafeMarker: Unsafe {} 1891cb0ef41Sopenharmony_ci }); 1901cb0ef41Sopenharmony_ci} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci} // namespace unsafe 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_cistruct SliceIterator<T: type, Reference: type> { 1951cb0ef41Sopenharmony_ci macro Empty(): bool { 1961cb0ef41Sopenharmony_ci return this.start == this.end; 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci macro Next(): T labels NoMore { 2001cb0ef41Sopenharmony_ci return *this.NextReference() otherwise NoMore; 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci macro NextReference(): Reference labels NoMore { 2041cb0ef41Sopenharmony_ci if (this.Empty()) { 2051cb0ef41Sopenharmony_ci goto NoMore; 2061cb0ef41Sopenharmony_ci } else { 2071cb0ef41Sopenharmony_ci const result = unsafe::NewReference<T>(this.object, this.start); 2081cb0ef41Sopenharmony_ci this.start += %SizeOf<T>(); 2091cb0ef41Sopenharmony_ci return result; 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci object: HeapObject|TaggedZeroPattern; 2141cb0ef41Sopenharmony_ci start: intptr; 2151cb0ef41Sopenharmony_ci end: intptr; 2161cb0ef41Sopenharmony_ci unsafeMarker: Unsafe; 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_cimacro AddIndexedFieldSizeToObjectSize( 2201cb0ef41Sopenharmony_ci baseSize: intptr, arrayLength: intptr, fieldSize: constexpr int32): intptr { 2211cb0ef41Sopenharmony_ci const arrayLength = Convert<int32>(arrayLength); 2221cb0ef41Sopenharmony_ci const byteLength = TryInt32Mul(arrayLength, fieldSize) 2231cb0ef41Sopenharmony_ci otherwise unreachable; 2241cb0ef41Sopenharmony_ci return TryIntPtrAdd(baseSize, Convert<intptr>(byteLength)) 2251cb0ef41Sopenharmony_ci otherwise unreachable; 2261cb0ef41Sopenharmony_ci} 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_cimacro AlignTagged(x: intptr): intptr { 2291cb0ef41Sopenharmony_ci // Round up to a multiple of kTaggedSize. 2301cb0ef41Sopenharmony_ci return (x + kObjectAlignmentMask) & ~kObjectAlignmentMask; 2311cb0ef41Sopenharmony_ci} 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_cimacro IsTaggedAligned(x: intptr): bool { 2341cb0ef41Sopenharmony_ci return (x & kObjectAlignmentMask) == 0; 2351cb0ef41Sopenharmony_ci} 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_cimacro ValidAllocationSize(sizeInBytes: intptr, map: Map): bool { 2381cb0ef41Sopenharmony_ci if (sizeInBytes <= 0) return false; 2391cb0ef41Sopenharmony_ci if (!IsTaggedAligned(sizeInBytes)) return false; 2401cb0ef41Sopenharmony_ci const instanceSizeInWords = Convert<intptr>(map.instance_size_in_words); 2411cb0ef41Sopenharmony_ci return instanceSizeInWords == kVariableSizeSentinel || 2421cb0ef41Sopenharmony_ci instanceSizeInWords * kTaggedSize == sizeInBytes; 2431cb0ef41Sopenharmony_ci} 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_citype UninitializedHeapObject extends HeapObject; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ciextern macro GetInstanceTypeMap(constexpr InstanceType): Map; 2481cb0ef41Sopenharmony_ciextern macro Allocate( 2491cb0ef41Sopenharmony_ci intptr, constexpr AllocationFlag): UninitializedHeapObject; 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ciconst kAllocateBaseFlags: constexpr AllocationFlag = 2521cb0ef41Sopenharmony_ci AllocationFlag::kAllowLargeObjectAllocation; 2531cb0ef41Sopenharmony_cimacro AllocateFromNew( 2541cb0ef41Sopenharmony_ci sizeInBytes: intptr, map: Map, pretenured: bool): UninitializedHeapObject { 2551cb0ef41Sopenharmony_ci dcheck(ValidAllocationSize(sizeInBytes, map)); 2561cb0ef41Sopenharmony_ci if (pretenured) { 2571cb0ef41Sopenharmony_ci return Allocate( 2581cb0ef41Sopenharmony_ci sizeInBytes, 2591cb0ef41Sopenharmony_ci %RawConstexprCast<constexpr AllocationFlag>( 2601cb0ef41Sopenharmony_ci %RawConstexprCast<constexpr int32>(kAllocateBaseFlags) | 2611cb0ef41Sopenharmony_ci %RawConstexprCast<constexpr int32>(AllocationFlag::kPretenured))); 2621cb0ef41Sopenharmony_ci } else { 2631cb0ef41Sopenharmony_ci return Allocate(sizeInBytes, kAllocateBaseFlags); 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci} 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_cimacro InitializeFieldsFromIterator<T: type, Iterator: type>( 2681cb0ef41Sopenharmony_ci target: MutableSlice<T>, originIterator: Iterator): void { 2691cb0ef41Sopenharmony_ci let targetIterator = target.Iterator(); 2701cb0ef41Sopenharmony_ci let originIterator = originIterator; 2711cb0ef41Sopenharmony_ci while (true) { 2721cb0ef41Sopenharmony_ci const ref:&T = targetIterator.NextReference() otherwise break; 2731cb0ef41Sopenharmony_ci *ref = originIterator.Next() otherwise unreachable; 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci} 2761cb0ef41Sopenharmony_ci// Dummy implementations: do not initialize for UninitializedIterator. 2771cb0ef41Sopenharmony_ciInitializeFieldsFromIterator<char8, UninitializedIterator>( 2781cb0ef41Sopenharmony_ci _target: MutableSlice<char8>, 2791cb0ef41Sopenharmony_ci _originIterator: UninitializedIterator): void {} 2801cb0ef41Sopenharmony_ciInitializeFieldsFromIterator<char16, UninitializedIterator>( 2811cb0ef41Sopenharmony_ci _target: MutableSlice<char16>, 2821cb0ef41Sopenharmony_ci _originIterator: UninitializedIterator): void {} 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ciextern macro IsDoubleHole(HeapObject, intptr): bool; 2851cb0ef41Sopenharmony_ciextern macro StoreDoubleHole(HeapObject, intptr): void; 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_cimacro LoadFloat64OrHole(r:&float64_or_hole): float64_or_hole { 2881cb0ef41Sopenharmony_ci return float64_or_hole{ 2891cb0ef41Sopenharmony_ci is_hole: IsDoubleHole( 2901cb0ef41Sopenharmony_ci %RawDownCast<HeapObject>(r.object), r.offset - kHeapObjectTag), 2911cb0ef41Sopenharmony_ci value: *unsafe::NewReference<float64>(r.object, r.offset) 2921cb0ef41Sopenharmony_ci }; 2931cb0ef41Sopenharmony_ci} 2941cb0ef41Sopenharmony_cimacro StoreFloat64OrHole(r:&float64_or_hole, value: float64_or_hole): void { 2951cb0ef41Sopenharmony_ci if (value.is_hole) { 2961cb0ef41Sopenharmony_ci StoreDoubleHole( 2971cb0ef41Sopenharmony_ci %RawDownCast<HeapObject>(r.object), r.offset - kHeapObjectTag); 2981cb0ef41Sopenharmony_ci } else { 2991cb0ef41Sopenharmony_ci *unsafe::NewReference<float64>(r.object, r.offset) = value.value; 3001cb0ef41Sopenharmony_ci } 3011cb0ef41Sopenharmony_ci} 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_cimacro DownCastForTorqueClass<T : type extends HeapObject>(o: HeapObject): 3041cb0ef41Sopenharmony_ci T labels CastError { 3051cb0ef41Sopenharmony_ci const map = o.map; 3061cb0ef41Sopenharmony_ci const minInstanceType = %MinInstanceType<T>(); 3071cb0ef41Sopenharmony_ci const maxInstanceType = %MaxInstanceType<T>(); 3081cb0ef41Sopenharmony_ci if constexpr (minInstanceType == maxInstanceType) { 3091cb0ef41Sopenharmony_ci if constexpr (%ClassHasMapConstant<T>()) { 3101cb0ef41Sopenharmony_ci if (map != %GetClassMapConstant<T>()) goto CastError; 3111cb0ef41Sopenharmony_ci } else { 3121cb0ef41Sopenharmony_ci if (map.instance_type != minInstanceType) goto CastError; 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci } else { 3151cb0ef41Sopenharmony_ci const diff: int32 = maxInstanceType - minInstanceType; 3161cb0ef41Sopenharmony_ci const offset = Convert<int32>(Convert<uint16>(map.instance_type)) - 3171cb0ef41Sopenharmony_ci Convert<int32>(Convert<uint16>( 3181cb0ef41Sopenharmony_ci FromConstexpr<InstanceType>(minInstanceType))); 3191cb0ef41Sopenharmony_ci if (Unsigned(offset) > Unsigned(diff)) goto CastError; 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci return %RawDownCast<T>(o); 3221cb0ef41Sopenharmony_ci} 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ciextern macro StaticAssert(bool, constexpr string): void; 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci// This is for the implementation of the dot operator. In any context where the 3271cb0ef41Sopenharmony_ci// dot operator is available, the correct way to get the length of an indexed 3281cb0ef41Sopenharmony_ci// field x from object o is `(&o.x).length`. 3291cb0ef41Sopenharmony_ciintrinsic %IndexedFieldLength<T: type>(o: T, f: constexpr string): intptr; 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci// If field x is defined as optional, then &o.x returns a reference to the field 3321cb0ef41Sopenharmony_ci// or crashes the program (unreachable) if the field is not present. Usually 3331cb0ef41Sopenharmony_ci// that's the most convenient behavior, but in rare cases such as the 3341cb0ef41Sopenharmony_ci// implementation of the dot operator, we may instead need to get a Slice to the 3351cb0ef41Sopenharmony_ci// optional field, which is either length zero or one depending on whether the 3361cb0ef41Sopenharmony_ci// field is present. This intrinsic provides Slices for both indexed fields 3371cb0ef41Sopenharmony_ci// (equivalent to &o.x) and optional fields. 3381cb0ef41Sopenharmony_ciintrinsic %FieldSlice<T: type, TSlice: type>( 3391cb0ef41Sopenharmony_ci o: T, f: constexpr string): TSlice; 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ciextern macro GetPendingMessage(): TheHole|JSMessageObject; 3421cb0ef41Sopenharmony_ciextern macro SetPendingMessage(TheHole | JSMessageObject): void; 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci// This is implicitly performed at the beginning of Torque catch-blocks. 3451cb0ef41Sopenharmony_cimacro GetAndResetPendingMessage(): TheHole|JSMessageObject { 3461cb0ef41Sopenharmony_ci const message = GetPendingMessage(); 3471cb0ef41Sopenharmony_ci SetPendingMessage(TheHole); 3481cb0ef41Sopenharmony_ci return message; 3491cb0ef41Sopenharmony_ci} 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci} // namespace torque_internal 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci// Indicates that an array-field should not be initialized. 3541cb0ef41Sopenharmony_ci// For safety reasons, this is only allowed for untagged types. 3551cb0ef41Sopenharmony_cistruct UninitializedIterator {} 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci// %RawDownCast should *never* be used anywhere in Torque code except for 3581cb0ef41Sopenharmony_ci// in Torque-based UnsafeCast operators preceeded by an appropriate 3591cb0ef41Sopenharmony_ci// type dcheck() 3601cb0ef41Sopenharmony_ciintrinsic %RawDownCast<To: type, From: type>(x: From): To; 3611cb0ef41Sopenharmony_ciintrinsic %RawConstexprCast<To: type, From: type>(f: From): To; 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ciintrinsic %MinInstanceType<T: type>(): constexpr InstanceType; 3641cb0ef41Sopenharmony_ciintrinsic %MaxInstanceType<T: type>(): constexpr InstanceType; 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ciintrinsic %ClassHasMapConstant<T: type>(): constexpr bool; 3671cb0ef41Sopenharmony_ciintrinsic %GetClassMapConstant<T: type>(): Map; 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_cistruct IteratorSequence<T: type, FirstIterator: type, SecondIterator: type> { 3701cb0ef41Sopenharmony_ci macro Empty(): bool { 3711cb0ef41Sopenharmony_ci return this.first.Empty() && this.second.Empty(); 3721cb0ef41Sopenharmony_ci } 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci macro Next(): T labels NoMore { 3751cb0ef41Sopenharmony_ci return this.first.Next() 3761cb0ef41Sopenharmony_ci otherwise return (this.second.Next() otherwise NoMore); 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci first: FirstIterator; 3801cb0ef41Sopenharmony_ci second: SecondIterator; 3811cb0ef41Sopenharmony_ci} 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_cimacro IteratorSequence<T: type, FirstIterator: type, SecondIterator: type>( 3841cb0ef41Sopenharmony_ci first: FirstIterator, second: SecondIterator): 3851cb0ef41Sopenharmony_ci IteratorSequence<T, FirstIterator, SecondIterator> { 3861cb0ef41Sopenharmony_ci return IteratorSequence<T>{first, second}; 3871cb0ef41Sopenharmony_ci} 388