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_RUNTIME_BASE_BIT_FIELD_H_
18 #define ART_RUNTIME_BASE_BIT_FIELD_H_
19 
20 #include "globals.h"
21 #include "logging.h"
22 
23 namespace art {
24 
25 static constexpr uintptr_t kUintPtrTOne = 1U;
26 
27 // BitField is a template for encoding and decoding a bit field inside
28 // an unsigned machine word.
29 template<typename T, size_t kPosition, size_t kSize>
30 class BitField {
31  public:
32   typedef T value_type;
33   static constexpr size_t position = kPosition;
34   static constexpr size_t size = kSize;
35 
36   static_assert(position < sizeof(uintptr_t) * kBitsPerByte, "Invalid position.");
37   static_assert(size != 0u, "Invalid size.");
38   static_assert(size <= sizeof(uintptr_t) * kBitsPerByte, "Invalid size.");
39   static_assert(size + position <= sizeof(uintptr_t) * kBitsPerByte, "Invalid position + size.");
40 
41   // Tells whether the provided value fits into the bit field.
IsValid(T value)42   static bool IsValid(T value) {
43     return (static_cast<uintptr_t>(value) & ~((kUintPtrTOne << size) - 1)) == 0;
44   }
45 
46   // Returns a uword mask of the bit field.
Mask()47   static uintptr_t Mask() {
48     return (kUintPtrTOne << size) - 1;
49   }
50 
51   // Returns a uword mask of the bit field which can be applied directly to
52   // the raw unshifted bits.
MaskInPlace()53   static uintptr_t MaskInPlace() {
54     return ((kUintPtrTOne << size) - 1) << position;
55   }
56 
57   // Returns the shift count needed to right-shift the bit field to
58   // the least-significant bits.
Shift()59   static int Shift() {
60     return position;
61   }
62 
63   // Returns the size of the bit field.
BitSize()64   static int BitSize() {
65     return size;
66   }
67 
68   // Returns a uword with the bit field value encoded.
Encode(T value)69   static uintptr_t Encode(T value) {
70     DCHECK(IsValid(value));
71     return static_cast<uintptr_t>(value) << position;
72   }
73 
74   // Extracts the bit field from the value.
Decode(uintptr_t value)75   static T Decode(uintptr_t value) {
76     return static_cast<T>((value >> position) & ((kUintPtrTOne << size) - 1));
77   }
78 
79   // Returns a uword with the bit field value encoded based on the
80   // original value. Only the bits corresponding to this bit field
81   // will be changed.
Update(T value,uintptr_t original)82   static uintptr_t Update(T value, uintptr_t original) {
83     DCHECK(IsValid(value));
84     return (static_cast<uintptr_t>(value) << position) |
85         (~MaskInPlace() & original);
86   }
87 };
88 
89 }  // namespace art
90 
91 #endif  // ART_RUNTIME_BASE_BIT_FIELD_H_
92