1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_BITFIELD_H_
6#define RUNTIME_VM_BITFIELD_H_
7
8#include "platform/assert.h"
9#include "platform/globals.h"
10
11namespace dart {
12
13static const uword kUwordOne = 1U;
14
15// BitField is a template for encoding and decoding a value of type T
16// inside a storage of type S.
17template <typename S, typename T, int position, int size>
18class BitField {
19 public:
20 typedef T Type;
21
22 static_assert((sizeof(S) * kBitsPerByte) >= (position + size),
23 "BitField does not fit into the type.");
24
25 static const intptr_t kNextBit = position + size;
26
27 // Tells whether the provided value fits into the bit field.
28 static constexpr bool is_valid(T value) {
29 return (static_cast<S>(value) & ~((kUwordOne << size) - 1)) == 0;
30 }
31
32 // Returns a S mask of the bit field.
33 static constexpr S mask() { return (kUwordOne << size) - 1; }
34
35 // Returns a S mask of the bit field which can be applied directly to
36 // to the raw unshifted bits.
37 static constexpr S mask_in_place() {
38 return ((kUwordOne << size) - 1) << position;
39 }
40
41 // Returns the shift count needed to right-shift the bit field to
42 // the least-significant bits.
43 static constexpr int shift() { return position; }
44
45 // Returns the size of the bit field.
46 static constexpr int bitsize() { return size; }
47
48 // Returns an S with the bit field value encoded.
49 static UNLESS_DEBUG(constexpr) S encode(T value) {
50 DEBUG_ASSERT(is_valid(value));
51 return static_cast<S>(value) << position;
52 }
53
54 // Extracts the bit field from the value.
55 static constexpr T decode(S value) {
56 return static_cast<T>((value >> position) & ((kUwordOne << size) - 1));
57 }
58
59 // Returns an S with the bit field value encoded based on the
60 // original value. Only the bits corresponding to this bit field
61 // will be changed.
62 static UNLESS_DEBUG(constexpr) S update(T value, S original) {
63 DEBUG_ASSERT(is_valid(value));
64 return (static_cast<S>(value) << position) | (~mask_in_place() & original);
65 }
66};
67
68} // namespace dart
69
70#endif // RUNTIME_VM_BITFIELD_H_
71