Revert "[vm] Add data field to TypedData"

This reverts commit d1085e80bed1440d2981def3d37b36dcd4d57d9f.

Reason for revert: performance regressions.

Original change's description:
> [vm] Add data field to TypedData
> 
> This is the first step towards unification of TypedData and
> ExternalTypedData.
> 
> Issue: https://github.com/dart-lang/sdk/issues/34796
> Change-Id: I8aec72030e251f9cd9f00fc5073f8e42b83a8d17
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/79430
> Commit-Queue: Alexander Markov <alexmarkov@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Reviewed-by: Ryan Macnak <rmacnak@google.com>

TBR=vegorov@google.com,kustermann@google.com,rmacnak@google.com,alexmarkov@google.com,regis@google.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Issue: https://github.com/dart-lang/sdk/issues/34796
Change-Id: Ia11d8c3af0af29d49c3dbf36a3fe7041fbf9aae3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97166
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 972d93e..126d193 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -3372,8 +3372,7 @@
       Deserializer::InitializeHeader(
           data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical);
       data->ptr()->length_ = Smi::New(length);
-      data->ResetData();
-      uint8_t* cdata = data->ptr()->data();
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
       d->ReadBytes(cdata, length_in_bytes);
     }
   }
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index cf5264e..c00607e 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -165,8 +165,6 @@
   __ LoadImmediate(R8, 0);                                                     \
   __ mov(R9, Operand(R8));                                                     \
   __ AddImmediate(R3, R0, target::TypedData::InstanceSize() - 1);              \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      R0, FieldAddress(R0, target::TypedData::data_offset()), R3);             \
   Label init_loop;                                                             \
   __ Bind(&init_loop);                                                         \
   __ AddImmediate(R3, 2 * target::kWordSize);                                  \
@@ -695,12 +693,13 @@
   // R4 = n ~/ _DIGIT_BITS
   __ Asr(R4, R3, Operand(5));
   // R8 = &x_digits[0]
-  __ ldr(R8, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R8, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // NOTFP = &x_digits[x_used]
   __ add(NOTFP, R8, Operand(R0, LSL, 1));
   // R6 = &r_digits[1]
-  __ ldr(R6, FieldAddress(R2, target::TypedData::data_offset()));
-  __ add(R6, R6, Operand(kBytesPerBigIntDigit));
+  __ add(R6, R2,
+         Operand(target::TypedData::data_offset() - kHeapObjectTag +
+                 kBytesPerBigIntDigit));
   // R6 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1]
   __ add(R4, R4, Operand(R0, ASR, 1));
   __ add(R6, R6, Operand(R4, LSL, 2));
@@ -734,9 +733,9 @@
   // R4 = n ~/ _DIGIT_BITS
   __ Asr(R4, R3, Operand(5));
   // R6 = &r_digits[0]
-  __ ldr(R6, FieldAddress(R2, target::TypedData::data_offset()));
+  __ add(R6, R2, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // NOTFP = &x_digits[n ~/ _DIGIT_BITS]
-  __ ldr(NOTFP, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   __ add(NOTFP, NOTFP, Operand(R4, LSL, 2));
   // R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1]
   __ add(R4, R4, Operand(1));
@@ -774,17 +773,17 @@
   // R0 = used, R1 = digits
   __ ldrd(R0, R1, SP, 3 * target::kWordSize);
   // R1 = &digits[0]
-  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R2 = a_used, R3 = a_digits
   __ ldrd(R2, R3, SP, 1 * target::kWordSize);
   // R3 = &a_digits[0]
-  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R8 = r_digits
   __ ldr(R8, Address(SP, 0 * target::kWordSize));
   // R8 = &r_digits[0]
-  __ ldr(R8, FieldAddress(R8, target::TypedData::data_offset()));
+  __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // NOTFP = &digits[a_used >> 1], a_used is Smi.
   __ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -834,17 +833,17 @@
   // R0 = used, R1 = digits
   __ ldrd(R0, R1, SP, 3 * target::kWordSize);
   // R1 = &digits[0]
-  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
+  __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R2 = a_used, R3 = a_digits
   __ ldrd(R2, R3, SP, 1 * target::kWordSize);
   // R3 = &a_digits[0]
-  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R8 = r_digits
   __ ldr(R8, Address(SP, 0 * target::kWordSize));
   // R8 = &r_digits[0]
-  __ ldr(R8, FieldAddress(R8, target::TypedData::data_offset()));
+  __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // NOTFP = &digits[a_used >> 1], a_used is Smi.
   __ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -913,8 +912,8 @@
   Label done;
   // R3 = x, no_op if x == 0
   __ ldrd(R0, R1, SP, 5 * target::kWordSize);  // R0 = xi as Smi, R1 = x_digits.
+  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
-  __ ldr(R3, Address(R3, R0, LSL, 1));
   __ tst(R3, Operand(R3));
   __ b(&done, EQ);
 
@@ -925,13 +924,13 @@
 
   // R4 = mip = &m_digits[i >> 1]
   __ ldrd(R0, R1, SP, 3 * target::kWordSize);  // R0 = i as Smi, R1 = m_digits.
-  __ ldr(R4, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R4, R4, Operand(R0, LSL, 1));
+  __ add(R1, R1, Operand(R0, LSL, 1));
+  __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R9 = ajp = &a_digits[j >> 1]
   __ ldrd(R0, R1, SP, 1 * target::kWordSize);  // R0 = j as Smi, R1 = a_digits.
-  __ ldr(R9, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R9, R9, Operand(R0, LSL, 1));
+  __ add(R1, R1, Operand(R0, LSL, 1));
+  __ add(R9, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R1 = c = 0
   __ mov(R1, Operand(0));
@@ -1013,8 +1012,8 @@
 
   // R4 = xip = &x_digits[i >> 1]
   __ ldrd(R2, R3, SP, 2 * target::kWordSize);  // R2 = i as Smi, R3 = x_digits
-  __ ldr(R4, FieldAddress(R3, target::TypedData::data_offset()));
-  __ add(R4, R4, Operand(R2, LSL, 1));
+  __ add(R3, R3, Operand(R2, LSL, 1));
+  __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R3 = x = *xip++, return if x == 0
   Label x_zero;
@@ -1024,8 +1023,8 @@
 
   // NOTFP = ajp = &a_digits[i]
   __ ldr(R1, Address(SP, 1 * target::kWordSize));  // a_digits
-  __ ldr(NOTFP, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(NOTFP, NOTFP, Operand(R2, LSL, 2));  // j == 2*i, i is Smi.
+  __ add(R1, R1, Operand(R2, LSL, 2));             // j == 2*i, i is Smi.
+  __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R8:R0 = t = x*x + *ajp
   __ ldr(R0, Address(NOTFP, 0));
@@ -1113,24 +1112,24 @@
   //   return 1;
   // }
 
-  // R4 = &args[0]
+  // R4 = args
   __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
-  __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R3 = rho = args[2]
-  __ ldr(R3, Address(R4, 2 * kBytesPerBigIntDigit));
+  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
+                                  2 * kBytesPerBigIntDigit));
 
   // R2 = digits[i >> 1]
   __ ldrd(R0, R1, SP, 0 * target::kWordSize);  // R0 = i as Smi, R1 = digits
+  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R2, R2, Operand(R0, LSL, 1));
-  __ ldr(R2, Address(R2));
 
   // R1:R0 = t = rho*d
   __ umull(R0, R1, R2, R3);
 
   // args[4] = t mod DIGIT_BASE = low32(t)
-  __ str(R0, Address(R4, 4 * kBytesPerBigIntDigit));
+  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+                                  4 * kBytesPerBigIntDigit));
 
   __ mov(R0, Operand(target::ToRawSmi(1)));  // One digit processed.
   __ Ret();
