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