Revert "Revert "base: Add more bit utils and bit struct class""

This reverts commit 5e008b3c5a907015116aa95623205ac8fc2c6768.

Change-Id: I05d26dd4a1f8d35e4377f65e209587b67b2ca04e
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 711bc65..ea776e7 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -530,6 +530,7 @@
         "barrier_test.cc",
         "base/arena_allocator_test.cc",
         "base/bit_field_test.cc",
+        "base/bit_struct_test.cc",
         "base/bit_utils_test.cc",
         "base/bit_vector_test.cc",
         "base/hash_set_test.cc",
diff --git a/runtime/base/bit_struct.h b/runtime/base/bit_struct.h
new file mode 100644
index 0000000..1f86ee1
--- /dev/null
+++ b/runtime/base/bit_struct.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_BASE_BIT_STRUCT_H_
+#define ART_RUNTIME_BASE_BIT_STRUCT_H_
+
+#include "bit_struct_detail.h"
+#include "bit_utils.h"
+
+//
+// Zero-cost, type-safe, well-defined "structs" of bit fields.
+//
+// ---------------------------------------------
+// Usage example:
+// ---------------------------------------------
+//
+//   // Definition for type 'Example'
+//   BITSTRUCT_DEFINE_START(Example, 10)
+//     BitStructUint<0, 2> u2;     // Every field must be a BitStruct[*].
+//     BitStructInt<2, 7>  i7;
+//     BitStructUint<9, 1> i1;
+//   BITSTRUCT_DEFINE_END(Example);
+//
+//  Would define a bit struct with this layout:
+//   <- 1 ->    <--  7  -->  <- 2 ->
+//  +--------+---------------+-----+
+//  |   i1   |       i7      | u2  +
+//  +--------+---------------+-----+
+//  10       9               2     0
+//
+//   // Read-write just like regular values.
+//   Example ex;
+//   ex.u2 = 3;
+//   ex.i7 = -25;
+//   ex.i1 = true;
+//   size_t u2 = ex.u2;
+//   int i7 = ex.i7;
+//   bool i1 = ex.i1;
+//
+//   // It's packed down to the smallest # of machine words.
+//   assert(sizeof(Example) == 2);
+//   // The exact bit pattern is well-defined by the template parameters.
+//   uint16_t cast = *reinterpret_cast<uint16_t*>(ex);
+//   assert(cast == ((3) | (0b100111 << 2) | (true << 9);
+//
+// ---------------------------------------------
+// Why not just use C++ bitfields?
+// ---------------------------------------------
+//
+// The layout is implementation-defined.
+// We do not know whether the fields are packed left-to-right or
+// right-to-left, so it makes it useless when the memory layout needs to be
+// precisely controlled.
+//
+// ---------------------------------------------
+// More info:
+// ---------------------------------------------
+// Currently uintmax_t is the largest supported underlying storage type,
+// all (kBitOffset + kBitWidth) must fit into BitSizeOf<uintmax_t>();
+//
+// Using BitStruct[U]int will automatically select an underlying type
+// that's the smallest to fit your (offset + bitwidth).
+//
+// BitStructNumber can be used to manually select an underlying type.
+//
+// BitStructField can be used with custom standard-layout structs,
+// thus allowing for arbitrary nesting of bit structs.
+//
+namespace art {
+// Zero-cost wrapper around a struct 'T', allowing it to be stored as a bitfield
+// at offset 'kBitOffset' and width 'kBitWidth'.
+// The storage is plain unsigned int, whose size is the smallest required  to fit
+// 'kBitOffset + kBitWidth'. All operations to this become BitFieldExtract/BitFieldInsert
+// operations to the underlying uint.
+//
+// Field memory representation:
+//
+// MSB      <-- width  -->      LSB
+// +--------+------------+--------+
+// | ?????? | u bitfield | ?????? +
+// +--------+------------+--------+
+//                       offset   0
+//
+// Reading/writing the bitfield (un)packs it into a temporary T:
+//
+// MSB               <-- width  --> LSB
+// +-----------------+------------+
+// | 0.............0 | T bitfield |
+// +-----------------+------------+
+//                                0
+//
+// It's the responsibility of the StorageType to ensure the bit representation
+// of T can be represented by kBitWidth.
+template <typename T,
+          size_t kBitOffset,
+          size_t kBitWidth = BitStructSizeOf<T>(),
+          typename StorageType = typename detail::MinimumTypeUnsignedHelper<kBitOffset + kBitWidth>::type>
+struct BitStructField {
+  static_assert(std::is_standard_layout<T>::value, "T must be standard layout");
+
+  operator T() const {
+    return Get();
+  }
+
+  // Exclude overload when T==StorageType.
+  template <typename _ = void,
+            typename = std::enable_if_t<std::is_same<T, StorageType>::value, _>>
+  explicit operator StorageType() const {
+    return GetStorage();
+  }
+
+  BitStructField& operator=(T value) {
+    return Assign(*this, value);
+  }
+
+  static constexpr size_t BitStructSizeOf() {
+    return kBitWidth;
+  }
+
+ protected:
+  template <typename T2>
+  T2& Assign(T2& what, T value) {
+    // Since C++ doesn't allow the type of operator= to change out
+    // in the subclass, reimplement operator= in each subclass
+    // manually and call this helper function.
+    static_assert(std::is_base_of<BitStructField, T2>::value, "T2 must inherit BitStructField");
+    what.Set(value);
+    return what;
+  }
+
+  T Get() const {
+    ValueStorage vs;
+    vs.pod_.val_ = GetStorage();
+    return vs.value_;
+  }
+
+  void Set(T value) {
+    ValueStorage value_as_storage;
+    value_as_storage.value_ = value;
+
+    storage_.pod_.val_ = BitFieldInsert(storage_.pod_.val_,
+                                        value_as_storage.pod_.val_,
+                                        kBitOffset,
+                                        kBitWidth);
+  }
+
+ private:
+  StorageType GetStorage() const {
+    return BitFieldExtract(storage_.pod_.val_, kBitOffset, kBitWidth);
+  }
+
+  // Underlying value must be wrapped in a separate standard-layout struct.
+  // See below for more details.
+  struct PodWrapper {
+    StorageType val_;
+  };
+
+  union ValueStorage {
+    // Safely alias pod_ and value_ together.
+    //
+    // See C++ 9.5.1 [class.union]:
+    // If a standard-layout union contains several standard-layout structs that share a common
+    // initial sequence ... it is permitted to inspect the common initial sequence of any of
+    // standard-layout struct members.
+    PodWrapper pod_;
+    T value_;
+  } storage_;
+
+  // Future work: In theory almost non-standard layout can be supported here,
+  // assuming they don't rely on the address of (this).
+  // We just have to use memcpy since the union-aliasing would not work.
+};
+
+// Base class for number-like BitStruct fields.
+// T is the type to store in as a bit field.
+// kBitOffset, kBitWidth define the position and length of the bitfield.
+//
+// (Common usage should be BitStructInt, BitStructUint -- this
+// intermediate template allows a user-defined integer to be used.)
+template <typename T, size_t kBitOffset, size_t kBitWidth>
+struct BitStructNumber : public BitStructField<T, kBitOffset, kBitWidth, /*StorageType*/T> {
+  using StorageType = T;
+
+  BitStructNumber& operator=(T value) {
+    return BaseType::Assign(*this, value);
+  }
+
+  /*implicit*/ operator T() const {
+    return Get();
+  }
+
+  explicit operator bool() const {
+    return static_cast<bool>(Get());
+  }
+
+  BitStructNumber& operator++() {
+    *this = Get() + 1u;
+    return *this;
+  }
+
+  StorageType operator++(int) {
+    return Get() + 1u;
+  }
+
+  BitStructNumber& operator--() {
+    *this = Get() - 1u;
+    return *this;
+  }
+
+  StorageType operator--(int) {
+    return Get() - 1u;
+  }
+
+ private:
+  using BaseType = BitStructField<T, kBitOffset, kBitWidth, /*StorageType*/T>;
+  using BaseType::Get;
+};
+
+// Create a BitStruct field which uses the smallest underlying int storage type,
+// in order to be large enough to fit (kBitOffset + kBitWidth).
+//
+// Values are sign-extended when they are read out.
+template <size_t kBitOffset, size_t kBitWidth>
+using BitStructInt =
+    BitStructNumber<typename detail::MinimumTypeHelper<int, kBitOffset + kBitWidth>::type,
+                    kBitOffset,
+                    kBitWidth>;
+
+// Create a BitStruct field which uses the smallest underlying uint storage type,
+// in order to be large enough to fit (kBitOffset + kBitWidth).
+//
+// Values are zero-extended when they are read out.
+template <size_t kBitOffset, size_t kBitWidth>
+using BitStructUint =
+    BitStructNumber<typename detail::MinimumTypeHelper<unsigned int, kBitOffset + kBitWidth>::type,
+                    kBitOffset,
+                    kBitWidth>;
+
+// Start a definition for a bitstruct.
+// A bitstruct is defined to be a union with a common initial subsequence
+// that we call 'DefineBitStructSize<bitwidth>'.
+//
+// See top of file for usage example.
+//
+// This marker is required by the C++ standard in order to
+// have a "common initial sequence".
+//
+// See C++ 9.5.1 [class.union]:
+// If a standard-layout union contains several standard-layout structs that share a common
+// initial sequence ... it is permitted to inspect the common initial sequence of any of
+// standard-layout struct members.
+#define BITSTRUCT_DEFINE_START(name, bitwidth)                                 \
+    union name {                                                               \
+      art::detail::DefineBitStructSize<(bitwidth)> _;                          \
+      static constexpr size_t BitStructSizeOf() { return (bitwidth); }
+
+// End the definition of a bitstruct, and insert a sanity check
+// to ensure that the bitstruct did not exceed the specified size.
+//
+// See top of file for usage example.
+#define BITSTRUCT_DEFINE_END(name)                                             \
+    };    /* NOLINT [readability/braces] [4] */                                \
+    static_assert(art::detail::ValidateBitStructSize<name>(),                  \
+                  #name "bitsize incorrect: "                                  \
+                  "did you insert extra fields that weren't BitStructX, "      \
+                  "and does the size match the sum of the field widths?")
+
+// Determine the minimal bit size for a user-defined type T.
+// Used by BitStructField to determine how small a custom type is.
+template <typename T>
+static constexpr size_t BitStructSizeOf() {
+  return T::BitStructSizeOf();
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_BASE_BIT_STRUCT_H_
diff --git a/runtime/base/bit_struct_detail.h b/runtime/base/bit_struct_detail.h
new file mode 100644
index 0000000..9f629c0
--- /dev/null
+++ b/runtime/base/bit_struct_detail.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_BASE_BIT_STRUCT_DETAIL_H_
+#define ART_RUNTIME_BASE_BIT_STRUCT_DETAIL_H_
+
+#include "bit_utils.h"
+#include "globals.h"
+
+#include <type_traits>
+
+// Implementation details for bit_struct.h
+// Not intended to be used stand-alone.
+
+namespace art {
+
+template <typename T>
+static constexpr size_t BitStructSizeOf();
+
+namespace detail {
+  // Select the smallest uintX_t that will fit kBitSize bits.
+  template <size_t kBitSize>
+  struct MinimumTypeUnsignedHelper {
+    using type =
+      typename std::conditional<kBitSize == 0, void,
+      typename std::conditional<kBitSize <= 8, uint8_t,
+      typename std::conditional<kBitSize <= 16, uint16_t,
+      typename std::conditional<kBitSize <= 32, uint32_t,
+      typename std::conditional<kBitSize <= 64, uint64_t,
+      typename std::conditional<kBitSize <= BitSizeOf<uintmax_t>(), uintmax_t,
+                                void>::type>::type>::type>::type>::type>::type;
+  };
+
+  // Select the smallest [u]intX_t that will fit kBitSize bits.
+  // Automatically picks intX_t or uintX_t based on the sign-ness of T.
+  template <typename T, size_t kBitSize>
+  struct MinimumTypeHelper {
+    using type_unsigned = typename MinimumTypeUnsignedHelper<kBitSize>::type;
+
+    using type =
+      typename std::conditional</* if */   std::is_signed<T>::value,
+                                /* then */ typename std::make_signed<type_unsigned>::type,
+                                /* else */ type_unsigned>::type;
+  };
+
+  // Ensure the minimal type storage for 'T' matches its declared BitStructSizeOf.
+  // Nominally used by the BITSTRUCT_DEFINE_END macro.
+  template <typename T>
+  static constexpr bool ValidateBitStructSize() {
+    const size_t kBitStructSizeOf = BitStructSizeOf<T>();
+    const size_t kExpectedSize = (BitStructSizeOf<T>() < kBitsPerByte)
+                                     ? kBitsPerByte
+                                     : RoundUpToPowerOfTwo(kBitStructSizeOf);
+
+    // Ensure no extra fields were added in between START/END.
+    const size_t kActualSize = sizeof(T) * kBitsPerByte;
+    return kExpectedSize == kActualSize;
+  }
+
+  // Denotes the beginning of a bit struct.
+  //
+  // This marker is required by the C++ standard in order to
+  // have a "common initial sequence".
+  //
+  // See C++ 9.5.1 [class.union]:
+  // If a standard-layout union contains several standard-layout structs that share a common
+  // initial sequence ... it is permitted to inspect the common initial sequence of any of
+  // standard-layout struct members.
+  template <size_t kSize>
+  struct DefineBitStructSize {
+   private:
+    typename MinimumTypeUnsignedHelper<kSize>::type _;
+  };
+}  // namespace detail
+}  // namespace art
+
+#endif  // ART_RUNTIME_BASE_BIT_STRUCT_DETAIL_H_
diff --git a/runtime/base/bit_struct_test.cc b/runtime/base/bit_struct_test.cc
new file mode 100644
index 0000000..872ada3
--- /dev/null
+++ b/runtime/base/bit_struct_test.cc
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bit_struct.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+
+// A copy of detail::ValidateBitStructSize that uses EXPECT for a more
+// human-readable message.
+template <typename T>
+static constexpr bool ValidateBitStructSize(const char* name) {
+  const size_t kBitStructSizeOf = BitStructSizeOf<T>();
+  const size_t kExpectedSize = (BitStructSizeOf<T>() < kBitsPerByte)
+                                   ? kBitsPerByte
+                                   : RoundUpToPowerOfTwo(kBitStructSizeOf);
+
+  // Ensure no extra fields were added in between START/END.
+  const size_t kActualSize = sizeof(T) * kBitsPerByte;
+  EXPECT_EQ(kExpectedSize, kActualSize) << name;
+  return true;
+}
+
+#define VALIDATE_BITSTRUCT_SIZE(type) ValidateBitStructSize<type>(#type)
+
+TEST(BitStructs, MinimumType) {
+  EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<1>::type));
+  EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<2>::type));
+  EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<3>::type));
+  EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<8>::type));
+  EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<9>::type));
+  EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<10>::type));
+  EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<15>::type));
+  EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<16>::type));
+  EXPECT_EQ(4u, sizeof(typename detail::MinimumTypeUnsignedHelper<17>::type));
+  EXPECT_EQ(4u, sizeof(typename detail::MinimumTypeUnsignedHelper<32>::type));
+  EXPECT_EQ(8u, sizeof(typename detail::MinimumTypeUnsignedHelper<33>::type));
+  EXPECT_EQ(8u, sizeof(typename detail::MinimumTypeUnsignedHelper<64>::type));
+}
+
+template <typename T>
+size_t AsUint(const T& value) {
+  size_t uint_value = 0;
+  memcpy(&uint_value, &value, sizeof(value));
+  return uint_value;
+}
+
+struct CustomBitStruct {
+  CustomBitStruct() = default;
+  explicit CustomBitStruct(int8_t data) : data(data) {}
+
+  static constexpr size_t BitStructSizeOf() {
+    return 4;
+  }
+
+  int8_t data;
+};
+
+template <typename T>
+void ZeroInitialize(T& value) {
+  memset(&value, 0, sizeof(T));
+  // TODO: replace with value initialization
+}
+
+TEST(BitStructs, Custom) {
+  CustomBitStruct expected(0b1111);
+
+  BitStructField<CustomBitStruct, /*lsb*/4, /*width*/4> f;
+  ZeroInitialize(f);
+
+  EXPECT_EQ(1u, sizeof(f));
+
+  f = CustomBitStruct(0b1111);
+
+  CustomBitStruct read_out = f;
+  EXPECT_EQ(read_out.data, 0b1111);
+
+  EXPECT_EQ(AsUint(f), 0b11110000u);
+}
+
+BITSTRUCT_DEFINE_START(TestTwoCustom, /* size */ 8)
+  BitStructField<CustomBitStruct, /*lsb*/0, /*width*/4> f4_a;
+  BitStructField<CustomBitStruct, /*lsb*/4, /*width*/4> f4_b;
+BITSTRUCT_DEFINE_END(TestTwoCustom);
+
+TEST(BitStructs, TwoCustom) {
+  EXPECT_EQ(sizeof(TestTwoCustom), 1u);
+
+  VALIDATE_BITSTRUCT_SIZE(TestTwoCustom);
+
+  TestTwoCustom cst;
+  ZeroInitialize(cst);
+
+  // Test the write to most-significant field doesn't clobber least-significant.
+  cst.f4_a = CustomBitStruct(0b0110);
+  cst.f4_b = CustomBitStruct(0b0101);
+
+  int8_t read_out = static_cast<CustomBitStruct>(cst.f4_a).data;
+  int8_t read_out_b = static_cast<CustomBitStruct>(cst.f4_b).data;
+
+  EXPECT_EQ(0b0110, static_cast<int>(read_out));
+  EXPECT_EQ(0b0101, static_cast<int>(read_out_b));
+
+  EXPECT_EQ(AsUint(cst), 0b01010110u);
+
+  // Test write to least-significant field doesn't clobber most-significant.
+  cst.f4_a = CustomBitStruct(0);
+
+  read_out = static_cast<CustomBitStruct>(cst.f4_a).data;
+  read_out_b = static_cast<CustomBitStruct>(cst.f4_b).data;
+
+  EXPECT_EQ(0b0, static_cast<int>(read_out));
+  EXPECT_EQ(0b0101, static_cast<int>(read_out_b));
+
+  EXPECT_EQ(AsUint(cst), 0b01010000u);
+}
+
+TEST(BitStructs, Number) {
+  BitStructNumber<uint16_t, /*lsb*/4, /*width*/4> bsn;
+  ZeroInitialize(bsn);
+  EXPECT_EQ(2u, sizeof(bsn));
+
+  bsn = 0b1111;
+
+  uint32_t read_out = static_cast<uint32_t>(bsn);
+  uint32_t read_out_impl = bsn;
+
+  EXPECT_EQ(read_out, read_out_impl);
+  EXPECT_EQ(read_out, 0b1111u);
+  EXPECT_EQ(AsUint(bsn), 0b11110000u);
+}
+
+BITSTRUCT_DEFINE_START(TestBitStruct, /* size */ 8)
+  BitStructInt</*lsb*/0, /*width*/3> i3;
+  BitStructUint</*lsb*/3, /*width*/4> u4;
+
+  BitStructUint</*lsb*/0, /*width*/7> alias_all;
+BITSTRUCT_DEFINE_END(TestBitStruct);
+
+TEST(BitStructs, Test1) {
+  {
+    // Check minimal size selection is correct.
+    BitStructInt</*lsb*/0, /*width*/3> i3;
+    BitStructUint</*lsb*/3, /*width*/4> u4;
+
+    BitStructUint</*lsb*/0, /*width*/7> alias_all;
+
+    EXPECT_EQ(1u, sizeof(i3));
+    EXPECT_EQ(1u, sizeof(u4));
+    EXPECT_EQ(1u, sizeof(alias_all));
+  }
+  TestBitStruct tst;
+  ZeroInitialize(tst);
+
+  // Check minimal size selection is correct.
+  EXPECT_EQ(1u, sizeof(TestBitStruct));
+  EXPECT_EQ(1u, sizeof(tst._));
+  EXPECT_EQ(1u, sizeof(tst.i3));
+  EXPECT_EQ(1u, sizeof(tst.u4));
+  EXPECT_EQ(1u, sizeof(tst.alias_all));
+
+  // Check operator assignment.
+  tst.i3 = -1;
+  tst.u4 = 0b1010;
+
+  // Check implicit operator conversion.
+  int8_t read_i3 = tst.i3;
+  uint8_t read_u4 = tst.u4;
+
+  // Ensure read-out values were correct.
+  EXPECT_EQ(static_cast<int8_t>(-1), read_i3);
+  EXPECT_EQ(0b1010, read_u4);
+
+  // Ensure aliasing is working.
+  EXPECT_EQ(0b1010111, static_cast<uint8_t>(tst.alias_all));
+
+  // Ensure the bit pattern is correct.
+  EXPECT_EQ(0b1010111u, AsUint(tst));
+
+  // Math operator checks
+  {
+    // In-place
+    ++tst.u4;
+    EXPECT_EQ(static_cast<uint8_t>(0b1011), static_cast<uint8_t>(tst.u4));
+    --tst.u4;
+    EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
+
+    // Copy
+    uint8_t read_and_convert = tst.u4++;
+    EXPECT_EQ(static_cast<uint8_t>(0b1011), read_and_convert);
+    EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
+    read_and_convert = tst.u4--;
+    EXPECT_EQ(static_cast<uint8_t>(0b1001), read_and_convert);
+    EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
+
+    // Check boolean operator conversion.
+    tst.u4 = 0b1010;
+    EXPECT_TRUE(static_cast<bool>(tst.u4));
+    bool succ = tst.u4 ? true : false;
+    EXPECT_TRUE(succ);
+
+    tst.u4 = 0;
+    EXPECT_FALSE(static_cast<bool>(tst.u4));
+
+/*
+    // Disabled: Overflow is caught by the BitFieldInsert DCHECKs.
+    // Check overflow for uint.
+    tst.u4 = 0b1111;
+    ++tst.u4;
+    EXPECT_EQ(static_cast<uint8_t>(0), static_cast<uint8_t>(tst.u4));
+*/
+  }
+}
+
+BITSTRUCT_DEFINE_START(MixedSizeBitStruct, /* size */ 32)
+  BitStructUint</*lsb*/0, /*width*/3> u3;
+  BitStructUint</*lsb*/3, /*width*/10> u10;
+  BitStructUint</*lsb*/13, /*width*/19> u19;
+
+  BitStructUint</*lsb*/0, /*width*/32> alias_all;
+BITSTRUCT_DEFINE_END(MixedSizeBitStruct);
+
+// static_assert(sizeof(MixedSizeBitStruct) == sizeof(uint32_t), "TestBitStructs#MixedSize");
+
+TEST(BitStructs, Mixed) {
+  EXPECT_EQ(4u, sizeof(MixedSizeBitStruct));
+
+  MixedSizeBitStruct tst;
+  ZeroInitialize(tst);
+
+  // Check operator assignment.
+  tst.u3 = 0b111u;
+  tst.u10 = 0b1111010100u;
+  tst.u19 = 0b1010101010101010101u;
+
+  // Check implicit operator conversion.
+  uint8_t read_u3 = tst.u3;
+  uint16_t read_u10 = tst.u10;
+  uint32_t read_u19 = tst.u19;
+
+  // Ensure read-out values were correct.
+  EXPECT_EQ(0b111u, read_u3);
+  EXPECT_EQ(0b1111010100u, read_u10);
+  EXPECT_EQ(0b1010101010101010101u, read_u19);
+
+  uint32_t read_all = tst.alias_all;
+
+  // Ensure aliasing is working.
+  EXPECT_EQ(0b10101010101010101011111010100111u, read_all);
+
+  // Ensure the bit pattern is correct.
+  EXPECT_EQ(0b10101010101010101011111010100111u, AsUint(tst));
+}
+
+}  // namespace art
diff --git a/runtime/base/bit_utils.h b/runtime/base/bit_utils.h
index 87dac02..da3c704 100644
--- a/runtime/base/bit_utils.h
+++ b/runtime/base/bit_utils.h
@@ -371,6 +371,128 @@
   return opnd;
 }
 