@@ -1496,7 +1495,6 @@
   // Field '_state'.
   __ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
-  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
 
   const int64_t disp_0 =
       target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
@@ -1504,13 +1502,13 @@
       disp_0 + target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
 
   __ LoadImmediate(R0, a_int32_value);
-  __ LoadFromOffset(kWord, R2, R1, disp_0);
-  __ LoadFromOffset(kWord, R3, R1, disp_1);
+  __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
+  __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag);
   __ mov(R8, Operand(0));  // Zero extend unsigned _state[kSTATE_HI].
   // Unsigned 32-bit multiply and 64-bit accumulate into R8:R3.
   __ umlal(R3, R8, R0, R2);  // R8:R3 <- R8:R3 + R0 * R2.
-  __ StoreToOffset(kWord, R3, R1, disp_0);
-  __ StoreToOffset(kWord, R8, R1, disp_1);
+  __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
+  __ StoreToOffset(kWord, R8, R1, disp_1 - kHeapObjectTag);
   ASSERT(target::ToRawSmi(0) == 0);
   __ eor(R0, R0, Operand(R0));
   __ Ret();
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 0153c00..6ba42cd 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -177,8 +177,6 @@
   /* data area to be initialized. */                                           \
   __ mov(R3, ZR);                                                              \
   __ AddImmediate(R2, R0, target::TypedData::InstanceSize() - 1);              \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      R0, FieldAddress(R0, target::TypedData::data_offset()), R2);             \
   Label init_loop, done;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmp(R2, Operand(R1));                                                     \
@@ -603,12 +601,13 @@
   // R0 = n ~/ (2*_DIGIT_BITS)
   __ AsrImmediate(R0, R5, 6);
   // R6 = &x_digits[0]
-  __ ldr(R6, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R6, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // R7 = &x_digits[2*R2]
   __ add(R7, R6, Operand(R2, LSL, 3));
   // R8 = &r_digits[2*1]
-  __ ldr(R8, FieldAddress(R4, target::TypedData::data_offset()));
-  __ add(R8, R8, Operand(2 * kBytesPerBigIntDigit));
+  __ add(R8, R4,
+         Operand(target::TypedData::data_offset() - kHeapObjectTag +
+                 2 * kBytesPerBigIntDigit));
   // R8 = &r_digits[2*(R2 + n ~/ (2*_DIGIT_BITS) + 1)]
   __ add(R0, R0, Operand(R2));
   __ add(R8, R8, Operand(R0, LSL, 3));
@@ -646,9 +645,9 @@
   // R0 = n ~/ (2*_DIGIT_BITS)
   __ AsrImmediate(R0, R5, 6);
   // R8 = &r_digits[0]
-  __ ldr(R8, FieldAddress(R4, target::TypedData::data_offset()));
+  __ add(R8, R4, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // R7 = &x_digits[2*(n ~/ (2*_DIGIT_BITS))]
-  __ ldr(R7, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R7, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   __ add(R7, R7, Operand(R0, LSL, 3));
   // R6 = &r_digits[2*(R2 - n ~/ (2*_DIGIT_BITS) - 1)]
   __ add(R0, R0, Operand(1));
@@ -690,19 +689,19 @@
   __ add(R2, R2, Operand(2));  // used > 0, Smi. R2 = used + 1, round up.
   __ add(R2, ZR, Operand(R2, ASR, 2));  // R2 = num of digit pairs to process.
   // R3 = &digits[0]
-  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R4 = a_used, R5 = a_digits
   __ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
   __ add(R4, R4, Operand(2));  // a_used > 0, Smi. R4 = a_used + 1, round up.
   __ add(R4, ZR, Operand(R4, ASR, 2));  // R4 = num of digit pairs to process.
   // R5 = &a_digits[0]
-  __ ldr(R5, FieldAddress(R5, target::TypedData::data_offset()));
+  __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R6 = r_digits
   __ ldr(R6, Address(SP, 0 * target::kWordSize));
   // R6 = &r_digits[0]
-  __ ldr(R6, FieldAddress(R6, target::TypedData::data_offset()));
+  __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R7 = &digits[a_used rounded up to even number].
   __ add(R7, R3, Operand(R4, LSL, 3));
@@ -756,19 +755,19 @@
   __ add(R2, R2, Operand(2));  // used > 0, Smi. R2 = used + 1, round up.
   __ add(R2, ZR, Operand(R2, ASR, 2));  // R2 = num of digit pairs to process.
   // R3 = &digits[0]
-  __ ldr(R3, FieldAddress(R3, target::TypedData::data_offset()));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R4 = a_used, R5 = a_digits
   __ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
   __ add(R4, R4, Operand(2));  // a_used > 0, Smi. R4 = a_used + 1, round up.
   __ add(R4, ZR, Operand(R4, ASR, 2));  // R4 = num of digit pairs to process.
   // R5 = &a_digits[0]
-  __ ldr(R5, FieldAddress(R5, target::TypedData::data_offset()));
+  __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R6 = r_digits
   __ ldr(R6, Address(SP, 0 * target::kWordSize));
   // R6 = &r_digits[0]
-  __ ldr(R6, FieldAddress(R6, target::TypedData::data_offset()));
+  __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R7 = &digits[a_used rounded up to even number].
   __ add(R7, R3, Operand(R4, LSL, 3));
@@ -839,9 +838,8 @@
   // R3 = x, no_op if x == 0
   // R0 = xi as Smi, R1 = x_digits.
   __ ldp(R0, R1, Address(SP, 5 * target::kWordSize, Address::PairOffset));
+  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R3, R3, Operand(R0, LSL, 1));
-  __ ldr(R3, Address(R3, 0));
   __ tst(R3, Operand(R3));
   __ b(&done, EQ);
 
@@ -854,14 +852,14 @@
   // R4 = mip = &m_digits[i >> 1]
   // R0 = i as Smi, R1 = m_digits.
   __ ldp(R0, R1, Address(SP, 3 * target::kWordSize, Address::PairOffset));
-  __ ldr(R4, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R4, R4, Operand(R0, LSL, 1));
+  __ add(R1, R1, Operand(R0, LSL, 1));
+  __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R5 = ajp = &a_digits[j >> 1]
   // R0 = j as Smi, R1 = a_digits.
   __ ldp(R0, R1, Address(SP, 1 * target::kWordSize, Address::PairOffset));
-  __ ldr(R5, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R5, R5, Operand(R0, LSL, 1));
+  __ add(R1, R1, Operand(R0, LSL, 1));
+  __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R1 = c = 0
   __ mov(R1, ZR);
@@ -948,8 +946,8 @@
   // R4 = xip = &x_digits[i >> 1]
   // R2 = i as Smi, R3 = x_digits
   __ ldp(R2, R3, Address(SP, 2 * target::kWordSize, Address::PairOffset));
-  __ ldr(R4, FieldAddress(R3, target::TypedData::data_offset()));
-  __ add(R4, R4, Operand(R2, LSL, 1));
+  __ add(R3, R3, Operand(R2, LSL, 1));
+  __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R3 = x = *xip++, return if x == 0
   Label x_zero;
@@ -959,8 +957,8 @@
 
   // R5 = ajp = &a_digits[i]
   __ ldr(R1, Address(SP, 1 * target::kWordSize));  // a_digits
-  __ ldr(R5, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R5, R5, Operand(R2, LSL, 2));  // j == 2*i, i is Smi.
+  __ add(R1, R1, Operand(R2, LSL, 2));             // j == 2*i, i is Smi.
+  __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R6:R1 = t = x*x + *ajp
   __ ldr(R0, Address(R5, 0));
@@ -1078,19 +1076,18 @@
   //   return 2;
   // }
 
-  // R4 = &args[0]
+  // R4 = args
   __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
-  __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R3 = yt = args[0..1]
-  __ ldr(R3, Address(R4, 0));
+  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R2 = dh = digits[(i >> 1) - 1 .. i >> 1]
   // R0 = i as Smi, R1 = digits
   __ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
-  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ ldr(R2, Address(R1, -kBytesPerBigIntDigit));
+  __ ldr(R2, FieldAddress(
+                 R1, target::TypedData::data_offset() - kBytesPerBigIntDigit));
 
   // R0 = qd = (DIGIT_MASK << 32) | DIGIT_MASK = -1
   __ movn(R0, Immediate(0), 0);
@@ -1101,7 +1098,8 @@
   __ b(&return_qd, EQ);
 
   // R1 = dl = digits[(i >> 1) - 3 .. (i >> 1) - 2]
-  __ ldr(R1, Address(R1, -3 * kBytesPerBigIntDigit));
+  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset() -
+                                  3 * kBytesPerBigIntDigit));
 
   // R5 = yth = yt >> 32
   __ orr(R5, ZR, Operand(R3, LSR, 32));
