ART: Fast copy stack mask

StackMap::SetStackMask will currently copy a BitVector into a Memory-
Region bit by bit. This patch adds a new function for copying the data
with memcpy.

This is resubmission of CL I28d45a590b35a4a854cca2f57db864cf8a081487
but with a fix for a broken test which it revealed.

Change-Id: Ib65aa614d3ab7b5c99c6719fdc8e436466a4213d
diff --git a/runtime/base/bit_vector_test.cc b/runtime/base/bit_vector_test.cc
index c51b9b0..19c01f2 100644
--- a/runtime/base/bit_vector_test.cc
+++ b/runtime/base/bit_vector_test.cc
@@ -211,4 +211,62 @@
   }
 }
 
+TEST(BitVector, CopyTo) {
+  {
+    // Test copying an empty BitVector. Padding should fill `buf` with zeroes.
+    BitVector bv(0, true, Allocator::GetMallocAllocator());
+    uint32_t buf;
+
+    bv.CopyTo(&buf, sizeof(buf));
+    EXPECT_EQ(0u, bv.GetSizeOf());
+    EXPECT_EQ(0u, buf);
+  }
+
+  {
+    // Test copying when `bv.storage_` and `buf` are of equal lengths.
+    BitVector bv(0, true, Allocator::GetMallocAllocator());
+    uint32_t buf;
+
+    bv.SetBit(0);
+    bv.SetBit(17);
+    bv.SetBit(26);
+    EXPECT_EQ(sizeof(buf), bv.GetSizeOf());
+
+    bv.CopyTo(&buf, sizeof(buf));
+    EXPECT_EQ(0x04020001u, buf);
+  }
+
+  {
+    // Test copying when the `bv.storage_` is longer than `buf`. As long as
+    // `buf` is long enough to hold all set bits, copying should succeed.
+    BitVector bv(0, true, Allocator::GetMallocAllocator());
+    uint8_t buf[5];
+
+    bv.SetBit(18);
+    bv.SetBit(39);
+    EXPECT_LT(sizeof(buf), bv.GetSizeOf());
+
+    bv.CopyTo(buf, sizeof(buf));
+    EXPECT_EQ(0x00u, buf[0]);
+    EXPECT_EQ(0x00u, buf[1]);
+    EXPECT_EQ(0x04u, buf[2]);
+    EXPECT_EQ(0x00u, buf[3]);
+    EXPECT_EQ(0x80u, buf[4]);
+  }
+
+  {
+    // Test zero padding when `bv.storage_` is shorter than `buf`.
+    BitVector bv(0, true, Allocator::GetMallocAllocator());
+    uint32_t buf[2];
+
+    bv.SetBit(18);
+    bv.SetBit(31);
+    EXPECT_GT(sizeof(buf), bv.GetSizeOf());
+
+    bv.CopyTo(buf, sizeof(buf));
+    EXPECT_EQ(0x80040000U, buf[0]);
+    EXPECT_EQ(0x00000000U, buf[1]);
+  }
+}
+
 }  // namespace art