+// Create a mask for the least significant "bits"
+// The returned value is always unsigned to prevent undefined behavior for bitwise ops.
+//
+// Given 'bits',
+// Returns:
+//                   <--- bits --->
+// +-----------------+------------+
+// | 0 ............0 |   1.....1  |
+// +-----------------+------------+
+// msb                           lsb
+template <typename T = size_t>
+inline static constexpr std::make_unsigned_t<T> MaskLeastSignificant(size_t bits) {
+  DCHECK_GE(BitSizeOf<T>(), bits) << "Bits out of range for type T";
+  using unsigned_T = std::make_unsigned_t<T>;
+  if (bits >= BitSizeOf<T>()) {
+    return std::numeric_limits<unsigned_T>::max();
+  } else {
+    return static_cast<unsigned_T>((1 << bits) - 1);
+  }
+}
+
+// Clears the bitfield starting at the least significant bit "lsb" with a bitwidth of 'width'.
+// (Equivalent of ARM BFC instruction).
+//
+// Given:
+//           <-- width  -->
+// +--------+------------+--------+
+// | ABC... |  bitfield  | XYZ... +
+// +--------+------------+--------+
+//                       lsb      0
+// Returns:
+//           <-- width  -->
+// +--------+------------+--------+
+// | ABC... | 0........0 | XYZ... +
+// +--------+------------+--------+
+//                       lsb      0
+template <typename T>
+inline static constexpr T BitFieldClear(T value, size_t lsb, size_t width) {
+  DCHECK_GE(BitSizeOf(value), lsb + width) << "Bit field out of range for value";
+  const auto val = static_cast<std::make_unsigned_t<T>>(value);
+  const auto mask = MaskLeastSignificant<T>(width);
+
+  return static_cast<T>(val & ~(mask << lsb));
+}
+
+// Inserts the contents of 'data' into bitfield of 'value'  starting
+// at the least significant bit "lsb" with a bitwidth of 'width'.
+// Note: data must be within range of [MinInt(width), MaxInt(width)].
+// (Equivalent of ARM BFI instruction).
+//
+// Given (data):
+//           <-- width  -->
+// +--------+------------+--------+
+// | ABC... |  bitfield  | XYZ... +
+// +--------+------------+--------+
+//                       lsb      0
+// Returns:
+//           <-- width  -->
+// +--------+------------+--------+
+// | ABC... | 0...data   | XYZ... +
+// +--------+------------+--------+
+//                       lsb      0
+
+template <typename T, typename T2>
+inline static constexpr T BitFieldInsert(T value, T2 data, size_t lsb, size_t width) {
+  DCHECK_GE(BitSizeOf(value), lsb + width) << "Bit field out of range for value";
+  if (width != 0u) {
+    DCHECK_GE(MaxInt<T2>(width), data) << "Data out of range [too large] for bitwidth";
+    DCHECK_LE(MinInt<T2>(width), data) << "Data out of range [too small] for bitwidth";
+  } else {
+    DCHECK_EQ(static_cast<T2>(0), data) << "Data out of range [nonzero] for bitwidth 0";
+  }
+  const auto data_mask = MaskLeastSignificant<T2>(width);
+  const auto value_cleared = BitFieldClear(value, lsb, width);
+
+  return static_cast<T>(value_cleared | ((data & data_mask) << lsb));
+}
+
+// Extracts the bitfield starting at the least significant bit "lsb" with a bitwidth of 'width'.
+// Signed types are sign-extended during extraction. (Equivalent of ARM UBFX/SBFX instruction).
+//
+// Given:
+//           <-- width   -->
+// +--------+-------------+-------+
+// |        |   bitfield  |       +
+// +--------+-------------+-------+
+//                       lsb      0
+// (Unsigned) Returns:
+//                  <-- width   -->
+// +----------------+-------------+
+// | 0...        0  |   bitfield  |
+// +----------------+-------------+
+//                                0
+// (Signed) Returns:
+//                  <-- width   -->
+// +----------------+-------------+
+// | S...        S  |   bitfield  |
+// +----------------+-------------+
+//                                0
+// where S is the highest bit in 'bitfield'.
+template <typename T>
+inline static constexpr T BitFieldExtract(T value, size_t lsb, size_t width) {
+  DCHECK_GE(BitSizeOf(value), lsb + width) << "Bit field out of range for value";
+  const auto val = static_cast<std::make_unsigned_t<T>>(value);
+
+  const T bitfield_unsigned =
+      static_cast<T>((val >> lsb) & MaskLeastSignificant<T>(width));
+  if (std::is_signed<T>::value) {
+    // Perform sign extension
+    if (width == 0) {  // Avoid underflow.
+      return static_cast<T>(0);
+    } else if (bitfield_unsigned & (1 << (width - 1))) {  // Detect if sign bit was set.
+      // MSB        <width> LSB
+      // 0b11111...100...000000
+      const auto ones_negmask = ~MaskLeastSignificant<T>(width);
+      return static_cast<T>(bitfield_unsigned | ones_negmask);
+    }
+  }
+  // Skip sign extension.
+  return bitfield_unsigned;
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_BASE_BIT_UTILS_H_
diff --git a/runtime/base/bit_utils_test.cc b/runtime/base/bit_utils_test.cc
index c96c6dc..0276d8d 100644
--- a/runtime/base/bit_utils_test.cc
+++ b/runtime/base/bit_utils_test.cc
@@ -345,6 +345,97 @@
               "TestIsAbsoluteUint64#27");
 static_assert(!IsAbsoluteUint<32, int64_t>(kUint32MaxPlus1), "TestIsAbsoluteUint64#28");
 
