[VM/SIMDBC] Add simdbc64 bytecodes to allow LoadIndexed/StoreIndexed to work on untagged arrays

Issue https://github.com/dart-lang/sdk/issues/35154

Change-Id: I86db977ce6c618fbbff6186cd75c8dc84546f6f9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97302
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index 0ffd8d9..580ffee 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -748,7 +748,7 @@
     case kExternalTypedDataUint8ArrayCid:
       ASSERT(index_scale() == 1);
       if (IsExternal()) {
-        __ StoreIndexedExternalUint8(array, index, value);
+        __ StoreIndexedUntaggedUint8(array, index, value);
       } else {
         __ StoreIndexedUint8(array, index, value);
       }
@@ -760,43 +760,58 @@
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid: {
       if (IsExternal()) {
-        Unsupported(compiler);
-        UNREACHABLE();
-      }
-      if (index_scale() == 1) {
-        __ StoreIndexedUint32(array, index, value);
+        if (index_scale() == 1) {
+          __ StoreIndexedUntaggedUint32(array, index, value);
+        } else {
+          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+          __ StoreIndexedUntaggedUint32(array, temp, value);
+        }
       } else {
-        __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-        __ StoreIndexedUint32(array, temp, value);
+        if (index_scale() == 1) {
+          __ StoreIndexedUint32(array, index, value);
+        } else {
+          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+          __ StoreIndexedUint32(array, temp, value);
+        }
       }
       break;
     }
     case kTypedDataFloat32ArrayCid:
       if (IsExternal()) {
-        Unsupported(compiler);
-        UNREACHABLE();
-      }
-      if (index_scale() == 1) {
-        __ StoreIndexedFloat32(array, index, value);
-      } else if (index_scale() == 4) {
-        __ StoreIndexed4Float32(array, index, value);
+        if (index_scale() == 1) {
+          __ StoreIndexedUntaggedFloat32(array, index, value);
+        } else {
+          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+          __ StoreIndexedUntaggedFloat32(array, temp, value);
+        }
       } else {
-        __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-        __ StoreIndexedFloat32(array, temp, value);
+        if (index_scale() == 1) {
+          __ StoreIndexedFloat32(array, index, value);
+        } else if (index_scale() == 4) {
+          __ StoreIndexed4Float32(array, index, value);
+        } else {
+          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+          __ StoreIndexedFloat32(array, temp, value);
+        }
       }
       break;
     case kTypedDataFloat64ArrayCid:
       if (IsExternal()) {
-        Unsupported(compiler);
-        UNREACHABLE();
-      }
-      if (index_scale() == 1) {
-        __ StoreIndexedFloat64(array, index, value);
-      } else if (index_scale() == 8) {
-        __ StoreIndexed8Float64(array, index, value);
+        if (index_scale() == 1) {
+          __ StoreIndexedUntaggedFloat64(array, index, value);
+        } else {
+          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+          __ StoreIndexedUntaggedFloat64(array, temp, value);
+        }
       } else {
-        __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-        __ StoreIndexedFloat64(array, temp, value);
+        if (index_scale() == 1) {
+          __ StoreIndexedFloat64(array, index, value);
+        } else if (index_scale() == 8) {
+          __ StoreIndexed8Float64(array, index, value);
+        } else {
+          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+          __ StoreIndexedFloat64(array, temp, value);
+        }
       }
       break;
     default:
@@ -829,7 +844,7 @@
       case kExternalTypedDataUint8ClampedArrayCid:
         ASSERT(index_scale() == 1);
         if (IsExternal()) {
-          __ LoadIndexedExternalUint8(result, array, index);
+          __ LoadIndexedUntaggedUint8(result, array, index);
         } else {
           __ LoadIndexedUint8(result, array, index);
         }
@@ -837,7 +852,7 @@
       case kTypedDataInt8ArrayCid:
         ASSERT(index_scale() == 1);
         if (IsExternal()) {
-          __ LoadIndexedExternalInt8(result, array, index);
+          __ LoadIndexedUntaggedInt8(result, array, index);
         } else {
           __ LoadIndexedInt8(result, array, index);
         }
