this repo has no description
at trunk 128 lines 3.8 kB view raw
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