11cb0ef41Sopenharmony_ci// Copyright 2021 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#include 'src/objects/swiss-name-dictionary.h'
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci@doNotGenerateCppClass
81cb0ef41Sopenharmony_ciextern class SwissNameDictionary extends HeapObject {
91cb0ef41Sopenharmony_ci  hash: uint32;
101cb0ef41Sopenharmony_ci  const capacity: int32;
111cb0ef41Sopenharmony_ci  meta_table: ByteArray;
121cb0ef41Sopenharmony_ci  data_table[Convert<intptr>(capacity) * 2]: JSAny|TheHole;
131cb0ef41Sopenharmony_ci  ctrl_table[Convert<intptr>(capacity) + swiss_table::kGroupWidth]: uint8;
141cb0ef41Sopenharmony_ci  property_details_table[Convert<intptr>(capacity)]: uint8;
151cb0ef41Sopenharmony_ci}
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace swiss_table {
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst kDataTableEntryCount: constexpr intptr
201cb0ef41Sopenharmony_ci    generates 'SwissNameDictionary::kDataTableEntryCount';
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ciconst kMax1ByteMetaTableCapacity: constexpr int32
231cb0ef41Sopenharmony_ci    generates 'SwissNameDictionary::kMax1ByteMetaTableCapacity';
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciconst kMax2ByteMetaTableCapacity: constexpr int32
261cb0ef41Sopenharmony_ci    generates 'SwissNameDictionary::kMax2ByteMetaTableCapacity';
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciconst kNotFoundSentinel:
291cb0ef41Sopenharmony_ci    constexpr int32 generates 'SwissNameDictionary::kNotFoundSentinel';
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciextern macro LoadSwissNameDictionaryKey(SwissNameDictionary, intptr): Name;
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciextern macro StoreSwissNameDictionaryKeyAndValue(
341cb0ef41Sopenharmony_ci    SwissNameDictionary, intptr, Object, Object): void;
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciextern macro SwissNameDictionarySetCtrl(
371cb0ef41Sopenharmony_ci    SwissNameDictionary, intptr, intptr, uint8): void;
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciextern macro StoreSwissNameDictionaryPropertyDetails(
401cb0ef41Sopenharmony_ci    SwissNameDictionary, intptr, intptr, uint8): void;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ciextern macro
431cb0ef41Sopenharmony_ciSwissNameDictionaryIncreaseElementCountOrBailout(
441cb0ef41Sopenharmony_ci    ByteArray, intptr, uint32): uint32 labels Bailout;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ciextern macro
471cb0ef41Sopenharmony_ciStoreSwissNameDictionaryEnumToEntryMapping(
481cb0ef41Sopenharmony_ci    SwissNameDictionary, intptr, intptr, int32): void;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ciextern macro
511cb0ef41Sopenharmony_ciSwissNameDictionaryUpdateCountsForDeletion(ByteArray, intptr): uint32;
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_cinamespace runtime {
541cb0ef41Sopenharmony_ciextern runtime SwissTableFindEntry(NoContext, SwissNameDictionary, Name): Smi;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ciextern runtime SwissTableAdd(
571cb0ef41Sopenharmony_ci    NoContext, SwissNameDictionary, Name, Object, Smi): SwissNameDictionary;
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ciextern runtime ShrinkSwissNameDictionary(
601cb0ef41Sopenharmony_ci    NoContext, SwissNameDictionary): SwissNameDictionary;
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci// Counterpart for SwissNameDictionary::CapacityFor in C++.
641cb0ef41Sopenharmony_ci@export
651cb0ef41Sopenharmony_cimacro SwissNameDictionaryCapacityFor(atLeastSpaceFor: intptr): intptr {
661cb0ef41Sopenharmony_ci  if (atLeastSpaceFor <= 4) {
671cb0ef41Sopenharmony_ci    if (atLeastSpaceFor == 0) {
681cb0ef41Sopenharmony_ci      return 0;
691cb0ef41Sopenharmony_ci    } else if (atLeastSpaceFor < kSwissNameDictionaryInitialCapacity) {
701cb0ef41Sopenharmony_ci      return 4;
711cb0ef41Sopenharmony_ci    } else if (FromConstexpr<bool>(kGroupWidth == 16)) {
721cb0ef41Sopenharmony_ci      dcheck(atLeastSpaceFor == 4);
731cb0ef41Sopenharmony_ci      return 4;
741cb0ef41Sopenharmony_ci    } else if (FromConstexpr<bool>(kGroupWidth == 8)) {
751cb0ef41Sopenharmony_ci      dcheck(atLeastSpaceFor == 4);
761cb0ef41Sopenharmony_ci      return 8;
771cb0ef41Sopenharmony_ci    }
781cb0ef41Sopenharmony_ci  }
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  const nonNormalized = atLeastSpaceFor + atLeastSpaceFor / 7;
811cb0ef41Sopenharmony_ci  return IntPtrRoundUpToPowerOfTwo32(nonNormalized);
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci// Counterpart for SwissNameDictionary::MaxUsableCapacity in C++.
851cb0ef41Sopenharmony_ci@export
861cb0ef41Sopenharmony_cimacro SwissNameDictionaryMaxUsableCapacity(capacity: intptr): intptr {
871cb0ef41Sopenharmony_ci  dcheck(capacity == 0 || capacity >= kSwissNameDictionaryInitialCapacity);
881cb0ef41Sopenharmony_ci  if (FromConstexpr<bool>(kGroupWidth == 8) && capacity == 4) {
891cb0ef41Sopenharmony_ci    // If the group size is 16 we can fully utilize capacity 4: There will be
901cb0ef41Sopenharmony_ci    // enough kEmpty entries in the ctrl table.
911cb0ef41Sopenharmony_ci    return 3;
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci  return capacity - capacity / 8;
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci// Counterpart for SwissNameDictionary::SizeFor in C++.
971cb0ef41Sopenharmony_ci@export
981cb0ef41Sopenharmony_cimacro SwissNameDictionarySizeFor(capacity: intptr): intptr {
991cb0ef41Sopenharmony_ci  const constant: constexpr int32 = kHeapObjectHeaderSize + 8 + kTaggedSize;
1001cb0ef41Sopenharmony_ci  const dynamic: intptr =
1011cb0ef41Sopenharmony_ci      capacity * FromConstexpr<intptr>(2 * kTaggedSize + 2) +
1021cb0ef41Sopenharmony_ci      FromConstexpr<intptr>(kGroupWidth);
1031cb0ef41Sopenharmony_ci  return constant + dynamic;
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci// Counterpart for SwissNameDictionary::MetaTableSizePerEntryFor in C++.
1071cb0ef41Sopenharmony_ci@export
1081cb0ef41Sopenharmony_cimacro SwissNameDictionaryMetaTableSizePerEntryFor(capacity: intptr): intptr {
1091cb0ef41Sopenharmony_ci  if (capacity <= kMax1ByteMetaTableCapacity) {
1101cb0ef41Sopenharmony_ci    return 1;
1111cb0ef41Sopenharmony_ci  } else if (capacity <= kMax2ByteMetaTableCapacity) {
1121cb0ef41Sopenharmony_ci    return 2;
1131cb0ef41Sopenharmony_ci  } else {
1141cb0ef41Sopenharmony_ci    return 4;
1151cb0ef41Sopenharmony_ci  }
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci// Counterpart for SwissNameDictionary::MetaTableSizeFor in C++.
1191cb0ef41Sopenharmony_ci@export
1201cb0ef41Sopenharmony_cimacro SwissNameDictionaryMetaTableSizeFor(capacity: intptr): intptr {
1211cb0ef41Sopenharmony_ci  const perEntry: intptr =
1221cb0ef41Sopenharmony_ci      SwissNameDictionaryMetaTableSizePerEntryFor(capacity);
1231cb0ef41Sopenharmony_ci  const maxUsable: intptr =
1241cb0ef41Sopenharmony_ci      Convert<intptr>(SwissNameDictionaryMaxUsableCapacity(capacity));
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci  return (2 + maxUsable) * perEntry;
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci//
1301cb0ef41Sopenharmony_ci// Offsets. MT stands for "minus tag"
1311cb0ef41Sopenharmony_ci//
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ciconst kDataTableStartOffsetMT: constexpr intptr
1341cb0ef41Sopenharmony_ci    generates 'SwissNameDictionary::DataTableStartOffset() - kHeapObjectTag';
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci@export
1371cb0ef41Sopenharmony_cimacro SwissNameDictionaryDataTableStartOffsetMT(): intptr {
1381cb0ef41Sopenharmony_ci  return kDataTableStartOffsetMT;
1391cb0ef41Sopenharmony_ci}
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci@export
1421cb0ef41Sopenharmony_cimacro SwissNameDictionaryCtrlTableStartOffsetMT(capacity: intptr): intptr {
1431cb0ef41Sopenharmony_ci  return kDataTableStartOffsetMT +
1441cb0ef41Sopenharmony_ci      kDataTableEntryCount * FromConstexpr<intptr>(kTaggedSize) * capacity;
1451cb0ef41Sopenharmony_ci}
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_cimacro Probe(hash: uint32, mask: uint32): ProbeSequence {
1481cb0ef41Sopenharmony_ci  // Mask must be a power of 2 minus 1.
1491cb0ef41Sopenharmony_ci  dcheck(((mask + 1) & mask) == 0);
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  return ProbeSequence{mask: mask, offset: H1(hash) & mask, index: 0};
1521cb0ef41Sopenharmony_ci}
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_cimacro FindEntry<GroupLoader: type>(
1551cb0ef41Sopenharmony_ci    table: SwissNameDictionary, key: Name): never labels
1561cb0ef41Sopenharmony_ciFound(intptr), NotFound {
1571cb0ef41Sopenharmony_ci  const hash: uint32 = LoadNameHash(key);
1581cb0ef41Sopenharmony_ci  const capacity: int32 = table.capacity;
1591cb0ef41Sopenharmony_ci  const nonZeroCapacity: int32 = capacity | Convert<int32>(capacity == 0);
1601cb0ef41Sopenharmony_ci  const mask: uint32 = Unsigned(nonZeroCapacity - 1);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  const ctrlTableStart: intptr =
1631cb0ef41Sopenharmony_ci      SwissNameDictionaryCtrlTableStartOffsetMT(Convert<intptr>(capacity)) +
1641cb0ef41Sopenharmony_ci      BitcastTaggedToWord(table);
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  let seq = Probe(hash, mask);
1671cb0ef41Sopenharmony_ci  while (true) {
1681cb0ef41Sopenharmony_ci    const group =
1691cb0ef41Sopenharmony_ci        GroupLoader{}.LoadGroup(ctrlTableStart + Convert<intptr>(seq.offset));
1701cb0ef41Sopenharmony_ci    let match = group.Match(H2(hash));
1711cb0ef41Sopenharmony_ci    while (match.HasBitsSet()) {
1721cb0ef41Sopenharmony_ci      const inGroupIndex = match.LowestBitSet();
1731cb0ef41Sopenharmony_ci      const candidateEntry = Convert<intptr>(seq.Offset(inGroupIndex));
1741cb0ef41Sopenharmony_ci      const candidateKey: Object =
1751cb0ef41Sopenharmony_ci          LoadSwissNameDictionaryKey(table, candidateEntry);
1761cb0ef41Sopenharmony_ci      if (TaggedEqual(key, candidateKey)) {
1771cb0ef41Sopenharmony_ci        goto Found(candidateEntry);
1781cb0ef41Sopenharmony_ci      }
1791cb0ef41Sopenharmony_ci      match.ClearLowestSetBit();
1801cb0ef41Sopenharmony_ci    }
1811cb0ef41Sopenharmony_ci    if (group.MatchEmpty().HasBitsSet()) {
1821cb0ef41Sopenharmony_ci      goto NotFound;
1831cb0ef41Sopenharmony_ci    }
1841cb0ef41Sopenharmony_ci    seq.Next();
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  unreachable;
1881cb0ef41Sopenharmony_ci}
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_cimacro FindFirstEmpty<GroupLoader: type>(
1911cb0ef41Sopenharmony_ci    table: SwissNameDictionary, capacity: intptr, hash: uint32): int32 {
1921cb0ef41Sopenharmony_ci  const nonZeroCapacity: int32 =
1931cb0ef41Sopenharmony_ci      Convert<int32>(capacity) | Convert<int32>(capacity == 0);
1941cb0ef41Sopenharmony_ci  const mask: uint32 = Unsigned(nonZeroCapacity - 1);
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  const ctrlTableStart: intptr =
1971cb0ef41Sopenharmony_ci      SwissNameDictionaryCtrlTableStartOffsetMT(capacity) +
1981cb0ef41Sopenharmony_ci      BitcastTaggedToWord(table);
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  let seq = Probe(hash, mask);
2011cb0ef41Sopenharmony_ci  while (true) {
2021cb0ef41Sopenharmony_ci    const group =
2031cb0ef41Sopenharmony_ci        GroupLoader{}.LoadGroup(ctrlTableStart + Convert<intptr>(seq.offset));
2041cb0ef41Sopenharmony_ci    const match = group.MatchEmpty();
2051cb0ef41Sopenharmony_ci    if (match.HasBitsSet()) {
2061cb0ef41Sopenharmony_ci      const inGroupIndex = match.LowestBitSet();
2071cb0ef41Sopenharmony_ci      return Signed(seq.Offset(inGroupIndex));
2081cb0ef41Sopenharmony_ci    }
2091cb0ef41Sopenharmony_ci    seq.Next();
2101cb0ef41Sopenharmony_ci  }
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  unreachable;
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_cimacro Add<GroupLoader: type>(
2161cb0ef41Sopenharmony_ci    table: SwissNameDictionary, key: Name, value: Object,
2171cb0ef41Sopenharmony_ci    propertyDetails: uint8): void labels Bailout {
2181cb0ef41Sopenharmony_ci  const capacity: intptr = Convert<intptr>(table.capacity);
2191cb0ef41Sopenharmony_ci  const maxUsable: uint32 =
2201cb0ef41Sopenharmony_ci      Unsigned(Convert<int32>(SwissNameDictionaryMaxUsableCapacity(capacity)));
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  try {
2231cb0ef41Sopenharmony_ci    // We read the used capacity (present + deleted elements), compare it
2241cb0ef41Sopenharmony_ci    // against the max usable capacity to determine if a bailout is necessary,
2251cb0ef41Sopenharmony_ci    // and in case of no bailout increase the present element count all in one
2261cb0ef41Sopenharmony_ci    // go using the following macro. This way we don't have to do the branching
2271cb0ef41Sopenharmony_ci    // needed for meta table accesses multiple times.
2281cb0ef41Sopenharmony_ci    const used: uint32 = SwissNameDictionaryIncreaseElementCountOrBailout(
2291cb0ef41Sopenharmony_ci        table.meta_table, capacity, maxUsable) otherwise Bailout;
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci    const hash: uint32 = LoadNameHash(key);
2321cb0ef41Sopenharmony_ci    const newEntry32 = FindFirstEmpty<GroupLoader>(table, capacity, hash);
2331cb0ef41Sopenharmony_ci    const newEntry = Convert<intptr>(newEntry32);
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci    StoreSwissNameDictionaryKeyAndValue(table, newEntry, key, value);
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci    StoreSwissNameDictionaryEnumToEntryMapping(
2381cb0ef41Sopenharmony_ci        table, capacity, Convert<intptr>(used), newEntry32);
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci    const h2 = Convert<uint8>(Convert<intptr>(H2(hash)));
2411cb0ef41Sopenharmony_ci    SwissNameDictionarySetCtrl(table, capacity, newEntry, h2);
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci    StoreSwissNameDictionaryPropertyDetails(
2441cb0ef41Sopenharmony_ci        table, capacity, newEntry, propertyDetails);
2451cb0ef41Sopenharmony_ci  } label Bailout {
2461cb0ef41Sopenharmony_ci    goto Bailout;
2471cb0ef41Sopenharmony_ci  }
2481cb0ef41Sopenharmony_ci}
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci@export
2511cb0ef41Sopenharmony_cimacro SwissNameDictionaryDelete(table: SwissNameDictionary, entry: intptr):
2521cb0ef41Sopenharmony_ci    void labels Shrunk(SwissNameDictionary) {
2531cb0ef41Sopenharmony_ci  const capacity = Convert<intptr>(table.capacity);
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  // Update present and deleted element counts at once, without needing to do
2561cb0ef41Sopenharmony_ci  // the meta table access related branching more than once.
2571cb0ef41Sopenharmony_ci  const newElementCount =
2581cb0ef41Sopenharmony_ci      SwissNameDictionaryUpdateCountsForDeletion(table.meta_table, capacity);
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  StoreSwissNameDictionaryKeyAndValue(table, entry, TheHole, TheHole);
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  const kDeleted = FromConstexpr<uint8>(ctrl::kDeleted);
2631cb0ef41Sopenharmony_ci  SwissNameDictionarySetCtrl(table, capacity, entry, kDeleted);
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci  // Same logic for deciding when to shrink as in SwissNameDictionary::Delete.
2661cb0ef41Sopenharmony_ci  if (Convert<intptr>(Signed(newElementCount)) < (capacity >> 2)) {
2671cb0ef41Sopenharmony_ci    const shrunkTable = runtime::ShrinkSwissNameDictionary(kNoContext, table);
2681cb0ef41Sopenharmony_ci    goto Shrunk(shrunkTable);
2691cb0ef41Sopenharmony_ci  }
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci// TODO(v8:11330) Ideally, we would like to implement
2731cb0ef41Sopenharmony_ci// CodeStubAssembler::SwissNameDictionaryFindEntry in Torque and do the
2741cb0ef41Sopenharmony_ci// necessary switching between the two implementations with if(kUseSimd) {...}
2751cb0ef41Sopenharmony_ci// else {...}. However, Torque currently generates a call to
2761cb0ef41Sopenharmony_ci// CodeAssembler::Branch which cannot guarantee that code for the "bad" path is
2771cb0ef41Sopenharmony_ci// not generated, even if the branch can be resolved at compile time. This means
2781cb0ef41Sopenharmony_ci// that we end up trying to generate unused code using unsupported instructions.
2791cb0ef41Sopenharmony_ci@export
2801cb0ef41Sopenharmony_cimacro SwissNameDictionaryFindEntrySIMD(table: SwissNameDictionary, key: Name):
2811cb0ef41Sopenharmony_ci    never labels Found(intptr), NotFound {
2821cb0ef41Sopenharmony_ci  FindEntry<GroupSse2Loader>(table, key)
2831cb0ef41Sopenharmony_ci      otherwise Found, NotFound;
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci@export
2871cb0ef41Sopenharmony_cimacro SwissNameDictionaryFindEntryPortable(
2881cb0ef41Sopenharmony_ci    table: SwissNameDictionary, key: Name): never labels
2891cb0ef41Sopenharmony_ciFound(intptr),
2901cb0ef41Sopenharmony_ci    NotFound {
2911cb0ef41Sopenharmony_ci  FindEntry<GroupPortableLoader>(table, key)
2921cb0ef41Sopenharmony_ci      otherwise Found, NotFound;
2931cb0ef41Sopenharmony_ci}
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci// TODO(v8:11330) Ideally, we would like to implement
2961cb0ef41Sopenharmony_ci// CodeStubAssembler::SwissNameDictionaryAdd in Torque and do the necessary
2971cb0ef41Sopenharmony_ci// switching between the two implementations with if(kUseSimd) {...} else {...}.
2981cb0ef41Sopenharmony_ci// However, Torque currently generates a call to CodeAssembler::Branch which
2991cb0ef41Sopenharmony_ci// cannot guarantee that code for the "bad" path is not generated, even if the
3001cb0ef41Sopenharmony_ci// branch can be resolved at compile time. This means that we end up trying to
3011cb0ef41Sopenharmony_ci// generate unused code using unsupported instructions.
3021cb0ef41Sopenharmony_ci@export
3031cb0ef41Sopenharmony_cimacro SwissNameDictionaryAddSIMD(
3041cb0ef41Sopenharmony_ci    table: SwissNameDictionary, key: Name, value: Object,
3051cb0ef41Sopenharmony_ci    propertyDetails: uint8): void labels Bailout {
3061cb0ef41Sopenharmony_ci  Add<GroupSse2Loader>(table, key, value, propertyDetails)
3071cb0ef41Sopenharmony_ci      otherwise Bailout;
3081cb0ef41Sopenharmony_ci}
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci@export
3111cb0ef41Sopenharmony_cimacro SwissNameDictionaryAddPortable(
3121cb0ef41Sopenharmony_ci    table: SwissNameDictionary, key: Name, value: Object,
3131cb0ef41Sopenharmony_ci    propertyDetails: uint8): void labels Bailout {
3141cb0ef41Sopenharmony_ci  Add<GroupPortableLoader>(table, key, value, propertyDetails)
3151cb0ef41Sopenharmony_ci      otherwise Bailout;
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci}
318