@@ -861,55 +876,75 @@
       case kTypedDataInt32ArrayCid:
         ASSERT(representation() == kUnboxedInt32);
         if (IsExternal()) {
-          Unsupported(compiler);
-          UNREACHABLE();
-        }
-        if (index_scale() == 1) {
-          __ LoadIndexedInt32(result, array, index);
+          if (index_scale() == 1) {
+            __ LoadIndexedUntaggedInt32(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedUntaggedInt32(result, array, temp);
+          }
         } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ LoadIndexedInt32(result, array, temp);
+          if (index_scale() == 1) {
+            __ LoadIndexedInt32(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedInt32(result, array, temp);
+          }
         }
         break;
       case kTypedDataUint32ArrayCid:
         ASSERT(representation() == kUnboxedUint32);
         if (IsExternal()) {
-          Unsupported(compiler);
-          UNREACHABLE();
-        }
-        if (index_scale() == 1) {
-          __ LoadIndexedUint32(result, array, index);
+          if (index_scale() == 1) {
+            __ LoadIndexedUntaggedUint32(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedUntaggedUint32(result, array, temp);
+          }
         } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ LoadIndexedUint32(result, array, temp);
+          if (index_scale() == 1) {
+            __ LoadIndexedUint32(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedUint32(result, array, temp);
+          }
         }
         break;
       case kTypedDataFloat32ArrayCid:
         if (IsExternal()) {
-          Unsupported(compiler);
-          UNREACHABLE();
-        }
-        if (index_scale() == 1) {
-          __ LoadIndexedFloat32(result, array, index);
-        } else if (index_scale() == 4) {
-          __ LoadIndexed4Float32(result, array, index);
+          if (index_scale() == 1) {
+            __ LoadIndexedUntaggedFloat32(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedUntaggedFloat32(result, array, temp);
+          }
         } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ LoadIndexedFloat32(result, array, temp);
+          if (index_scale() == 1) {
+            __ LoadIndexedFloat32(result, array, index);
+          } else if (index_scale() == 4) {
+            __ LoadIndexed4Float32(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedFloat32(result, array, temp);
+          }
         }
         break;
       case kTypedDataFloat64ArrayCid:
         if (IsExternal()) {
-          Unsupported(compiler);
-          UNREACHABLE();
-        }
-        if (index_scale() == 1) {
-          __ LoadIndexedFloat64(result, array, index);
-        } else if (index_scale() == 8) {
-          __ LoadIndexed8Float64(result, array, index);
+          if (index_scale() == 1) {
+            __ LoadIndexedUntaggedFloat64(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedUntaggedFloat64(result, array, temp);
+          }
         } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ LoadIndexedFloat64(result, array, temp);
+          if (index_scale() == 1) {
+            __ LoadIndexedFloat64(result, array, index);
+          } else if (index_scale() == 8) {
+            __ LoadIndexed8Float64(result, array, index);
+          } else {
+            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
+            __ LoadIndexedFloat64(result, array, temp);
+          }
         }
         break;
       default:
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 74e1ac1..7d27ec6 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -866,14 +866,17 @@
   V(AllocateTOpt,                        A_D, reg, lit, ___) \
   V(StoreIndexedTOS,                       0, ___, ___, ___) \
   V(StoreIndexed,                      A_B_C, reg, reg, reg) \
-  V(StoreIndexedUint8,                 A_B_C, reg, reg, reg) \
-  V(StoreIndexedExternalUint8,         A_B_C, reg, reg, reg) \
   V(StoreIndexedOneByteString,         A_B_C, reg, reg, reg) \
+  V(StoreIndexedUint8,                 A_B_C, reg, reg, reg) \
   V(StoreIndexedUint32,                A_B_C, reg, reg, reg) \
   V(StoreIndexedFloat32,               A_B_C, reg, reg, reg) \
   V(StoreIndexed4Float32,              A_B_C, reg, reg, reg) \
   V(StoreIndexedFloat64,               A_B_C, reg, reg, reg) \
   V(StoreIndexed8Float64,              A_B_C, reg, reg, reg) \
+  V(StoreIndexedUntaggedUint8,         A_B_C, reg, reg, reg) \
+  V(StoreIndexedUntaggedUint32,        A_B_C, reg, reg, reg) \
+  V(StoreIndexedUntaggedFloat32,       A_B_C, reg, reg, reg) \
+  V(StoreIndexedUntaggedFloat64,       A_B_C, reg, reg, reg) \
   V(NoSuchMethod,                          0, ___, ___, ___) \
   V(TailCall,                              0, ___, ___, ___) \
   V(TailCallOpt,                         A_D, reg, reg, ___) \
@@ -885,18 +888,22 @@
   V(StoreFpRelativeSlotOpt,             A_B_Y, reg, reg, reg) \
   V(LoadIndexedTOS,                        0, ___, ___, ___) \
   V(LoadIndexed,                       A_B_C, reg, reg, reg) \
+  V(LoadIndexedOneByteString,          A_B_C, reg, reg, reg) \
+  V(LoadIndexedTwoByteString,          A_B_C, reg, reg, reg) \
   V(LoadIndexedUint8,                  A_B_C, reg, reg, reg) \
   V(LoadIndexedInt8,                   A_B_C, reg, reg, reg) \
   V(LoadIndexedInt32,                  A_B_C, reg, reg, reg) \
   V(LoadIndexedUint32,                 A_B_C, reg, reg, reg) \
-  V(LoadIndexedExternalUint8,          A_B_C, reg, reg, reg) \
-  V(LoadIndexedExternalInt8,           A_B_C, reg, reg, reg) \
   V(LoadIndexedFloat32,                A_B_C, reg, reg, reg) \
   V(LoadIndexed4Float32,               A_B_C, reg, reg, reg) \
   V(LoadIndexedFloat64,                A_B_C, reg, reg, reg) \
   V(LoadIndexed8Float64,               A_B_C, reg, reg, reg) \
-  V(LoadIndexedOneByteString,          A_B_C, reg, reg, reg) \
-  V(LoadIndexedTwoByteString,          A_B_C, reg, reg, reg) \
+  V(LoadIndexedUntaggedInt8,           A_B_C, reg, reg, reg) \
+  V(LoadIndexedUntaggedUint8,          A_B_C, reg, reg, reg) \
+  V(LoadIndexedUntaggedInt32,          A_B_C, reg, reg, reg) \
+  V(LoadIndexedUntaggedUint32,         A_B_C, reg, reg, reg) \
+  V(LoadIndexedUntaggedFloat32,        A_B_C, reg, reg, reg) \
+  V(LoadIndexedUntaggedFloat64,        A_B_C, reg, reg, reg) \
   V(StoreField,                        A_B_C, reg, num, reg) \
   V(StoreFieldExt,                       A_D, reg, reg, ___) \
   V(StoreFieldTOS,                         D, num, ___, ___) \
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 85e98a0..1714769 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -2353,9 +2353,8 @@
   {
     BYTECODE(StoreIndexedFloat32, A_B_C);
     uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
-    const uint64_t value = reinterpret_cast<uint64_t>(FP[rC]);
-    const uint32_t value32 = value;
-    *reinterpret_cast<uint32_t*>(data) = value32;
+    const float value = *reinterpret_cast<float*>(&FP[rC]);
+    *reinterpret_cast<float*>(data) = value;
     DISPATCH();
   }
 
@@ -2365,10 +2364,8 @@
     RawTypedData* array = reinterpret_cast<RawTypedData*>(FP[rA]);
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    const uint64_t value = reinterpret_cast<uint64_t>(FP[rC]);
-    const uint32_t value32 = value;
-    reinterpret_cast<uint32_t*>(array->ptr()->data())[Smi::Value(index)] =
-        value32;
+    const float value = *reinterpret_cast<float*>(&FP[rC]);
+    reinterpret_cast<float*>(array->ptr()->data())[Smi::Value(index)] = value;
     DISPATCH();
   }
 
@@ -3699,7 +3696,7 @@
   }
 
   {
-    BYTECODE(StoreIndexedExternalUint8, A_B_C);
+    BYTECODE(StoreIndexedUntaggedUint8, A_B_C);
     uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
     RawSmi* value = RAW_CAST(Smi, FP[rC]);
@@ -3708,6 +3705,33 @@
   }
 
   {
+    BYTECODE(StoreIndexedUntaggedUint32, A_B_C);
+    uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
+    RawSmi* index = RAW_CAST(Smi, FP[rB]);
+    const uint32_t value = *reinterpret_cast<uint32_t*>(&FP[rC]);
+    *reinterpret_cast<uint32_t*>(array + Smi::Value(index)) = value;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreIndexedUntaggedFloat32, A_B_C);
+    uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
+    RawSmi* index = RAW_CAST(Smi, FP[rB]);
+    const float value = *reinterpret_cast<float*>(&FP[rC]);
+    *reinterpret_cast<float*>(array + Smi::Value(index)) = value;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreIndexedUntaggedFloat64, A_B_C);
+    uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
+    RawSmi* index = RAW_CAST(Smi, FP[rB]);
+    const double value = *reinterpret_cast<double*>(&FP[rC]);
+    *reinterpret_cast<double*>(array + Smi::Value(index)) = value;
+    DISPATCH();
+  }
+
+  {
     BYTECODE(StoreIndexedOneByteString, A_B_C);
     RawOneByteString* array = RAW_CAST(OneByteString, FP[rA]);
     RawSmi* index = RAW_CAST(Smi, FP[rB]);
@@ -3837,7 +3861,7 @@
     BYTECODE(LoadIndexedUint32, A_B_C);
     const uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
     const uint32_t value = *reinterpret_cast<const uint32_t*>(data);
-    FP[rA] = reinterpret_cast<RawObject*>(value);
+    *reinterpret_cast<uint32_t*>(&FP[rA]) = value;
     DISPATCH();
   }
 