@@ -1205,7 +1203,8 @@
 
   __ Bind(&return_qd);
   // args[2..3] = qd
-  __ str(R0, Address(R4, 2 * kBytesPerBigIntDigit));
+  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+                                  2 * kBytesPerBigIntDigit));
 
   __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
@@ -1222,25 +1221,25 @@
   //   return 2;
   // }
 
-  // R4 = &args[0]
+  // R4 = args
   __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
-  __ ldr(R4, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R3 = rho = args[2..3]
-  __ ldr(R3, Address(R4, 2 * kBytesPerBigIntDigit));
+  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
+                                  2 * kBytesPerBigIntDigit));
 
   // R2 = digits[i >> 1 .. (i >> 1) + 1]
   // R0 = i as Smi, R1 = digits
   __ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
+  __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
-  __ add(R2, R2, Operand(R0, LSL, 1));
-  __ ldr(R2, Address(R2, 0));
 
   // R0 = rho*d mod DIGIT_BASE
   __ mul(R0, R2, R3);  // R0 = low64(R2*R3).
 
   // args[4 .. 5] = R0
-  __ str(R0, Address(R4, 4 * kBytesPerBigIntDigit));
+  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+                                  4 * kBytesPerBigIntDigit));
 
   __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
@@ -1558,10 +1557,10 @@
   // Field '_state'.
   __ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
 
-  // Address of _state[0].
-  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset()));
+  // Addresses of _state[0].
   const int64_t disp =
-      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
+      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid) -
+      kHeapObjectTag;
 
   __ LoadImmediate(R0, a_int_value);
   __ LoadFromOffset(R2, R1, disp);
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 88c48f9..392d129 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -167,8 +167,6 @@
   /* data area to be initialized. */                                           \
   __ xorl(ECX, ECX); /* Zero. */                                               \
   __ leal(EDI, FieldAddress(EAX, target::TypedData::InstanceSize()));          \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      EAX, FieldAddress(EAX, target::TypedData::data_offset()), EDI);          \
   Label done, init_loop;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmpl(EDI, EBX);                                                           \
@@ -715,14 +713,14 @@
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
   __ movl(ESI, ECX);
   __ sarl(ESI, Immediate(5));  // ESI = n ~/ _DIGIT_BITS.
