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