[vm] Revert 3fcf660e with the correct fix for --no-sound-null-safety.

Insert CheckNull instructions if in AOT mode prior to checking the
index for being within the bounds in inlined indexing operations.
If we're in --sound-null-safety mode, they'll be canonicalized away
since the indices won't be nullable anyway.

Fixes https://github.com/dart-lang/sdk/issues/52910.

TEST=corelib{,_2}/list_removeat_test and
  co19_2/LibTest/core/String/codeUnitAt_A03_t01 on
  vm-kernel-precomp-linux-release-x64-try

Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-x64-try
Change-Id: I37212e94c7c5032c75709e3f0bb91734cbc705cd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313507
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 1934704..3a79ea5 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2773,6 +2773,16 @@
       new (Z) Value(*array), Slot::GetLengthFieldForArrayCid(array_cid),
       call->source());
   *cursor = flow_graph->AppendTo(*cursor, length, nullptr, FlowGraph::kValue);
+  if (CompilerState::Current().is_aot()) {
+    // Add a null-check in case the index argument is known to be compatible
+    // but possibly nullable. By inserting the null-check, we can allow the
+    // unbox instruction later inserted to be non-speculative.
+    auto* const null_check = new (Z) CheckNullInstr(
+        new (Z) Value(*index), Symbols::Index(), call->deopt_id(),
+        call->source(), CheckNullInstr::kArgumentError);
+    *cursor = flow_graph->AppendTo(*cursor, null_check, call->env(),
+                                   FlowGraph::kEffect);
+  }
   *index = flow_graph->CreateCheckBound(length, *index, call->deopt_id());
   *cursor =
       flow_graph->AppendTo(*cursor, *index, call->env(), FlowGraph::kValue);
@@ -3483,6 +3493,16 @@
   cursor = flow_graph->AppendTo(cursor, length, nullptr, FlowGraph::kValue);
 
   // Bounds check.
+  if (CompilerState::Current().is_aot()) {
+    // Add a null-check in case the index argument is known to be compatible
+    // but possibly nullable. By inserting the null-check, we can allow the
+    // unbox instruction later inserted to be non-speculative.
+    auto* const null_check = new (Z)
+        CheckNullInstr(new (Z) Value(index), Symbols::Index(), call->deopt_id(),
+                       call->source(), CheckNullInstr::kArgumentError);
+    cursor = flow_graph->AppendTo(cursor, null_check, call->env(),
+                                  FlowGraph::kEffect);
+  }
   index = flow_graph->CreateCheckBound(length, index, call->deopt_id());
   cursor = flow_graph->AppendTo(cursor, index, call->env(), FlowGraph::kValue);
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 33da0ec..8bbf960 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -560,26 +560,12 @@
 
   // Allocate and initialize the null instance.
   // 'null_' must be the first object allocated as it is used in allocation to
-  // clear the object.
+  // clear the pointer fields of objects.
   {
     uword address =
         heap->Allocate(thread, Instance::InstanceSize(), Heap::kOld);
     null_ = static_cast<InstancePtr>(address + kHeapObjectTag);
-    // The call below is using 'null_' to initialize itself.
-    //
-    // TODO(52910): Change the below to
-    //   InitializeObjectVariant<Instance>(address, kNullCid);
-    // after we've fixed the unboxing of the null object without checking for
-    // null first when --no-sound-null-safety is on. (This is a stopgap so that
-    // those bad unboxings pull out really large values that almost certainly
-    // will fail, which was the old status quo.)
-    const intptr_t ptr_field_end_offset =
-        Instance::InstanceSize() - (Instance::ContainsCompressedPointers()
-                                        ? kCompressedWordSize
-                                        : kWordSize);
-    InitializeObject(address, kNullCid, Instance::InstanceSize(),
-                     Instance::ContainsCompressedPointers(),
-                     sizeof(UntaggedObject), ptr_field_end_offset);
+    InitializeObjectVariant<Instance>(address, kNullCid);
     null_->untag()->SetCanonical();
   }