this repo has no description
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */
2#pragma once
3
4#include "objects.h"
5#include "symbols.h"
6#include "utils.h"
7
8namespace py {
9
10enum AttributeFlags {
11 kNone = 0,
12
13 // When set, this indicates that the attribute is stored directly on the
14 // instance. When unset, this indicates that the attribute is stored in
15 // the overflow array attached to the instance.
16 kInObject = 1 << 0,
17
18 // Only applies to in-object attributes. When set, it indicates that the
19 // attribute has been deleted.
20 kDeleted = 1 << 1,
21
22 // Attribute lives at a fixed offset in the layout.
23 kFixedOffset = 1 << 2,
24
25 // Attribute is read-only for managed code.
26 kReadOnly = 1 << 3,
27
28 // Attribute is hidden from managed code but visible to tooling.
29 kHidden = 1 << 4,
30
31 // When set, this attribute should be initialized to Unbound to mark it as
32 // undefined when accessed before initizliation by the user.
33 kInitWithUnbound = 1 << 5,
34};
35
36// AttributeInfo packs attribute metadata into a SmallInt.
37class AttributeInfo {
38 public:
39 explicit AttributeInfo(RawObject value) {
40 DCHECK(value.isSmallInt(), "expected small integer");
41 value_ = value.raw();
42 }
43
44 AttributeInfo() : value_(RawObject::kSmallIntTag) {}
45
46 AttributeInfo(word offset, word flags) : value_(RawObject::kSmallIntTag) {
47 DCHECK(isValidOffset(offset), "offset %ld too large (max is %ld)", offset,
48 kMaxOffset);
49 value_ |= (offset << kOffsetOffset);
50 value_ |= (flags << kFlagsOffset);
51 }
52
53 // Getters and setters.
54
55 // Retrieve the offset at which the attribute is stored.
56 //
57 // Check the kInObject flag to determine whether to retrieve the attribute
58 // from the instance directly or from the overflow attributes.
59 //
60 // NB: For in-object attributes, this is the offset, in bytes, from the start
61 // of the instance. For overflow attributes, this is the index into the
62 // overflow array.
63 word offset();
64 static bool isValidOffset(word offset) { return offset <= kMaxOffset; }
65
66 AttributeFlags flags();
67 bool hasFlag(AttributeFlags flag);
68
69 bool isInObject() { return hasFlag(AttributeFlags::kInObject); }
70
71 bool isOverflow() { return !hasFlag(AttributeFlags::kInObject); }
72
73 bool isDeleted() { return hasFlag(AttributeFlags::kDeleted); }
74
75 bool isFixedOffset() { return hasFlag(AttributeFlags::kFixedOffset); }
76
77 bool isHidden() { return hasFlag(AttributeFlags::kHidden); }
78
79 bool isReadOnly() { return hasFlag(AttributeFlags::kReadOnly); }
80
81 bool isInitWithUnbound() { return hasFlag(AttributeFlags::kInitWithUnbound); }
82
83 // Casting.
84 RawSmallInt asSmallInt();
85
86 // Tags.
87 static const int kOffsetSize = 30;
88 static const int kOffsetOffset = RawObject::kSmallIntTagBits;
89 static const uword kOffsetMask = (1 << kOffsetSize) - 1;
90
91 static const int kFlagsSize = 33;
92 static const int kFlagsOffset = kOffsetOffset + kOffsetSize;
93 static const uword kFlagsMask = (1UL << kFlagsSize) - 1;
94
95 static_assert(
96 RawObject::kSmallIntTagBits + kOffsetSize + kFlagsSize == kBitsPerPointer,
97 "Number of bits used by AttributeInfo must fit in a RawSmallInt");
98
99 // Constants
100 static const word kMaxOffset = (1L << (kOffsetSize + 1)) - 1;
101
102 private:
103 uword value_;
104};
105
106struct BuiltinAttribute {
107 SymbolId name;
108 int offset;
109 AttributeFlags flags;
110};
111
112inline word AttributeInfo::offset() {
113 return (value_ >> kOffsetOffset) & kOffsetMask;
114}
115
116inline AttributeFlags AttributeInfo::flags() {
117 return static_cast<AttributeFlags>((value_ >> kFlagsOffset) & kFlagsMask);
118}
119
120inline bool AttributeInfo::hasFlag(AttributeFlags flag) {
121 return value_ & (static_cast<uword>(flag) << kFlagsOffset);
122}
123
124inline RawSmallInt AttributeInfo::asSmallInt() {
125 return RawSmallInt::cast(RawObject{value_});
126}
127
128} // namespace py