+static_assert(MaskLeastSignificant(0) == 0b0, "TestMaskLeastSignificant#1");
+static_assert(MaskLeastSignificant(1) == 0b1, "TestMaskLeastSignificant#2");
+static_assert(MaskLeastSignificant(2) == 0b11, "TestMaskLeastSignificant#3");
+static_assert(MaskLeastSignificant<uint8_t>(8) == 0xFF, "TestMaskLeastSignificant#4");
+static_assert(MaskLeastSignificant<int8_t>(8) == 0xFF, "TestMaskLeastSignificant#5");
+
+static_assert(BitFieldClear(0xFF, /*lsb*/0, /*width*/0) == 0xFF, "TestBitFieldClear#1");
+static_assert(BitFieldClear(std::numeric_limits<uint32_t>::max(), /*lsb*/0, /*width*/32) == 0x0,
+              "TestBitFieldClear#2");
+static_assert(BitFieldClear(std::numeric_limits<int32_t>::max(), /*lsb*/0, /*width*/32) == 0x0,
+              "TestBitFieldClear#3");
+static_assert(BitFieldClear(0xFF, /*lsb*/0, /*width*/2) == 0b11111100, "TestBitFieldClear#4");
+static_assert(BitFieldClear(0xFF, /*lsb*/0, /*width*/3) == 0b11111000, "TestBitFieldClear#5");
+static_assert(BitFieldClear(0xFF, /*lsb*/1, /*width*/3) == 0b11110001, "TestBitFieldClear#6");
+static_assert(BitFieldClear(0xFF, /*lsb*/2, /*width*/3) == 0b11100011, "TestBitFieldClear#7");
+
+static_assert(BitFieldExtract(0xFF, /*lsb*/0, /*width*/0) == 0x0, "TestBitFieldExtract#1");
+static_assert(BitFieldExtract(std::numeric_limits<uint32_t>::max(), /*lsb*/0, /*width*/32)
+                  == std::numeric_limits<uint32_t>::max(),
+              "TestBitFieldExtract#2");
+static_assert(BitFieldExtract(std::numeric_limits<int32_t>::max(), /*lsb*/0, /*width*/32)
+                  == std::numeric_limits<int32_t>::max(),
+              "TestBitFieldExtract#3");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/0, /*width*/2) == 0b00000011,
+              "TestBitFieldExtract#4");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/0, /*width*/3) == 0b00000111,
+              "TestBitFieldExtract#5");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/1, /*width*/3) == 0b00000111,
+              "TestBitFieldExtract#6");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/2, /*width*/3) == 0b00000111,
+              "TestBitFieldExtract#7");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/3, /*width*/3) == 0b00000111,
+              "TestBitFieldExtract#8");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/8, /*width*/3) == 0b00000000,
+              "TestBitFieldExtract#9");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/7, /*width*/3) == 0b00000001,
+              "TestBitFieldExtract#10");
+static_assert(BitFieldExtract(static_cast<uint32_t>(0xFF), /*lsb*/6, /*width*/3) == 0b00000011,
+              "TestBitFieldExtract#11");
+static_assert(BitFieldExtract(0xFF, /*lsb*/0, /*width*/2) == -1, "TestBitFieldExtract#12");
+static_assert(BitFieldExtract(0xFF, /*lsb*/0, /*width*/3) == -1, "TestBitFieldExtract#13");
+static_assert(BitFieldExtract(0xFF, /*lsb*/1, /*width*/3) == -1, "TestBitFieldExtract#14");
+static_assert(BitFieldExtract(0xFF, /*lsb*/2, /*width*/3) == -1, "TestBitFieldExtract#15");
+static_assert(BitFieldExtract(0xFF, /*lsb*/3, /*width*/3) == -1, "TestBitFieldExtract#16");
+static_assert(BitFieldExtract(0xFF, /*lsb*/8, /*width*/3) == 0b00000000, "TestBitFieldExtract#17");
+static_assert(BitFieldExtract(0xFF, /*lsb*/7, /*width*/3) == 0b00000001, "TestBitFieldExtract#18");
+static_assert(BitFieldExtract(0xFF, /*lsb*/6, /*width*/3) == 0b00000011, "TestBitFieldExtract#19");
+static_assert(BitFieldExtract(static_cast<uint8_t>(0b01101010), /*lsb*/2, /*width*/4)
+                  == 0b00001010,
+              "TestBitFieldExtract#20");
+static_assert(BitFieldExtract(static_cast<int8_t>(0b01101010), /*lsb*/2, /*width*/4)
+                  == static_cast<int8_t>(0b11111010),
+              "TestBitFieldExtract#21");
+
+static_assert(BitFieldInsert(0xFF, /*data*/0x0, /*lsb*/0, /*width*/0) == 0xFF,
+              "TestBitFieldInsert#1");
+static_assert(BitFieldInsert(std::numeric_limits<uint32_t>::max(),
+                             /*data*/std::numeric_limits<uint32_t>::max(),
+                             /*lsb*/0,
+                             /*width*/32)
+                  == std::numeric_limits<uint32_t>::max(),
+              "TestBitFieldInsert#2");
+static_assert(BitFieldInsert(std::numeric_limits<int32_t>::max(),
+                             /*data*/std::numeric_limits<uint32_t>::max(),
+                             /*lsb*/0,
+                             /*width*/32)
+                  == std::numeric_limits<uint32_t>::max(),
+              "TestBitFieldInsert#3");
+static_assert(BitFieldInsert(0u,
+                             /*data*/std::numeric_limits<uint32_t>::max(),
+                             /*lsb*/0,
+                             /*width*/32)
+                  == std::numeric_limits<uint32_t>::max(),
+              "TestBitFieldInsert#4");
+static_assert(BitFieldInsert(-(-0),
+                             /*data*/std::numeric_limits<uint32_t>::max(),
+                             /*lsb*/0,
+                             /*width*/32)
+                  == std::numeric_limits<uint32_t>::max(),
+              "TestBitFieldInsert#5");
+static_assert(BitFieldInsert(0x00, /*data*/0b11u, /*lsb*/0, /*width*/2) == 0b00000011,
+              "TestBitFieldInsert#6");
+static_assert(BitFieldInsert(0x00, /*data*/0b111u, /*lsb*/0, /*width*/3) == 0b00000111,
+              "TestBitFieldInsert#7");
+static_assert(BitFieldInsert(0x00, /*data*/0b111u, /*lsb*/1, /*width*/3) == 0b00001110,
+              "TestBitFieldInsert#8");
+static_assert(BitFieldInsert(0x00, /*data*/0b111u, /*lsb*/2, /*width*/3) == 0b00011100,
+              "TestBitFieldInsert#9");
+static_assert(BitFieldInsert(0b01011100, /*data*/0b1101u, /*lsb*/4, /*width*/4) == 0b11011100,
+              "TestBitFieldInsert#10");
+
 template <typename Container>
 void CheckElements(const std::initializer_list<uint32_t>& expected, const Container& elements) {
   auto expected_it = expected.begin();