[vm] Use LoadWordFromPool in AssertAssignable on ARMs instead of raw ldr

Pool offsets might be not encodable as immediates. However
 InstructionPattern::DecodeLoadWordFromPool can decode anything that
 LoadWordFromPool can emit.

Fixes https://github.com/flutter/flutter/issues/18332

Change-Id: I8873f523bb65844e7256c0c3030edea4cc591830
Reviewed-on: https://dart-review.googlesource.com/59640
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index ab6f811..10b2c61 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -767,6 +767,13 @@
 
   void LoadIsolate(Register rd);
 
+  // Load word from pool from the given offset using encoding that
+  // InstructionPattern::DecodeLoadWordFromPool can decode.
+  void LoadWordFromPoolOffset(Register rd,
+                              int32_t offset,
+                              Register pp,
+                              Condition cond);
+
   void LoadObject(Register rd, const Object& object, Condition cond = AL);
   void LoadUniqueObject(Register rd, const Object& object, Condition cond = AL);
   void LoadFunctionFromCalleePool(Register dst,
@@ -1110,11 +1117,6 @@
   void BindARMv6(Label* label);
   void BindARMv7(Label* label);
 
-  void LoadWordFromPoolOffset(Register rd,
-                              int32_t offset,
-                              Register pp,
-                              Condition cond);
-
   void BranchLink(const ExternalLabel* label);
 
   class CodeComment : public ZoneAllocated {
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index b0d94c2..368e4a3 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1493,6 +1493,10 @@
   void LoadImmediate(Register reg, int64_t imm);
   void LoadDImmediate(VRegister reg, double immd);
 
+  // Load word from pool from the given offset using encoding that
+  // InstructionPattern::DecodeLoadWordFromPool can decode.
+  void LoadWordFromPoolOffset(Register dst, uint32_t offset, Register pp = PP);
+
   void PushObject(const Object& object) {
     LoadObject(TMP, object);
     Push(TMP);
@@ -1618,7 +1622,6 @@
 
   bool constant_pool_allowed_;
 
-  void LoadWordFromPoolOffset(Register dst, uint32_t offset, Register pp = PP);
   void LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset);
 
   void LoadObjectHelper(Register dst, const Object& obj, bool is_unique);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 6d150d3..6233ee3 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -743,7 +743,8 @@
   __ LoadField(R9,
                FieldAddress(kDstTypeReg,
                             AbstractType::type_test_stub_entry_point_offset()));
-  __ ldr(kSubtypeTestCacheReg, Address(PP, sub_type_cache_offset));
+  __ LoadWordFromPoolOffset(kSubtypeTestCacheReg, sub_type_cache_offset, PP,
+                            AL);
   __ blx(R9);
   EmitCallsiteMetadata(token_pos, deopt_id, RawPcDescriptors::kOther, locs);
   __ Bind(&done);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index cef314e..5a11f70 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -712,7 +712,7 @@
   const intptr_t sub_type_cache_index = __ object_pool_wrapper().AddObject(
       Object::null_object(), Patchability::kPatchable);
   const intptr_t sub_type_cache_offset =
-      ObjectPool::element_offset(sub_type_cache_index);
+      ObjectPool::element_offset(sub_type_cache_index) - kHeapObjectTag;
   const intptr_t dst_name_index =
       __ object_pool_wrapper().AddObject(dst_name, Patchability::kPatchable);
   ASSERT((sub_type_cache_index + 1) == dst_name_index);
@@ -721,7 +721,7 @@
   __ LoadField(R9,
                FieldAddress(kDstTypeReg,
                             AbstractType::type_test_stub_entry_point_offset()));
-  __ ldr(kSubtypeTestCacheReg, Address(PP, sub_type_cache_offset));
+  __ LoadWordFromPoolOffset(kSubtypeTestCacheReg, sub_type_cache_offset);
   __ blr(R9);
   EmitCallsiteMetadata(token_pos, deopt_id, RawPcDescriptors::kOther, locs);
   __ Bind(&done);
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h
index 0738d64..e11c947 100644
--- a/runtime/vm/instructions_arm.h
+++ b/runtime/vm/instructions_arm.h
@@ -42,6 +42,10 @@
   // address of the first instruction in the sequence.  Returns the register
   // being loaded and the index in the pool being read from in the output
   // parameters 'reg' and 'index' respectively.
+  // IMPORANT: When generating code loading values from pool on ARM use
+  // LoadWordFromPool macro instruction instead of emitting direct load.
+  // The macro instruction takes care of pool offsets that can't be
+  // encoded as immediates.
   static uword DecodeLoadWordFromPool(uword end,
                                       Register* reg,
                                       intptr_t* index);
diff --git a/runtime/vm/instructions_arm64.h b/runtime/vm/instructions_arm64.h
index 10c74f5..1355cfe 100644
--- a/runtime/vm/instructions_arm64.h
+++ b/runtime/vm/instructions_arm64.h
@@ -42,6 +42,10 @@
   // address of the first instruction in the sequence.  Returns the register
   // being loaded and the index in the pool being read from in the output
   // parameters 'reg' and 'index' respectively.
+  // IMPORANT: When generating code loading values from pool on ARM64 use
+  // LoadWordFromPool macro instruction instead of emitting direct load.
+  // The macro instruction takes care of pool offsets that can't be
+  // encoded as immediates.
   static uword DecodeLoadWordFromPool(uword end,
                                       Register* reg,
                                       intptr_t* index);