1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_LIBARTBASE_BASE_BIT_FIELD_H_ 18 #define ART_LIBARTBASE_BASE_BIT_FIELD_H_ 19 20 #include <android-base/logging.h> 21 22 #include "globals.h" 23 24 namespace art { 25 26 static constexpr uintptr_t kUintPtrTOne = 1U; 27 28 // BitField is a template for encoding and decoding a bit field inside 29 // an unsigned machine word. 30 template<typename T, size_t kPosition, size_t kSize> 31 class BitField { 32 public: 33 typedef T value_type; 34 static constexpr size_t position = kPosition; 35 static constexpr size_t size = kSize; 36 37 static_assert(position < sizeof(uintptr_t) * kBitsPerByte, "Invalid position."); 38 static_assert(size != 0u, "Invalid size."); 39 static_assert(size <= sizeof(uintptr_t) * kBitsPerByte, "Invalid size."); 40 static_assert(size + position <= sizeof(uintptr_t) * kBitsPerByte, "Invalid position + size."); 41 42 // Tells whether the provided value fits into the bit field. IsValid(T value)43 static bool IsValid(T value) { 44 return (static_cast<uintptr_t>(value) & ~((kUintPtrTOne << size) - 1)) == 0; 45 } 46 47 // Returns a uword mask of the bit field. Mask()48 static uintptr_t Mask() { 49 return (kUintPtrTOne << size) - 1; 50 } 51 52 // Returns a uword mask of the bit field which can be applied directly to 53 // the raw unshifted bits. MaskInPlace()54 static uintptr_t MaskInPlace() { 55 return ((kUintPtrTOne << size) - 1) << position; 56 } 57 58 // Returns the shift count needed to right-shift the bit field to 59 // the least-significant bits. Shift()60 static int Shift() { 61 return position; 62 } 63 64 // Returns the size of the bit field. BitSize()65 static int BitSize() { 66 return size; 67 } 68 69 // Returns a uword with the bit field value encoded. Encode(T value)70 static uintptr_t Encode(T value) { 71 DCHECK(IsValid(value)); 72 return static_cast<uintptr_t>(value) << position; 73 } 74 75 // Extracts the bit field from the value. Decode(uintptr_t value)76 static T Decode(uintptr_t value) { 77 return static_cast<T>((value >> position) & ((kUintPtrTOne << size) - 1)); 78 } 79 80 // Returns a uword with the bit field value encoded based on the 81 // original value. Only the bits corresponding to this bit field 82 // will be changed. Update(T value,uintptr_t original)83 static uintptr_t Update(T value, uintptr_t original) { 84 DCHECK(IsValid(value)); 85 return (static_cast<uintptr_t>(value) << position) | 86 (~MaskInPlace() & original); 87 } 88 }; 89 90 } // namespace art 91 92 #endif // ART_LIBARTBASE_BASE_BIT_FIELD_H_ 93