-  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
-  __ leal(EBX, Address(EBX, ESI, TIMES_4, 0));
+  __ leal(EBX,
+          FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
   __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // x_used > 0, Smi.
   __ SmiUntag(ESI);
   __ decl(ESI);
   __ xorl(EAX, EAX);  // EAX = 0.
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
-  __ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
+  __ movl(EDX,
+          FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
   __ shldl(EAX, EDX, ECX);
   __ movl(Address(EBX, ESI, TIMES_4, kBytesPerBigIntDigit), EAX);
   Label last;
@@ -731,7 +729,9 @@
   Label loop;
   __ Bind(&loop);
   __ movl(EAX, EDX);
-  __ movl(EDX, Address(EDI, ESI, TIMES_4, -kBytesPerBigIntDigit));
+  __ movl(EDX, FieldAddress(
+                   EDI, ESI, TIMES_4,
+                   target::TypedData::data_offset() - kBytesPerBigIntDigit));
   __ shldl(EAX, EDX, ECX);
   __ movl(Address(EBX, ESI, TIMES_4, 0), EAX);
   __ decl(ESI);
@@ -764,12 +764,12 @@
   __ SmiUntag(ESI);
   __ decl(ESI);
   // EDI = &x_digits[x_used - 1].
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
-  __ leal(EDI, Address(EDI, ESI, TIMES_4, 0));
+  __ leal(EDI,
+          FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
   __ subl(ESI, EDX);
   // EBX = &r_digits[x_used - 1 - (n ~/ 32)].
-  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
-  __ leal(EBX, Address(EBX, ESI, TIMES_4, 0));
+  __ leal(EBX,
+          FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
   __ negl(ESI);
   __ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
   Label last;
@@ -811,10 +811,6 @@
   __ SmiUntag(ECX);                                   // a_used > 0.
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
 
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
-  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
-  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
-
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subl(EAX, ECX);
   __ incl(EAX);  // To account for the extra test between loops.
@@ -824,9 +820,12 @@
   Label add_loop;
   __ Bind(&add_loop);
   // Loop a_used times, ECX = a_used, ECX > 0.
-  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
-  __ adcl(EAX, Address(ESI, EDX, TIMES_4, 0));
-  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ adcl(EAX,
+          FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -839,9 +838,11 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop used - a_used times, ECX = used - a_used, ECX > 0.
-  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
   __ adcl(EAX, Immediate(0));
-  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -849,7 +850,8 @@
   __ Bind(&last_carry);
   __ movl(EAX, Immediate(0));
   __ adcl(EAX, Immediate(0));
-  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
 
   // Restore THR and return.
   __ popl(THR);
@@ -875,10 +877,6 @@
   __ SmiUntag(ECX);                                   // a_used > 0.
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
 
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
-  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
-  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
-
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subl(EAX, ECX);
   __ incl(EAX);  // To account for the extra test between loops.
@@ -888,9 +886,12 @@
   Label sub_loop;
   __ Bind(&sub_loop);
   // Loop a_used times, ECX = a_used, ECX > 0.
-  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
-  __ sbbl(EAX, Address(ESI, EDX, TIMES_4, 0));
-  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ sbbl(EAX,
+          FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -903,9 +904,11 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop used - a_used times, ECX = used - a_used, ECX > 0.
-  __ movl(EAX, Address(EDI, EDX, TIMES_4, 0));
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
   __ sbbl(EAX, Immediate(0));
-  __ movl(Address(EBX, EDX, TIMES_4, 0), EAX);
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -950,8 +953,8 @@
   // EBX = x, no_op if x == 0
   __ movl(ECX, Address(ESP, 7 * target::kWordSize));  // x_digits
   __ movl(EAX, Address(ESP, 6 * target::kWordSize));  // xi is Smi
-  __ movl(EBX, FieldAddress(ECX, target::TypedData::data_offset()));
-  __ movl(EBX, Address(EBX, EAX, TIMES_2, 0));
+  __ movl(EBX,
+          FieldAddress(ECX, EAX, TIMES_2, target::TypedData::data_offset()));
   __ testl(EBX, EBX);
   __ j(ZERO, &no_op, Assembler::kNearJump);
 
@@ -967,14 +970,14 @@
   // EDI = mip = &m_digits[i >> 1]
   __ movl(EDI, Address(ESP, 6 * target::kWordSize));  // m_digits
   __ movl(EAX, Address(ESP, 5 * target::kWordSize));  // i is Smi
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
-  __ leal(EDI, Address(EDI, EAX, TIMES_2, 0));
+  __ leal(EDI,
+          FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // ESI = ajp = &a_digits[j >> 1]
   __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // a_digits
   __ movl(EAX, Address(ESP, 3 * target::kWordSize));  // j is Smi
-  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
-  __ leal(ESI, Address(ESI, EAX, TIMES_2, 0));
+  __ leal(ESI,
+          FieldAddress(ESI, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // Save n
   __ pushl(EDX);
@@ -1071,8 +1074,8 @@
   // EDI = xip = &x_digits[i >> 1]
   __ movl(EDI, Address(ESP, 4 * target::kWordSize));  // x_digits
   __ movl(EAX, Address(ESP, 3 * target::kWordSize));  // i is Smi
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
-  __ leal(EDI, Address(EDI, EAX, TIMES_2, 0));
+  __ leal(EDI,
+          FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // EBX = x = *xip++, return if x == 0
   Label x_zero;
@@ -1087,8 +1090,8 @@
 
   // ESI = ajp = &a_digits[i]
   __ movl(ESI, Address(ESP, 3 * target::kWordSize));  // a_digits
-  __ movl(ESI, FieldAddress(ESI, target::TypedData::data_offset()));
-  __ leal(ESI, Address(ESI, EAX, TIMES_4, 0));
+  __ leal(ESI,
+          FieldAddress(ESI, EAX, TIMES_4, target::TypedData::data_offset()));
 
   // EDX:EAX = t = x*x + *ajp
   __ movl(EAX, EBX);
@@ -1193,18 +1196,18 @@
   //   return 1;
   // }
 
-  // EDI = &args[0]
+  // EDI = args
   __ movl(EDI, Address(ESP, 3 * target::kWordSize));  // args
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
 
   // ECX = yt = args[1]
-  __ movl(ECX, Address(EDI, kBytesPerBigIntDigit));
+  __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
+                                     kBytesPerBigIntDigit));
 
   // EBX = dp = &digits[i >> 1]
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // digits
   __ movl(EAX, Address(ESP, 1 * target::kWordSize));  // i is Smi
-  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
-  __ leal(EBX, Address(EBX, EAX, TIMES_2, 0));
+  __ leal(EBX,
+          FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // EDX = dh = dp[0]
   __ movl(EDX, Address(EBX, 0));
@@ -1225,7 +1228,9 @@
 
   __ Bind(&return_qd);
   // args[2] = qd
-  __ movl(Address(EDI, 2 * kBytesPerBigIntDigit), EAX);
+  __ movl(FieldAddress(
+              EDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
+          EAX);
 
   __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
@@ -1242,24 +1247,26 @@
   //   return 1;
   // }
 
-  // EDI = &args[0]
+  // EDI = args
   __ movl(EDI, Address(ESP, 3 * target::kWordSize));  // args
-  __ movl(EDI, FieldAddress(EDI, target::TypedData::data_offset()));
 
   // ECX = rho = args[2]
-  __ movl(ECX, Address(EDI, 2 * kBytesPerBigIntDigit));
+  __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
+                                     2 * kBytesPerBigIntDigit));
 
   // EAX = digits[i >> 1]
   __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // digits
   __ movl(EAX, Address(ESP, 1 * target::kWordSize));  // i is Smi
-  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
-  __ movl(EAX, Address(EBX, EAX, TIMES_2, 0));
+  __ movl(EAX,
+          FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // EDX:EAX = t = rho*d
   __ mull(ECX);
 
   // args[4] = t mod DIGIT_BASE = low32(t)
-  __ movl(Address(EDI, 4 * kBytesPerBigIntDigit), EAX);
+  __ movl(FieldAddress(
+              EDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
+          EAX);
 
   __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
@@ -1589,13 +1596,12 @@
   // Field '_state'.
   __ movl(EBX, FieldAddress(EAX, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
-  __ movl(EBX, FieldAddress(EBX, target::TypedData::data_offset()));
   const intptr_t scale =
       target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
   const intptr_t offset =
       target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
-  Address addr_0 = Address(EBX, 0 * scale + offset);
-  Address addr_1 = Address(EBX, 1 * scale + offset);
+  Address addr_0 = FieldAddress(EBX, 0 * scale + offset);
+  Address addr_1 = FieldAddress(EBX, 1 * scale + offset);
   __ movl(EAX, Immediate(a_int32_value));
   // 64-bit multiply EAX * value -> EDX:EAX.
   __ mull(addr_0);
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 1532070..1c34df5 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -169,8 +169,6 @@
   /* data area to be initialized. */                                           \
   __ xorq(RBX, RBX); /* Zero. */                                               \
   __ leaq(RDI, FieldAddress(RAX, target::TypedData::InstanceSize()));          \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      RAX, FieldAddress(RAX, target::TypedData::data_offset()), RDI);          \
   Label done, init_loop;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmpq(RDI, RCX);                                                           \
@@ -686,11 +684,11 @@
   __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
   __ movq(RSI, RCX);
   __ sarq(RSI, Immediate(6));  // RSI = n ~/ (2*_DIGIT_BITS).
-  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
-  __ leaq(RBX, Address(RBX, RSI, TIMES_8, 0));
+  __ leaq(RBX,
+          FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
   __ xorq(RAX, RAX);  // RAX = 0.
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
-  __ movq(RDX, Address(RDI, R8, TIMES_8, 0));
+  __ movq(RDX,
+          FieldAddress(RDI, R8, TIMES_8, target::TypedData::data_offset()));
   __ shldq(RAX, RDX, RCX);
   __ movq(Address(RBX, R8, TIMES_8, 2 * kBytesPerBigIntDigit), RAX);
   Label last;
@@ -699,7 +697,9 @@
   Label loop;
   __ Bind(&loop);
   __ movq(RAX, RDX);
-  __ movq(RDX, Address(RDI, R8, TIMES_8, -2 * kBytesPerBigIntDigit));
+  __ movq(RDX, FieldAddress(RDI, R8, TIMES_8,
+                            target::TypedData::data_offset() -
+                                2 * kBytesPerBigIntDigit));
   __ shldq(RAX, RDX, RCX);
   __ movq(Address(RBX, R8, TIMES_8, 0), RAX);
   __ decq(R8);
@@ -724,11 +724,11 @@
   __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // x_used is Smi
   __ subq(RSI, Immediate(2));  // x_used > 0, Smi. RSI = x_used - 1, round up.
   __ sarq(RSI, Immediate(2));
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
-  __ leaq(RDI, Address(RDI, RSI, TIMES_8, 0));
+  __ leaq(RDI,
+          FieldAddress(RDI, RSI, TIMES_8, target::TypedData::data_offset()));
   __ subq(RSI, RDX);  // RSI + 1 = number of digit pairs to read.
-  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
-  __ leaq(RBX, Address(RBX, RSI, TIMES_8, 0));
+  __ leaq(RBX,
+          FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
   __ negq(RSI);
   __ movq(RDX, Address(RDI, RSI, TIMES_8, 0));
   Label last;
@@ -765,10 +765,6 @@
   __ sarq(RCX, Immediate(2));  // R8 = number of digit pairs to process.
   __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
 
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
-  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
-  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
-
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subq(R8, RCX);
   __ incq(R8);  // To account for the extra test between loops.
@@ -777,9 +773,12 @@
   Label add_loop;
   __ Bind(&add_loop);
   // Loop (a_used+1)/2 times, RCX > 0.
-  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
-  __ adcq(RAX, Address(RSI, RDX, TIMES_8, 0));
-  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ adcq(RAX,
+          FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(RCX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -791,9 +790,11 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
-  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
   __ adcq(RAX, Immediate(0));
-  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(R8);   // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -801,7 +802,8 @@
   __ Bind(&last_carry);
   Label done;
   __ j(NOT_CARRY, &done);
-  __ movq(Address(RBX, RDX, TIMES_8, 0), Immediate(1));
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          Immediate(1));
 
   __ Bind(&done);
   __ LoadObject(RAX, NullObject());
@@ -824,10 +826,6 @@
   __ sarq(RCX, Immediate(2));  // R8 = number of digit pairs to process.
   __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
 
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
-  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
-  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
-
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subq(R8, RCX);
   __ incq(R8);  // To account for the extra test between loops.
@@ -836,9 +834,12 @@
   Label sub_loop;
   __ Bind(&sub_loop);
   // Loop (a_used+1)/2 times, RCX > 0.
-  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
-  __ sbbq(RAX, Address(RSI, RDX, TIMES_8, 0));
-  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ sbbq(RAX,
+          FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(RCX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -850,9 +851,11 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
-  __ movq(RAX, Address(RDI, RDX, TIMES_8, 0));
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
   __ sbbq(RAX, Immediate(0));
-  __ movq(Address(RBX, RDX, TIMES_8, 0), RAX);
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(R8);   // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -896,8 +899,8 @@
   // RBX = x, done if x == 0
   __ movq(RCX, Address(RSP, 7 * target::kWordSize));  // x_digits
   __ movq(RAX, Address(RSP, 6 * target::kWordSize));  // xi is Smi
-  __ movq(RBX, FieldAddress(RCX, target::TypedData::data_offset()));
-  __ movq(RBX, Address(RBX, RAX, TIMES_2, 0));
+  __ movq(RBX,
+          FieldAddress(RCX, RAX, TIMES_2, target::TypedData::data_offset()));
   __ testq(RBX, RBX);
   __ j(ZERO, &done, Assembler::kNearJump);
 
@@ -910,14 +913,14 @@
   // RDI = mip = &m_digits[i >> 1]
   __ movq(RDI, Address(RSP, 5 * target::kWordSize));  // m_digits
   __ movq(RAX, Address(RSP, 4 * target::kWordSize));  // i is Smi
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
-  __ leaq(RDI, Address(RDI, RAX, TIMES_2, 0));
+  __ leaq(RDI,
+          FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RSI = ajp = &a_digits[j >> 1]
   __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // a_digits
   __ movq(RAX, Address(RSP, 2 * target::kWordSize));  // j is Smi
-  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
-  __ leaq(RSI, Address(RSI, RAX, TIMES_2, 0));
+  __ leaq(RSI,
+          FieldAddress(RSI, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RCX = c = 0
   __ xorq(RCX, RCX);
@@ -1004,8 +1007,8 @@
   // RDI = xip = &x_digits[i >> 1]
   __ movq(RDI, Address(RSP, 4 * target::kWordSize));  // x_digits
   __ movq(RAX, Address(RSP, 3 * target::kWordSize));  // i is Smi
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
-  __ leaq(RDI, Address(RDI, RAX, TIMES_2, 0));
+  __ leaq(RDI,
+          FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RBX = x = *xip++, return if x == 0
   Label x_zero;
@@ -1016,8 +1019,8 @@
 
   // RSI = ajp = &a_digits[i]
   __ movq(RSI, Address(RSP, 2 * target::kWordSize));  // a_digits
-  __ movq(RSI, FieldAddress(RSI, target::TypedData::data_offset()));
-  __ leaq(RSI, Address(RSI, RAX, TIMES_4, 0));
+  __ leaq(RSI,
+          FieldAddress(RSI, RAX, TIMES_4, target::TypedData::data_offset()));
 
   // RDX:RAX = t = x*x + *ajp
   __ movq(RAX, RBX);
@@ -1113,18 +1116,18 @@
   //   return 2;
   // }
 
-  // RDI = &args[0]
+  // RDI = args
   __ movq(RDI, Address(RSP, 3 * target::kWordSize));  // args
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
 
   // RCX = yt = args[0..1]
-  __ movq(RCX, Address(RDI, 0));
+  __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset()));
 
   // RBX = dp = &digits[(i >> 1) - 1]
   __ movq(RBX, Address(RSP, 2 * target::kWordSize));  // digits
   __ movq(RAX, Address(RSP, 1 * target::kWordSize));  // i is Smi and odd.
-  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
-  __ leaq(RBX, Address(RBX, RAX, TIMES_2, -kBytesPerBigIntDigit));
+  __ leaq(RBX, FieldAddress(
+                   RBX, RAX, TIMES_2,
+                   target::TypedData::data_offset() - kBytesPerBigIntDigit));
 
   // RDX = dh = dp[0]
   __ movq(RDX, Address(RBX, 0));
@@ -1145,7 +1148,9 @@
 
   __ Bind(&return_qd);
   // args[2..3] = qd
-  __ movq(Address(RDI, 2 * kBytesPerBigIntDigit), RAX);
+  __ movq(FieldAddress(
+              RDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
+          RAX);
 
   __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
@@ -1162,24 +1167,26 @@
   //   return 2;
   // }
 
-  // RDI = &args[0]
+  // RDI = args
   __ movq(RDI, Address(RSP, 3 * target::kWordSize));  // args
-  __ movq(RDI, FieldAddress(RDI, target::TypedData::data_offset()));
 
   // RCX = rho = args[2 .. 3]
-  __ movq(RCX, Address(RDI, 2 * kBytesPerBigIntDigit));
+  __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset() +
+                                     2 * kBytesPerBigIntDigit));
 
   // RAX = digits[i >> 1 .. (i >> 1) + 1]
   __ movq(RBX, Address(RSP, 2 * target::kWordSize));  // digits
   __ movq(RAX, Address(RSP, 1 * target::kWordSize));  // i is Smi
-  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
-  __ movq(RAX, Address(RBX, RAX, TIMES_2, 0));
+  __ movq(RAX,
+          FieldAddress(RBX, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RDX:RAX = t = rho*d
   __ mulq(RCX);
 
   // args[4 .. 5] = t mod DIGIT_BASE^2 = low64(t)
-  __ movq(Address(RDI, 4 * kBytesPerBigIntDigit), RAX);
+  __ movq(FieldAddress(
+              RDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
+          RAX);
 
   __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
@@ -1496,13 +1503,12 @@
   // Field '_state'.
   __ movq(RBX, FieldAddress(RAX, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
-  __ movq(RBX, FieldAddress(RBX, target::TypedData::data_offset()));
   const intptr_t scale =
       target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
   const intptr_t offset =
       target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
-  Address addr_0 = Address(RBX, 0 * scale + offset);
-  Address addr_1 = Address(RBX, 1 * scale + offset);
+  Address addr_0 = FieldAddress(RBX, 0 * scale + offset);
+  Address addr_1 = FieldAddress(RBX, 1 * scale + offset);
   __ movq(RAX, Immediate(a_int_value));
   __ movl(RCX, addr_0);
   __ imulq(RCX, RAX);
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index c7b7037..d441d61 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3446,9 +3446,7 @@
                                              intptr_t index,
                                              Register temp) {
   const int64_t offset_base =
-      ((is_external || RawObject::IsTypedDataClassId(cid))
-           ? 0
-           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset =
       offset_base + static_cast<int64_t>(index) * index_scale;
   ASSERT(Utils::IsInt(32, offset));
@@ -3470,9 +3468,7 @@
                                               Register array,
                                               intptr_t index) {
   const int64_t offset_base =
-      ((is_external || RawObject::IsTypedDataClassId(cid))
-           ? 0
-           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset =
       offset_base + static_cast<int64_t>(index) * index_scale;
   ASSERT(Utils::IsInt(32, offset));
@@ -3487,9 +3483,8 @@
                                              Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
-                       ? 0
-                       : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  int32_t offset =
+      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   const OperandSize size = Address::OperandSizeFor(cid);
   ASSERT(array != IP);
   ASSERT(index != IP);
@@ -3529,9 +3524,8 @@
                                               Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
-                       ? 0
-                       : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  int32_t offset =
+      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   if (shift < 0) {
     ASSERT(shift == -1);
     add(address, array, Operand(index, ASR, 1));
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index a7eaf8d..b41c7a4 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1566,9 +1566,7 @@
                                              intptr_t index) const {
   const int64_t offset =
       index * index_scale +
-      ((is_external || RawObject::IsTypedDataClassId(cid))
-           ? 0
-           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   ASSERT(Utils::IsInt(32, offset));
   const OperandSize size = Address::OperandSizeFor(cid);
   ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
@@ -1583,9 +1581,7 @@
                                               intptr_t index) {
   const int64_t offset =
       index * index_scale +
-      ((is_external || RawObject::IsTypedDataClassId(cid))
-           ? 0
-           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   AddImmediate(address, array, offset);
 }
 
@@ -1597,9 +1593,8 @@
                                              Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  const int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
-                             ? 0
-                             : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  const int32_t offset =
+      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   ASSERT(array != TMP);
   ASSERT(index != TMP);
   const Register base = is_load ? TMP : index;
@@ -1625,9 +1620,8 @@
                                               Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  const int32_t offset = (is_external || RawObject::IsTypedDataClassId(cid))
-                             ? 0
-                             : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  const int32_t offset =
+      is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag);
   if (shift == 0) {
     add(address, array, Operand(index));
   } else if (shift < 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 38c3771..f1ef6b1 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2535,7 +2535,7 @@
                                              Register array,
                                              intptr_t index,
                                              intptr_t extra_disp) {
-  if (is_external || RawObject::IsTypedDataClassId(cid)) {
+  if (is_external) {
     return Address(array, index * index_scale + extra_disp);
   } else {
     const int64_t disp = static_cast<int64_t>(index) * index_scale +
@@ -2573,7 +2573,7 @@
                                              Register array,
                                              Register index,
                                              intptr_t extra_disp) {
-  if (is_external || RawObject::IsTypedDataClassId(cid)) {
+  if (is_external) {
     return Address(array, index, ToScaleFactor(index_scale), extra_disp);
   } else {
     return FieldAddress(array, index, ToScaleFactor(index_scale),
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index ebccda6..af6b564 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -2075,7 +2075,7 @@
                                              intptr_t index_scale,
                                              Register array,
                                              intptr_t index) {
-  if (is_external || RawObject::IsTypedDataClassId(cid)) {
+  if (is_external) {
     return Address(array, index * index_scale);
   } else {
     const int64_t disp = static_cast<int64_t>(index) * index_scale +
@@ -2112,7 +2112,7 @@
                                              intptr_t index_scale,
                                              Register array,
                                              Register index) {
-  if (is_external || RawObject::IsTypedDataClassId(cid)) {
+  if (is_external) {
     return Address(array, index, ToScaleFactor(index_scale), 0);
   } else {
     return FieldAddress(array, index, ToScaleFactor(index_scale),
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index e6766dc..bcf71bb 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1184,9 +1184,7 @@
   const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
   const intptr_t scale = Instance::ElementSizeFor(cid);
   const intptr_t base_offset =
-      (is_external || RawObject::IsTypedDataClassId(cid)
-           ? 0
-           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset = index * scale + base_offset;
   if (!Utils::IsAbsoluteUint(12, offset)) {
     return false;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index b10e64d..7e1de69 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1064,9 +1064,8 @@
   const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
   const intptr_t scale = Instance::ElementSizeFor(cid);
   const int64_t offset =
-      index * scale + (is_external || RawObject::IsTypedDataClassId(cid)
-                           ? 0
-                           : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      index * scale +
+      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   if (!Utils::IsInt(32, offset)) {
     return false;
   }
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index a81b2cc..b53f252 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2439,11 +2439,9 @@
     // Load from the data from backing store which is a fixed-length array.
     *array = elements;
     array_cid = kArrayCid;
-  } else if (RawObject::IsTypedDataClassId(array_cid) ||
-             RawObject::IsExternalTypedDataClassId(array_cid)) {
-    ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
-    LoadUntaggedInstr* elements = new (Z)
-        LoadUntaggedInstr(new (Z) Value(*array), TypedData::data_offset());
+  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
+        new (Z) Value(*array), ExternalTypedData::data_offset());
     *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
     *array = elements;
   }
@@ -2858,6 +2856,64 @@
                                  FlowGraph::kValue);
 }
 
+// Emits preparatory code for a typed getter/setter.
+// Handles three cases:
+//   (1) dynamic:  generates a conditional on the receiver cid
+//                 that handles external (load untagged) and
+//                 internal storage at runtime.
+//   (2) external: generates load untagged.
+//   (3) internal: no code required.
+static void PrepareInlineByteArrayBaseOp(FlowGraph* flow_graph,
+                                         Instruction* call,
+                                         Definition* receiver,
+                                         intptr_t array_cid,
+                                         Definition** array,
+                                         Instruction** cursor,
+                                         TargetEntryInstr** block_external,
+                                         TargetEntryInstr** block_internal) {
+  if (array_cid == kDynamicCid) {
+    // Dynamic case:   runtime resolution between external/internal typed data.
+    //                 cid = LoadCid
+    //                 if cid in [ kExternalTypedDataInt8ArrayCid,
+    //                             kExternalTypedDataFloat64x2ArrayCid ]
+    // block_external: LoadUntagged
+    //                 ..
+    //                 else
+    // block_internal: ..
+    //
+    // TODO(ajcbik): as suggested above, subtract + single unsigned test.
+    //
+    LoadClassIdInstr* load_cid =
+        new (Z) LoadClassIdInstr(new (Z) Value(receiver));
+    *cursor = flow_graph->AppendTo(*cursor, load_cid, NULL, FlowGraph::kValue);
+    ConstantInstr* cid_lo = flow_graph->GetConstant(
+        Smi::ZoneHandle(Smi::New(kExternalTypedDataInt8ArrayCid)));
+    RelationalOpInstr* le_lo = new (Z)
+        RelationalOpInstr(call->token_pos(), Token::kLTE, new (Z) Value(cid_lo),
+                          new (Z) Value(load_cid), kSmiCid, call->deopt_id());
+    ConstantInstr* cid_hi = flow_graph->GetConstant(
+        Smi::ZoneHandle(Smi::New(kExternalTypedDataFloat64x2ArrayCid)));
+    RelationalOpInstr* le_hi = new (Z) RelationalOpInstr(
+        call->token_pos(), Token::kLTE, new (Z) Value(load_cid),
+        new (Z) Value(cid_hi), kSmiCid, call->deopt_id());
+    *cursor = flow_graph->NewDiamond(*cursor, call,
+                                     FlowGraph::LogicalAnd(le_lo, le_hi),
+                                     block_external, block_internal);
+    LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
+        new (Z) Value(*array), ExternalTypedData::data_offset());
+    flow_graph->InsertAfter(*block_external, elements, NULL, FlowGraph::kValue);
+    *array = elements;  // return load untagged definition in array
+  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    // External typed data: load untagged.
+    LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
+        new (Z) Value(*array), ExternalTypedData::data_offset());
+    *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
+    *array = elements;
+  } else {
+    // Internal typed data: no action.
+  }
+}
+
 static LoadIndexedInstr* NewLoad(FlowGraph* flow_graph,
                                  Instruction* call,
                                  Definition* array,
@@ -2909,16 +2965,44 @@
                                        array, &index, &cursor);
   }
 
-  ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
-  LoadUntaggedInstr* elements =
-      new (Z) LoadUntaggedInstr(new (Z) Value(array), TypedData::data_offset());
-  cursor = flow_graph->AppendTo(cursor, elements, nullptr, FlowGraph::kValue);
+  // Generates a template for the load, either a dynamic conditional
+  // that dispatches on external and internal storage, or a single
+  // case that deals with either external or internal storage.
+  TargetEntryInstr* block_external = nullptr;
+  TargetEntryInstr* block_internal = nullptr;
+  PrepareInlineByteArrayBaseOp(flow_graph, call, receiver, array_cid, &array,
+                               &cursor, &block_external, &block_internal);
 
-  LoadIndexedInstr* load = NewLoad(flow_graph, call, elements, index, view_cid);
-  flow_graph->AppendTo(
-      cursor, load, call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-      FlowGraph::kValue);
-  cursor = *last = load;
+  // Fill out the generated template with loads.
+  if (array_cid == kDynamicCid) {
+    ASSERT(block_external != nullptr && block_internal != nullptr);
+    // Load from external in block_external and internal in block_internal
+    // (resolves (B)). The former loads from "array", which is the returned
+    // load untagged definition. The latter loads from the original "receiver".
+    LoadIndexedInstr* load1 = NewLoad(flow_graph, call, array, index, view_cid);
+    ASSERT(block_external->next() == array);
+    flow_graph->InsertAfter(
+        block_external->next(), load1,
+        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+        FlowGraph::kValue);
+    LoadIndexedInstr* load2 =
+        NewLoad(flow_graph, call, receiver, index, view_cid);
+    flow_graph->InsertAfter(
+        block_internal, load2,
+        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+        FlowGraph::kValue);
+    // Construct phi of external and internal load.
+    *last = flow_graph->AddPhi(cursor->AsJoinEntry(), load1, load2);
+  } else {
+    ASSERT(block_external == nullptr && block_internal == nullptr);
+    // Load from either external or internal.
+    LoadIndexedInstr* load = NewLoad(flow_graph, call, array, index, view_cid);
+    flow_graph->AppendTo(
+        cursor, load,
+        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+        FlowGraph::kValue);
+    cursor = *last = load;
+  }
 
   if (view_cid == kTypedDataFloat32ArrayCid) {
     *last = new (Z) FloatToDoubleInstr(new (Z) Value((*last)->AsDefinition()),
@@ -3097,17 +3181,43 @@
                                   FlowGraph::kValue);
   }
 
-  ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
-  LoadUntaggedInstr* elements =
-      new (Z) LoadUntaggedInstr(new (Z) Value(array), TypedData::data_offset());
-  cursor = flow_graph->AppendTo(cursor, elements, nullptr, FlowGraph::kValue);
+  // Generates a template for the store, either a dynamic conditional
+  // that dispatches on external and internal storage, or a single
+  // case that deals with either external or internal storage.
+  TargetEntryInstr* block_external = nullptr;
+  TargetEntryInstr* block_internal = nullptr;
+  PrepareInlineByteArrayBaseOp(flow_graph, call, receiver, array_cid, &array,
+                               &cursor, &block_external, &block_internal);
 
-  StoreIndexedInstr* store =
-      NewStore(flow_graph, call, elements, index, stored_value, view_cid);
-  flow_graph->AppendTo(
-      cursor, store, call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
-      FlowGraph::kEffect);
-  *last = store;
+  // Fill out the generated template with stores.
+  if (array_cid == kDynamicCid) {
+    ASSERT(block_external != nullptr && block_internal != nullptr);
+    // Store to external in block_external and internal in block_internal
+    // (resolves (B)). The former stores to "array", which is the returned
+    // load untagged definition. The latter stores to the original "receiver".
+    ASSERT(block_external->next() == array);
+    flow_graph->InsertAfter(
+        block_external->next(),
+        NewStore(flow_graph, call, array, index, stored_value, view_cid),
+        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+        FlowGraph::kEffect);
+    flow_graph->InsertAfter(
+        block_internal,
+        NewStore(flow_graph, call, receiver, index, stored_value, view_cid),
+        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+        FlowGraph::kEffect);
+    *last = cursor;
+  } else {
+    ASSERT(block_external == nullptr && block_internal == nullptr);
+    // Store on either external or internal.
+    StoreIndexedInstr* store =
+        NewStore(flow_graph, call, array, index, stored_value, view_cid);
+    flow_graph->AppendTo(
+        cursor, store,
+        call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
+        FlowGraph::kEffect);
+    *last = store;
+  }
   // We need a return value to replace uses of the original definition. However,
   // the final instruction is a use of 'void operator[]=()', so we use null.
   *result = flow_graph->constant_null();
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 85c5e6c..f49a686 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -275,9 +275,7 @@
   index = PrepareIndexedOp(flow_graph, &builder, array, index,
                            Slot::GetLengthFieldForArrayCid(array_cid));
 
-  if (RawObject::IsTypedDataClassId(array_cid) ||
-      RawObject::IsExternalTypedDataClassId(array_cid)) {
-    ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
     array = builder.AddDefinition(new LoadUntaggedInstr(
         new Value(array), ExternalTypedData::data_offset()));
   }
@@ -423,9 +421,7 @@
       UNREACHABLE();
   }
 
-  if (RawObject::IsTypedDataClassId(array_cid) ||
-      RawObject::IsExternalTypedDataClassId(array_cid)) {
-    ASSERT(TypedData::data_offset() == ExternalTypedData::data_offset());
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
     array = builder.AddDefinition(new LoadUntaggedInstr(
         new Value(array), ExternalTypedData::data_offset()));
   }
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index ba72cc1..ce66591 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -254,10 +254,6 @@
 const word RawObject::kBarrierOverlapShift =
     dart::RawObject::kBarrierOverlapShift;
 
-bool RawObject::IsTypedDataClassId(intptr_t cid) {
-  return dart::RawObject::IsTypedDataClassId(cid);
-}
-
 intptr_t ObjectPool::element_offset(intptr_t index) {
   return dart::ObjectPool::element_offset(index);
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 652c1b3..8df8767 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -335,8 +335,6 @@
   static const word kSizeTagMaxSizeTag;
   static const word kTagBitsSizeTagPos;
   static const word kBarrierOverlapShift;
-
-  static bool IsTypedDataClassId(intptr_t cid);
 };
 
 class RawAbstractType : public AllStatic {
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index 91e2058..e3073a0 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -483,10 +483,6 @@
         // Slide the object down.
         memmove(reinterpret_cast<void*>(new_addr),
                 reinterpret_cast<void*>(old_addr), size);
-
-        if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
-          reinterpret_cast<RawTypedData*>(new_obj)->ResetData();
-        }
       }
       new_obj->ClearMarkBit();
       new_obj->VisitPointers(compactor_);
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 0242715..fba5def 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -208,10 +208,6 @@
         new_obj->ptr()->tags_ = tags;
       }
 
-      if (RawObject::IsTypedDataClassId(new_obj->GetClassId())) {
-        reinterpret_cast<RawTypedData*>(new_obj)->ResetData();
-      }
-
       // Remember forwarding address.
       ForwardTo(raw_addr, new_addr);
     }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 86b63a5..496631e 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1223,7 +1223,6 @@
       intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0));
       ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size);
       raw->StoreSmi(&(raw->ptr()->length_), Smi::New(leftover_len));
-      raw->ResetData();
     } else {
       // Update the leftover space as a basic object.
       ASSERT(leftover_size == Object::InstanceSize());
@@ -16385,11 +16384,13 @@
 
 intptr_t Instance::DataOffsetFor(intptr_t cid) {
   if (RawObject::IsExternalTypedDataClassId(cid) ||
-      RawObject::IsExternalStringClassId(cid) ||
-      RawObject::IsTypedDataClassId(cid)) {
-    // Elements start at offset 0 of the external and typed data.
+      RawObject::IsExternalStringClassId(cid)) {
+    // Elements start at offset 0 of the external data.
     return 0;
   }
+  if (RawObject::IsTypedDataClassId(cid)) {
+    return TypedData::data_offset();
+  }
   switch (cid) {
     case kArrayCid:
     case kImmutableArrayCid:
@@ -20855,11 +20856,9 @@
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
-    result.ResetData();
     if (len > 0) {
       memset(result.DataAddr(0), 0, lengthInBytes);
     }
-    ASSERT(result.Length() == len);
   }
   return result.raw();
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 044ecc5..4129963 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -8221,9 +8221,13 @@
 
   static intptr_t length_offset() { return OFFSET_OF(RawTypedData, length_); }
 
-  static intptr_t data_offset() { return OFFSET_OF(RawTypedData, data_); }
+  static intptr_t data_offset() {
+    return OFFSET_OF_RETURNED_VALUE(RawTypedData, data);
+  }
 
   static intptr_t InstanceSize() {
+    ASSERT(sizeof(RawTypedData) ==
+           OFFSET_OF_RETURNED_VALUE(RawTypedData, data));
     return 0;
   }
 
@@ -8315,13 +8319,6 @@
     StoreSmi(&raw_ptr()->length_, Smi::New(value));
   }
 
-  void SetData(uint8_t* data) const {
-    ASSERT(Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
-    StoreNonPointer(&raw_ptr()->data_, data);
-  }
-
-  void ResetData() { raw()->ResetData(); }
-
  private:
   // Provides const access to non-pointer, non-aligned data within the object.
   // Such access does not need a write barrier, but it is *not* GC-safe, since
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 79372ea..6392703 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -2248,31 +2248,13 @@
 class RawTypedData : public RawInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypedData);
 
- public:
-  // Reset data_ pointer to internal data.
-  void ResetData() { ptr()->data_ = ptr()->internal_data(); }
-
  protected:
   VISIT_FROM(RawCompressed, length_)
   RawSmi* length_;
   VISIT_TO_LENGTH(RawCompressed, &ptr()->length_)
-
-  uint8_t* data_;
   // Variable length data follows here.
-
-  uint8_t* internal_data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
-  const uint8_t* internal_data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
-
-  uint8_t* data() {
-    // TODO(alexmarkov): revise after merging with ExternalTypedData
-    ASSERT(data_ == internal_data());
-    return data_;
-  }
-  const uint8_t* data() const {
-    // TODO(alexmarkov): revise after merging with ExternalTypedData
-    ASSERT(data_ == internal_data());
-    return data_;
-  }
+  uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
+  const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
 
   friend class Api;
   friend class Instance;