@@ -3845,23 +3869,60 @@
     BYTECODE(LoadIndexedInt32, A_B_C);
     const uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
     const int32_t value = *reinterpret_cast<const int32_t*>(data);
-    FP[rA] = reinterpret_cast<RawObject*>(value);
+    *reinterpret_cast<int32_t*>(&FP[rA]) = value;
     DISPATCH();
   }
 
   {
-    BYTECODE(LoadIndexedExternalUint8, A_B_C);
+    BYTECODE(LoadIndexedUntaggedInt8, A_B_C);
     uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = Smi::New(data[Smi::Value(index)]);
+    FP[rA] = Smi::New(*reinterpret_cast<int8_t*>(data + Smi::Value(index)));
     DISPATCH();
   }
 
   {
-    BYTECODE(LoadIndexedExternalInt8, A_B_C);
-    int8_t* data = reinterpret_cast<int8_t*>(FP[rB]);
+    BYTECODE(LoadIndexedUntaggedUint8, A_B_C);
+    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
     RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = Smi::New(data[Smi::Value(index)]);
+    FP[rA] = Smi::New(*reinterpret_cast<uint8_t*>(data + Smi::Value(index)));
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadIndexedUntaggedInt32, A_B_C);
+    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    const int32_t value = *reinterpret_cast<int32_t*>(data + Smi::Value(index));
+    *reinterpret_cast<int32_t*>(&FP[rA]) = value;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadIndexedUntaggedUint32, A_B_C);
+    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    const uint32_t value =
+        *reinterpret_cast<uint32_t*>(data + Smi::Value(index));
+    *reinterpret_cast<uint32_t*>(&FP[rA]) = value;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadIndexedUntaggedFloat32, A_B_C);
+    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    const float value = *reinterpret_cast<float*>(data + Smi::Value(index));
+    *reinterpret_cast<float*>(&FP[rA]) = value;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadIndexedUntaggedFloat64, A_B_C);
+    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    const double value = *reinterpret_cast<double*>(data + Smi::Value(index));
+    *reinterpret_cast<double*>(&FP[rA]) = value;
     DISPATCH();
   }