runtime/objects.h (5,600 lines of code) (raw):
/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */
// Object structures
// -----------------
//
// This file describes the layout of built-in types on the managed heap. There
// is one class for each type providing an abstraction over a simple pointer.
// Each class provides constants for field offsets and a getter and setter
// function for each field.
//
// There should be a public getter and setter for every field using RawObject
// or word types. The code is meant to abstract over the layout, not to provide
// abstract data types: Do not add further type or consistency checks and leave
// that to higher levels.
#pragma once
#include <cstdio>
#include <limits>
#include "globals.h"
#include "utils.h"
#include "view.h"
namespace py {
class Byteslike;
class Frame;
template <typename T>
class Handle;
class Thread;
// Python types that store their value directly in a RawObject.
#define IMMEDIATE_CLASS_NAMES(V) \
V(SmallInt) \
V(SmallBytes) \
V(SmallStr) \
V(Bool) \
V(NotImplementedType) \
V(Unbound) \
V(NoneType)
// Python types that hold a pointer to heap-allocated data in a RawObject.
// Subclasses of `RawInstance` are listed separately in `INSTANCE_CLASS_NAMES`.
#define HEAP_CLASS_NAMES(V) \
V(Bytes) \
V(Complex) \
V(Ellipsis) \
V(Float) \
V(Int) \
V(LargeBytes) \
V(LargeInt) \
V(LargeStr) \
V(MutableBytes) \
V(MutableTuple) \
V(Str) \
V(Tuple)
#define INSTANCE_CLASS_NAMES(V) \
V(Array) \
V(AsyncGenerator) \
V(AsyncGeneratorAclose) \
V(AsyncGeneratorAsend) \
V(AsyncGeneratorAthrow) \
V(AsyncGeneratorOpIterBase) \
V(AsyncGeneratorWrappedValue) \
V(BoundMethod) \
V(BufferedRandom) \
V(BufferedReader) \
V(BufferedWriter) \
V(Bytearray) \
V(BytearrayIterator) \
V(BytesIO) \
V(BytesIterator) \
V(Cell) \
V(ClassMethod) \
V(Code) \
V(Context) \
V(ContextVar) \
V(Coroutine) \
V(CoroutineWrapper) \
V(Deque) \
V(DequeIterator) \
V(DequeReverseIterator) \
V(Dict) \
V(DictItemIterator) \
V(DictItems) \
V(DictKeyIterator) \
V(DictKeys) \
V(DictValueIterator) \
V(DictValues) \
V(Enumerate) \
V(ExceptionState) \
V(FileIO) \
V(FrameProxy) \
V(FrozenSet) \
V(Function) \
V(Generator) \
V(GeneratorFrame) \
V(IncrementalNewlineDecoder) \
V(InstanceMethod) \
V(InstanceProxy) \
V(Layout) \
V(List) \
V(ListIterator) \
V(LongRangeIterator) \
V(MappingProxy) \
V(MemoryView) \
V(Mmap) \
V(Module) \
V(ModuleProxy) \
V(Object) \
V(Pointer) \
V(Property) \
V(Range) \
V(RangeIterator) \
V(SeqIterator) \
V(Set) \
V(SetIterator) \
V(Slice) \
V(SlotDescriptor) \
V(StaticMethod) \
V(StrArray) \
V(StrIterator) \
V(StringIO) \
V(Super) \
V(TextIOWrapper) \
V(Token) \
V(Traceback) \
V(TupleIterator) \
V(Type) \
V(TypeProxy) \
V(UnderBufferedIOBase) \
V(UnderBufferedIOMixin) \
V(UnderIOBase) \
V(UnderRawIOBase) \
V(UnderTextIOBase) \
V(ValueCell) \
V(WeakCallableProxy) \
V(WeakProxy) \
V(WeakLink) \
V(WeakRef)
// Heap-allocated Python types in the BaseException hierarchy.
#define EXCEPTION_CLASS_NAMES(V) \
V(ArithmeticError) \
V(AssertionError) \
V(AttributeError) \
V(BaseException) \
V(BlockingIOError) \
V(BrokenPipeError) \
V(BufferError) \
V(BytesWarning) \
V(ChildProcessError) \
V(ConnectionAbortedError) \
V(ConnectionError) \
V(ConnectionRefusedError) \
V(ConnectionResetError) \
V(DeprecationWarning) \
V(EOFError) \
V(Exception) \
V(FileExistsError) \
V(FileNotFoundError) \
V(FloatingPointError) \
V(FutureWarning) \
V(GeneratorExit) \
V(ImportError) \
V(ImportWarning) \
V(IndentationError) \
V(IndexError) \
V(InterruptedError) \
V(IsADirectoryError) \
V(KeyboardInterrupt) \
V(KeyError) \
V(LookupError) \
V(MemoryError) \
V(ModuleNotFoundError) \
V(NameError) \
V(NotADirectoryError) \
V(NotImplementedError) \
V(OSError) \
V(OverflowError) \
V(PendingDeprecationWarning) \
V(PermissionError) \
V(ProcessLookupError) \
V(RecursionError) \
V(ReferenceError) \
V(ResourceWarning) \
V(RuntimeError) \
V(RuntimeWarning) \
V(StopAsyncIteration) \
V(StopIteration) \
V(SyntaxError) \
V(SyntaxWarning) \
V(SystemError) \
V(SystemExit) \
V(TabError) \
V(TimeoutError) \
V(TypeError) \
V(UnboundLocalError) \
V(UnicodeDecodeError) \
V(UnicodeEncodeError) \
V(UnicodeError) \
V(UnicodeTranslateError) \
V(UnicodeWarning) \
V(UserWarning) \
V(ValueError) \
V(Warning) \
V(ZeroDivisionError)
#define CLASS_NAMES(V) \
IMMEDIATE_CLASS_NAMES(V) \
HEAP_CLASS_NAMES(V) \
INSTANCE_CLASS_NAMES(V) \
EXCEPTION_CLASS_NAMES(V)
// This enumerates layout ids of intrinsic classes. Notably, the layout of an
// instance of an intrinsic class does not change.
//
// An instance of an intrinsic class that has an immediate representation
// cannot have attributes added. An instance of an intrinsic class that is heap
// allocated has a predefined number in-object attributes in the base
// instance. For some of those types, the language forbids adding new
// attributes. For the types which are permitted to have attributes added,
// these types must include a hidden attribute that indirects to attribute
// storage.
//
// NB: If you add something here make sure you add it to the appropriate macro
// above
enum class LayoutId : word {
// Immediate objects - note that the SmallInt class is also aliased to all
// even integers less than 32, so that classes of immediate objects can be
// looked up simply by using the low 5 bits of the immediate value. This
// implies that all other immediate class ids must be odd.
kSmallInt = 0,
kSmallBytes = 5,
kBool = 7,
kSmallStr = 13,
kNotImplementedType = 15,
// There is no RawType associated with the RawError object type, this is here
// as a placeholder.
kError = 21,
kUnbound = 23,
// We have room for one more immediate object with LayoutId = 29
kNoneType = 31,
// clang-format off
// Heap objects
#define LAYOUT_ID(name) k##name,
#define GET_FIRST(name) k##name + 0 *
#define GET_LAST(name) 0 + k##name *
HEAP_CLASS_NAMES(LAYOUT_ID)
kLastNonInstance = HEAP_CLASS_NAMES(GET_LAST) 1,
INSTANCE_CLASS_NAMES(LAYOUT_ID)
EXCEPTION_CLASS_NAMES(LAYOUT_ID)
// Mark the first and last Exception LayoutIds, to allow range comparisons.
kFirstException = EXCEPTION_CLASS_NAMES(GET_FIRST) 0,
kLastException = EXCEPTION_CLASS_NAMES(GET_LAST) 1,
#undef GET_FIRST
#undef GET_LAST
#undef LAYOUT_ID
// clang-format on
kLastBuiltinId = kLastException,
kSentinelId = kLastBuiltinId + 1,
};
// Add functionality common to all RawObject subclasses, split into two parts
// since some types manually define cast() but want everything else.
#define RAW_OBJECT_COMMON_NO_CAST(ty) \
/* TODO(T34683229): Once Handle<T> doesn't inherit from T, delete this. \
* Right now it exists to prevent implicit conversion of Handle<T> to T. */ \
template <typename T> \
Raw##ty(const Handle<T>&) = delete; \
DISALLOW_HEAP_ALLOCATION()
#define RAW_OBJECT_COMMON(ty) \
static Raw##ty cast(RawObject object) { \
DCHECK(object.is##ty(), "invalid cast, expected " #ty); \
return object.rawCast<Raw##ty>(); \
} \
RAW_OBJECT_COMMON_NO_CAST(ty)
const int kObjectAlignmentLog2 = 4; // bits
const int kObjectAlignment = word{1} << kObjectAlignmentLog2;
bool isInstanceLayout(LayoutId id);
word roundAllocationSize(word size);
class RawObject {
public:
explicit RawObject(uword raw);
// Getters and setters.
uword raw() const;
bool isObject() const;
bool isInternal() const;
LayoutId layoutId() const;
// Immediate objects
bool isBool() const;
bool isError() const;
bool isErrorError() const;
bool isErrorException() const;
bool isErrorNoMoreItems() const;
bool isErrorNotFound() const;
bool isErrorOutOfBounds() const;
bool isErrorOutOfMemory() const;
bool isHeader() const;
bool isImmediateObjectNotSmallInt() const;
bool isNoneType() const;
bool isNotImplementedType() const;
bool isSmallBytes() const;
bool isSmallInt() const;
bool isSmallStr() const;
bool isUnbound() const;
// Heap objects
bool isArray() const;
bool isAsyncGenerator() const;
bool isAsyncGeneratorAclose() const;
bool isAsyncGeneratorAsend() const;
bool isAsyncGeneratorAthrow() const;
bool isAsyncGeneratorOpIterBase() const;
bool isAsyncGeneratorWrappedValue() const;
bool isAttributeDict() const;
bool isBaseException() const;
bool isBoundMethod() const;
bool isBufferedRandom() const;
bool isBufferedReader() const;
bool isBufferedWriter() const;
bool isBytearray() const;
bool isBytearrayIterator() const;
bool isBytesIO() const;
bool isBytesIterator() const;
bool isCell() const;
bool isClassMethod() const;
bool isCode() const;
bool isComplex() const;
bool isContext() const;
bool isContextVar() const;
bool isCoroutine() const;
bool isCoroutineWrapper() const;
bool isDataArray() const;
bool isDeque() const;
bool isDequeIterator() const;
bool isDequeReverseIterator() const;
bool isDict() const;
bool isDictItemIterator() const;
bool isDictItems() const;
bool isDictKeyIterator() const;
bool isDictKeys() const;
bool isDictValueIterator() const;
bool isDictValues() const;
bool isEllipsis() const;
bool isEnumerate() const;
bool isException() const;
bool isExceptionState() const;
bool isFileIO() const;
bool isFloat() const;
bool isFrameProxy() const;
bool isFrozenSet() const;
bool isFunction() const;
bool isGenerator() const;
bool isGeneratorFrame() const;
bool isHeapObject() const;
bool isHeapObjectWithLayout(LayoutId layout_id) const;
bool isImportError() const;
bool isIncrementalNewlineDecoder() const;
bool isIndexError() const;
bool isInstance() const;
bool isInstanceMethod() const;
bool isInstanceProxy() const;
bool isKeyError() const;
bool isLargeBytes() const;
bool isLargeInt() const;
bool isLargeStr() const;
bool isLayout() const;
bool isList() const;
bool isListIterator() const;
bool isLongRangeIterator() const;
bool isLookupError() const;
bool isMappingProxy() const;
bool isMemoryView() const;
bool isMmap() const;
bool isModule() const;
bool isModuleNotFoundError() const;
bool isModuleProxy() const;
bool isMutableBytes() const;
bool isMutableTuple() const;
bool isNotImplementedError() const;
bool isPointer() const;
bool isProperty() const;
bool isRange() const;
bool isRangeIterator() const;
bool isRuntimeError() const;
bool isSeqIterator() const;
bool isSet() const;
bool isSetIterator() const;
bool isSlice() const;
bool isSlotDescriptor() const;
bool isStaticMethod() const;
bool isStopIteration() const;
bool isStrArray() const;
bool isStrIterator() const;
bool isStringIO() const;
bool isSuper() const;
bool isSyntaxError() const;
bool isSystemExit() const;
bool isTextIOWrapper() const;
bool isToken() const;
bool isTraceback() const;
bool isTuple() const;
bool isTupleIterator() const;
bool isType() const;
bool isTypeProxy() const;
bool isUnderBufferedIOBase() const;
bool isUnderBufferedIOMixin() const;
bool isUnderIOBase() const;
bool isUnderRawIOBase() const;
bool isUnicodeDecodeError() const;
bool isUnicodeEncodeError() const;
bool isUnicodeError() const;
bool isUnicodeErrorBase() const;
bool isUnicodeTranslateError() const;
bool isValueCell() const;
bool isWeakCallableProxy() const;
bool isWeakProxy() const;
bool isWeakLink() const;
bool isWeakRef() const;
// superclass objects
bool isBytes() const;
bool isGeneratorBase() const;
bool isInt() const;
bool isSetBase() const;
bool isStr() const;
bool operator==(const RawObject& other) const;
bool operator!=(const RawObject& other) const;
// Constants
// Tags.
static const uword kSmallIntTag = 0; // 0b****0
static const uword kHeapObjectTag = 1; // 0b**001
static const uword kHeaderTag = 3; // 0b**011
static const uword kSmallBytesTag = 5; // 0b00101
static const uword kSmallStrTag = 13; // 0b01101
static const uword kErrorTag = 21; // 0b10101
// 0b11101 is unused
static const uword kBoolTag = 7; // 0b00111
static const uword kNotImplementedTag = 15; // 0b01111
static const uword kUnboundTag = 23; // 0b10111
static const uword kNoneTag = 31; // 0b11111
// Up to the five least significant bits are used to tag the object's layout.
// The three low bits make up a primary tag, used to differentiate Header and
// HeapObject from immediate objects. All even tags map to SmallInt, which is
// optimized by checking only the lowest bit for parity.
static const uword kSmallIntTagBits = 1;
static const uword kPrimaryTagBits = 3;
static const uword kImmediateTagBits = 5;
static const uword kSmallIntTagMask = (1 << kSmallIntTagBits) - 1;
static const uword kPrimaryTagMask = (1 << kPrimaryTagBits) - 1;
static const uword kImmediateTagMask = (1 << kImmediateTagBits) - 1;
// Cast this RawObject to another Raw* type with no runtime checks. Only used
// in a few limited situations; most code should use Raw*::cast() instead.
template <typename T>
T rawCast() const;
RAW_OBJECT_COMMON(Object);
private:
// Zero-initializing raw_ gives RawSmallInt::fromWord(0).
uword raw_{};
};
// CastError and OptInt<T> represent the result of a call to RawInt::asInt<T>():
// If error == CastError::None, value contains the result. Otherwise, error
// indicates why the value didn't fit in T.
enum class CastError {
None,
Underflow,
Overflow,
};
template <typename T>
class OptInt {
public:
static OptInt valid(T i) { return {i, CastError::None}; }
static OptInt underflow() { return {0, CastError::Underflow}; }
static OptInt overflow() { return {0, CastError::Overflow}; }
T value;
CastError error;
};
// Generic superclasses for Python types with multiple native types
// Common `bytes` wrapper around RawSmallBytes/RawLargeBytes
class RawBytes : public RawObject {
public:
// Singleton.
static RawBytes empty();
// Getters and setters.
word length() const;
byte byteAt(word index) const;
void copyTo(byte* dst, word length) const;
// Copy length bytes from this to dst, starting at the given index
void copyToStartAt(byte* dst, word length, word index) const;
bool isASCII() const;
// Read adjacent bytes as `uint16_t` integer.
uint16_t uint16At(word index) const;
// Read adjacent bytes as `uint32_t` integer.
uint32_t uint32At(word index) const;
// Read adjacent bytes as `uint64_t` integer.
uint64_t uint64At(word index) const;
// Rewrite the header to make UTF-8 conformant bytes look like a Str
RawObject becomeStr() const;
// Returns a positive value if 'this' is greater than 'that', a negative value
// if 'this' is less than 'that', and zero if they are the same.
// Does not guarantee to return -1, 0, or 1.
word compare(RawBytes that) const;
// Returns the index at which value is found in this[start:start+length] (not
// including end), or -1 if not found.
word findByte(byte value, word start, word length) const;
// Check for the presence of a non-zero byte.
bool includesByte(byte b) const;
// Conversion to an unescaped C string. The underlying memory is allocated
// with malloc and must be freed by the caller.
char* toCStr() const;
RAW_OBJECT_COMMON(Bytes);
};
// Common `int` wrapper around RawSmallInt/RawLargeInt/RawBool
class RawInt : public RawObject {
public:
// Getters and setters.
word asWord() const;
// Returns the value as a word if it fits into a word.
// Otherwise, returns kMinWord for negative values or kMaxWord for positive
// values.
word asWordSaturated() const;
void* asCPtr() const;
// If this fits in T, get its value as a T. If not, indicate what went wrong.
template <typename T>
OptInt<T> asInt() const;
// Returns a positive value if 'this' is greater than 'other', zero if it
// is the same, a negavite value if smaller. The value does not have to be
// -1, 0, or 1.
word compare(RawInt that) const;
word bitLength() const;
bool isEven() const;
bool isNegative() const;
bool isOdd() const;
bool isPositive() const;
bool isZero() const;
// Indexing into digits
uword digitAt(word index) const;
// Number of digits
word numDigits() const;
// Copies digits bytewise to `dst`. Returns number of bytes copied.
word copyTo(byte* dst, word max_length) const;
RAW_OBJECT_COMMON(Int);
};
// Common `str` wrapper around RawSmallStr/RawLargeStr
class RawStr : public RawObject {
public:
// Singletons.
static RawStr empty();
// Getters and setters.
byte byteAt(word index) const;
word length() const;
void copyTo(byte* dst, word char_length) const;
void copyToStartAt(byte* dst, word char_length, word char_start) const;
// Equality checks.
word compare(RawStr that) const;
word compareCStr(const char* c_str) const;
bool equals(RawStr that) const;
bool equalsCStr(const char* c_str) const;
bool includes(RawObject that) const;
// Check for the presence of a non-zero byte.
bool includesByte(byte b) const;
// Codepoints
int32_t codePointAt(word char_index, word* char_length) const;
word codePointLength() const;
bool isASCII() const;
// Find the number of occurences of substring `needle`.
word occurrencesOf(RawObject that) const;
// Returns an index into a string offset by either a positive or negative
// number of code points. Otherwise, if the new index would be negative, -1
// is returned or if the new index would be greater than the length of the
// string, the length is returned.
word offsetByCodePoints(word char_index, word count) const;
// Conversion to an unescaped C string. The underlying memory is allocated
// with malloc and must be freed by the caller.
char* toCStr() const;
RAW_OBJECT_COMMON(Str);
};
// Immediate objects
class RawSmallInt : public RawObject {
public:
// Getters and setters.
word value() const;
void* asCPtr() const;
// Converts a `SmallInt` created by `fromAlignedCPtr()` back to a pointer.
void* asAlignedCPtr() const;
word asReinterpretedWord() const;
// If this fits in T, get its value as a T. If not, indicate what went wrong.
template <typename T>
if_signed_t<T, OptInt<T>> asInt() const;
template <typename T>
if_unsigned_t<T, OptInt<T>> asInt() const;
word hash() const;
// Construction.
static RawSmallInt fromWord(word value);
static RawSmallInt fromWordTruncated(word value);
// Reinterpret a word value with the lowest `kSmallIntTagBits` cleared
// directly as a `RawSmallInt` value, without performing the usual shift.
static RawSmallInt fromReinterpretedWord(word value);
// Create a `SmallInt` from an aligned C pointer.
// This is slightly faster than `Runtime::newIntFromCPtr()` but only works for
// pointers with an alignment of at least `2**kSmallIntTagBits`.
// Use `toAlignedCPtr()` to reverse this operation; `toCPtr()` will not work
// correctly.
static RawSmallInt fromAlignedCPtr(void* ptr);
static constexpr bool isValid(word value) {
return (value >= kMinValue) && (value <= kMaxValue);
}
static word truncate(word value);
// Constants.
static const word kBits = kBitsPerPointer - kSmallIntTagBits;
static const word kMinValue = -(word{1} << (kBits - 1));
static const word kMaxValue = (word{1} << (kBits - 1)) - 1;
static const word kMaxDigits10 = 18;
static const word kMaxDigits10Pow = 1000000000000000000;
static_assert((kMaxDigits10Pow <= kMaxValue) &&
(kMaxDigits10Pow > kMaxValue / 10),
"invalid max");
RAW_OBJECT_COMMON(SmallInt);
};
enum class ObjectFormat {
// Instances that do not contain objects
kData = 0,
// Instances that contain objects
kObjects = 1,
};
// RawHeader objects
//
// Headers are located in first logical word of a heap allocated object and
// contain metadata related to the object its part of. A header is not
// really object that the user will interact with directly. Nevertheless, we
// tag them as immediate object. This allows the runtime to identify the start
// of an object when scanning the heap.
//
// Headers encode the following information
//
// Name Size Description
// ----------------------------------------------------------------------------
// Tag 3 tag for a header object
// Format 1 enumeration describing the object encoding
// LayoutId 20 identifier for the layout, allowing 2^20 unique layouts
// Count 8 number of array elements or instance variables
// Hash 32 bits to use for an identity hash code
class RawHeader : public RawObject {
public:
word hashCode() const;
RawHeader withHashCode(word value) const;
ObjectFormat format() const;
LayoutId layoutId() const;
RawHeader withLayoutId(LayoutId layout_id) const;
word count() const;
bool hasOverflow() const;
static RawHeader from(word count, word hash, LayoutId id,
ObjectFormat format);
// Layout.
static const int kFormatBits = 1;
static const int kFormatOffset = kPrimaryTagBits;
static const uword kFormatMask = (1 << kFormatBits) - 1;
static const int kLayoutIdBits = 20;
static const int kLayoutIdOffset = kFormatOffset + kFormatBits;
static const uword kLayoutIdMask = (1 << kLayoutIdBits) - 1;
static const int kCountBits = 8;
static const int kCountOffset = kLayoutIdOffset + kLayoutIdBits;
static const uword kCountMask = (1 << kCountBits) - 1;
static const int kHashCodeBits = 32;
static const int kHashCodeOffset = kCountOffset + kCountBits;
static const uword kHashCodeMask = (1UL << kHashCodeBits) - 1;
static const int kTotalBits = kHashCodeOffset + kHashCodeBits;
static_assert(kTotalBits == 64, "Header should be exactly 64 bits");
static const int kCountOverflowFlag = (1 << kCountBits) - 1;
static const int kCountMax = kCountOverflowFlag - 1;
static const int kSize = kPointerSize;
// Constants
static const word kMaxLayoutId = (1L << (kLayoutIdBits + 1)) - 1;
static const word kUninitializedHash = 0;
RAW_OBJECT_COMMON(Header);
};
class RawSmallData : public RawObject {
public:
// Getters and setters.
word length() const;
byte byteAt(word index) const;
void copyTo(byte* dst, word length) const;
// Copy length bytes from this to dst, starting at the given index
void copyToStartAt(byte* dst, word length, word index) const;
bool isASCII() const;
// Read adjacent bytes as `uint16_t` integer.
uint16_t uint16At(word index) const;
// Read adjacent bytes as `uint32_t` integer.
uint32_t uint32At(word index) const;
// Returns the index at which value is found in this[start:start+length] (not
// including end), or -1 if not found.
word findByte(byte value, word start, word length) const;
// Check for the presence of a non-zero byte.
bool includesByte(byte b) const;
// Codepoints
int32_t codePointAt(word char_index, word* char_length) const;
word codePointLength() const;
word offsetByCodePoints(word index, word count) const;
// Conversion to an unescaped C string. The underlying memory is allocated
// with malloc and must be freed by the caller.
char* toCStr() const;
word hash() const;
// Constants.
static const word kMaxLength = kWordSize - 1;
static const word kDataOffset = 1;
protected:
explicit RawSmallData(uword raw);
};
class RawSmallBytes : public RawSmallData {
public:
// Construction.
static RawSmallBytes fromBytes(View<byte> data);
static RawSmallBytes empty();
// Rewrite the tag byte to make UTF-8 conformant bytes look like a Str
RawObject becomeStr() const;
RAW_OBJECT_COMMON(SmallBytes);
private:
explicit RawSmallBytes(uword raw);
};
class RawSmallStr : public RawSmallData {
public:
// Construction.
static RawSmallStr fromCodePoint(int32_t code_point);
static RawSmallStr fromCStr(const char* value);
static RawSmallStr fromBytes(View<byte> data);
static RawSmallStr empty();
// Comparison
word compare(RawObject that) const;
word equalsCStr(const char* c_str) const;
bool includes(RawObject that) const;
// Check for the presence of a non-zero byte.
bool includesByte(byte b) const;
word occurrencesOf(RawObject that) const;
RawObject becomeBytes() const;
// Constants.
static const word kMaxLength = kWordSize - 1;
RAW_OBJECT_COMMON(SmallStr);
private:
explicit RawSmallStr(uword raw);
};
// An ErrorKind is in every RawError to give some high-level detail about what
// went wrong.
//
// Note that the only ErrorKind that implies a raised exception is Exception.
// All others are used either in situations where an exception wouldn't be
// appropriate, or where the error could be intercepted by runtime code before
// it has to be materialized into an actual exception, to avoid memory traffic
// on the Thread.
enum class ErrorKind : byte {
// Generic RawError: when none of the other kinds fit. Should be avoided if
// possible.
kNone,
// An exception was raised, and Thread::current()->hasPendingException() is
// true.
kException,
// The attribute/function/dict entry/other named entity requested by the
// caller was not found.
kNotFound,
// The given index was out of bounds for the container being searched.
kOutOfBounds,
// An allocation failed due to insufficient memory.
kOutOfMemory,
// An iterator hit the end of its container.
kNoMoreItems,
// If the largest ErrorKind is ever > 7, the immediate objects won't fit in
// one byte, which may have performance implications.
};
// RawError is a special object type, internal to the runtime. It is used to
// signal that an error has occurred inside the runtime or native code, e.g. an
// exception has been raised or a value wasn't found during a lookup.
class RawError : public RawObject {
public:
// Singletons. See the documentation for ErrorKind for what each one means.
static RawError error();
static RawError exception();
static RawError noMoreItems();
static RawError notFound();
static RawError outOfBounds();
static RawError outOfMemory();
// Kind.
ErrorKind kind() const;
// Bit Layout.
static const int kTagMask = (1 << kBitsPerByte) - 1;
static const int kKindOffset = kBitsPerByte;
static const int kKindBits = 3;
RAW_OBJECT_COMMON(Error);
private:
RawError(ErrorKind kind);
};
// Force users to call RawObject::isError*() rather than
// obj == Error::error(), since there isn't one unique RawError.
bool operator==(const RawError&, const RawObject&) = delete;
bool operator==(const RawObject&, const RawError&) = delete;
bool operator!=(const RawError&, const RawObject&) = delete;
bool operator!=(const RawObject&, const RawError&) = delete;
class RawBool : public RawObject {
public:
// Getters and setters.
bool value() const;
word hash() const;
// Singletons
static RawBool trueObj();
static RawBool falseObj();
// Construction.
static RawBool fromBool(bool value);
static RawBool negate(RawObject value);
// Bit Layout.
static const int kTagMask = (1 << kBitsPerByte) - 1;
static const int kValueOffset = kBitsPerByte;
RAW_OBJECT_COMMON(Bool);
};
class RawNotImplementedType : public RawObject {
public:
// Singletons.
static RawNotImplementedType object();
RAW_OBJECT_COMMON(NotImplementedType);
};
class RawUnbound : public RawObject {
public:
// Singletons.
static RawUnbound object();
RAW_OBJECT_COMMON(Unbound);
};
class RawNoneType : public RawObject {
public:
// Singletons.
static RawNoneType object();
RAW_OBJECT_COMMON(NoneType);
};
// Heap objects
class RawHeapObject : public RawObject {
public:
// Getters and setters.
uword address() const;
uword baseAddress() const;
RawHeader header() const;
void setHeader(RawHeader header) const;
word headerOverflow() const;
word headerCountOrOverflow() const;
word size() const;
// Construction.
static RawHeapObject fromAddress(uword address);
static RawHeapObject initializeHeader(uword address, word count, word hash,
LayoutId id, ObjectFormat format);
// Sizing
static word headerSize(word count);
// Garbage collection.
bool isRoot() const;
bool isForwarding() const;
RawObject forward() const;
void forwardTo(RawObject object) const;
// Layout.
static const int kHeaderOffset = -kPointerSize;
static const int kHeaderOverflowOffset = kHeaderOffset - kPointerSize;
static const int kSize = kHeaderOffset + kPointerSize;
RAW_OBJECT_COMMON(HeapObject);
};
// Instances are objects with attributes described via the layout system.
class RawInstance : public RawHeapObject {
public:
// Sizing.
static word allocationSize(word num_attr);
// This is only public for the inline-cache to use. All other cases should
// use more specific getter methods in the subclasses.
RawObject instanceVariableAt(word offset) const;
void instanceVariableAtPut(word offset, RawObject value) const;
void setLayoutId(LayoutId layout_id) const;
RAW_OBJECT_COMMON(Instance);
// Instance initialization should only done by the Runtime.
static RawObject initializeWithNone(uword address, word num_attributes,
LayoutId layout_id);
static RawObject initializeWithZero(uword address, word num_attributes,
LayoutId layout_id);
};
class RawBaseException : public RawInstance {
public:
// Getters and setters.
RawObject args() const;
void setArgs(RawObject args) const;
// The traceback, cause, and context can all be Unbound to indicate that they
// are "NULL" rather than the normal unset value of None. The only code that
// cares about the distinction is a handful of C-API functions, so the
// standard getters transparently replace Unbound with None. The *OrUnbound
// getters return the value as it's stored in memory, and are used
// in the few C-API functions that care about the distinction.
RawObject traceback() const;
RawObject tracebackOrUnbound() const;
void setTraceback(RawObject traceback) const;
RawObject cause() const;
RawObject causeOrUnbound() const;
void setCause(RawObject cause) const;
RawObject context() const;
RawObject contextOrUnbound() const;
void setContext(RawObject context) const;
RawObject suppressContext() const;
void setSuppressContext(RawObject suppress) const;
static const int kArgsOffset = RawHeapObject::kSize;
static const int kTracebackOffset = kArgsOffset + kPointerSize;
static const int kCauseOffset = kTracebackOffset + kPointerSize;
static const int kContextOffset = kCauseOffset + kPointerSize;
static const int kSuppressContextOffset = kContextOffset + kPointerSize;
static const int kSize = kSuppressContextOffset + kPointerSize;
RAW_OBJECT_COMMON(BaseException);
};
class RawException : public RawBaseException {
public:
RAW_OBJECT_COMMON(Exception);
};
class RawSyntaxError : public RawException {
public:
static const int kFilenameOffset = RawException::kSize;
static const int kLinenoOffset = kFilenameOffset + kPointerSize;
static const int kMsgOffset = kLinenoOffset + kPointerSize;
static const int kOffsetOffset = kMsgOffset + kPointerSize;
static const int kPrintFileAndLineOffset = kOffsetOffset + kPointerSize;
static const int kTextOffset = kPrintFileAndLineOffset + kPointerSize;
static const int kSize = kTextOffset + kPointerSize;
RAW_OBJECT_COMMON(SyntaxError);
};
class RawStopIteration : public RawBaseException {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
static const int kValueOffset = RawBaseException::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON(StopIteration);
};
class RawSystemExit : public RawBaseException {
public:
RawObject code() const;
void setCode(RawObject code) const;
static const int kCodeOffset = RawBaseException::kSize;
static const int kSize = kCodeOffset + kPointerSize;
RAW_OBJECT_COMMON(SystemExit);
};
class RawRuntimeError : public RawException {
public:
RAW_OBJECT_COMMON(RuntimeError);
};
class RawNotImplementedError : public RawRuntimeError {
public:
RAW_OBJECT_COMMON(NotImplementedError);
};
class RawImportError : public RawException {
public:
// Getters and setters
RawObject msg() const;
void setMsg(RawObject msg) const;
RawObject name() const;
void setName(RawObject name) const;
RawObject path() const;
void setPath(RawObject path) const;
static const int kMsgOffset = RawBaseException::kSize;
static const int kNameOffset = kMsgOffset + kPointerSize;
static const int kPathOffset = kNameOffset + kPointerSize;
static const int kSize = kPathOffset + kPointerSize;
RAW_OBJECT_COMMON(ImportError);
};
class RawModuleNotFoundError : public RawImportError {
public:
RAW_OBJECT_COMMON(ModuleNotFoundError);
};
class RawLookupError : public RawException {
public:
RAW_OBJECT_COMMON(LookupError);
};
class RawIndexError : public RawLookupError {
public:
RAW_OBJECT_COMMON(IndexError);
};
class RawKeyError : public RawLookupError {
public:
RAW_OBJECT_COMMON(KeyError);
};
class RawUnicodeError : public RawException {
public:
RAW_OBJECT_COMMON(UnicodeError);
};
// This is a base class to allow for code reuse in the C++ implementations of
// the UnicodeError subclasses. According to the Python type system, each
// subclass of this Base class actually subclasses UnicodeError.
class RawUnicodeErrorBase : public RawException {
public:
RawObject encoding() const;
void setEncoding(RawObject encoding_name) const;
RawObject object() const;
void setObject(RawObject value) const;
RawObject start() const;
void setStart(RawObject index) const;
RawObject end() const;
void setEnd(RawObject index) const;
RawObject reason() const;
void setReason(RawObject error_description) const;
static const int kEncodingOffset = RawBaseException::kSize;
static const int kObjectOffset = kEncodingOffset + kPointerSize;
static const int kStartOffset = kObjectOffset + kPointerSize;
static const int kEndOffset = kStartOffset + kPointerSize;
static const int kReasonOffset = kEndOffset + kPointerSize;
static const int kSize = kReasonOffset + kPointerSize;
RAW_OBJECT_COMMON(UnicodeErrorBase);
};
class RawUnicodeDecodeError : public RawUnicodeErrorBase {
public:
RAW_OBJECT_COMMON(UnicodeDecodeError);
};
class RawUnicodeEncodeError : public RawUnicodeErrorBase {
public:
RAW_OBJECT_COMMON(UnicodeEncodeError);
};
class RawUnicodeTranslateError : public RawUnicodeErrorBase {
public:
RAW_OBJECT_COMMON(UnicodeTranslateError);
};
class RawAttributeDict : public RawInstance {
public:
RawObject attributes() const;
void setAttributes(RawObject mutable_tuple) const;
word attributesRemaining() const;
void setAttributesRemaining(word free) const;
static const int kAttributesOffset = RawInstance::kSize;
static const int kAttributesRemainingOffset =
kAttributesOffset + kPointerSize;
static const int kSize = kAttributesRemainingOffset + kPointerSize;
RAW_OBJECT_COMMON(AttributeDict);
};
class RawType : public RawAttributeDict {
public:
enum Flag : word {
kNone = 0,
// Bits 0-7 are reserved to hold a LayoutId.
// Has non-empty __abstractmethods__
kIsAbstract = 1 << 8,
// The type has an attribute dictionary in cpython but is not using the
// usual tuple-overflow or dict-overflow modes in the layout to provide it.
kHasCustomDict = 1 << 9,
// Instances have a block of of memory in the unmanaged C heap attached to
// them. Instances are `RawNativeProxy`s.
kHasNativeData = 1 << 10,
// Has the extension flag Py_TPFLAGS_HAVE_GC
kHasCycleGC = 1 << 11,
// Has a default extension dealloc slot
kHasDefaultDealloc = 1 << 12,
// Has __slots__ in itself or its base
kHasSlots = 1 << 13,
// Runtime expects some attributes of this type to be at a fixed address.
kIsFixedAttributeBase = 1 << 14,
// Whether the type should behave like a CPython heap-type. Heap-types are
// the default for user defined types. Non-heap types are used for most
// built-in types. They have immutable type dictionaries and deal with
// `__module__`, `__name__` and `__qualname__` in a different way.
kIsCPythonHeaptype = 1 << 15,
// Type may be used as a base class to create subclasses. A cleared basetype
// is sometimes called "final class" in other languages.
kIsBasetype = 1 << 16,
// This type is an instance of a metaclass that defined an `mro` method and
// potentially installed an irregular MRO.
kHasCustomMro = 1 << 17,
// this_type.__getattribute__ is object.__getattribute__.
kHasObjectDunderGetattribute = 1 << 18,
// this_type.__getattribute__ is type.__getattribute__.
kHasTypeDunderGetattribute = 1 << 19,
// this_type.__getattribute__ is module.__getattribute__.
kHasModuleDunderGetattribute = 1 << 20,
// this_type.__new__ is object.__new__.
kHasObjectDunderNew = 1 << 21,
// this_type.__hash__ is object.__hash__.
kHasObjectDunderHash = 1 << 22,
// this_type.__hash__ is str.__hash__.
kHasStrDunderHash = 1 << 23,
// this_type.__bool__ exists.
kHasDunderBool = 1 << 24,
// this_type.__len__ exists.
kHasDunderLen = 1 << 25,
// this_type.__class__ is object.__class__.
kHasObjectDunderClass = 1 << 26,
// this_type.__get__ exists.
kHasDunderGet = 1 << 27,
// this_type.__set__ exists.
kHasDunderSet = 1 << 28,
// this_type.__delete__ exists.
kHasDunderDelete = 1 << 29,
// this_type.__eq__ is object.__eq__.
kHasObjectDunderEq = 1 << 30,
};
static const word kAttributeFlags =
Flag::kHasObjectDunderGetattribute | Flag::kHasTypeDunderGetattribute |
Flag::kHasModuleDunderGetattribute | Flag::kHasObjectDunderNew |
Flag::kHasObjectDunderHash | Flag::kHasStrDunderHash |
Flag::kHasDunderBool | Flag::kHasDunderLen | Flag::kHasObjectDunderClass |
Flag::kHasDunderGet | Flag::kHasDunderSet | Flag::kHasDunderDelete |
Flag::kHasObjectDunderEq;
static const word kUninheritableFlags = Flag::kIsAbstract |
Flag::kIsFixedAttributeBase |
Flag::kIsBasetype | kAttributeFlags;
static const word kInheritableFlags = ~kUninheritableFlags;
// Getters and setters.
RawObject instanceLayout() const;
void setInstanceLayout(RawObject layout) const;
LayoutId instanceLayoutId() const;
void setInstanceLayoutId(LayoutId id) const;
RawObject bases() const;
void setBases(RawObject bases_tuple) const;
RawObject doc() const;
void setDoc(RawObject doc) const;
RawObject mro() const;
void setMro(RawObject object_array) const;
RawObject name() const;
void setName(RawObject name) const;
// Flags.
//
// Bits 0-7 contain the LayoutId of the builtin base type. For builtin types,
// this is the type itself, except for subtypes of int and str, which have
// kInt and kStr, respectively. For user-defined types, it is the LayoutId of
// the first builtin base class (kObject for most types).
//
// Bits 8+ are a bitmask of flags describing certain properties of the type.
Flag flags() const;
bool hasFlag(Flag bit) const;
LayoutId builtinBase() const;
void setFlags(Flag value) const;
void setFlagsAndBuiltinBase(Flag value, LayoutId base) const;
void setBuiltinBase(LayoutId base) const;
bool isBuiltin() const;
bool hasCustomDict() const;
bool hasNativeData() const;
bool isCPythonHeaptype() const;
bool isBasetype() const;
RawObject slots() const;
void setSlots(RawObject slots) const;
RawObject abstractMethods() const;
void setAbstractMethods(RawObject methods) const;
RawObject subclasses() const;
void setSubclasses(RawObject subclasses) const;
// Lazily allocated read-only proxy to the type dict.
RawObject proxy() const;
void setProxy(RawObject proxy) const;
// Constructor function for this class. Either type.__call__ or
// a function that has the same effect as type.__call__.
RawObject ctor() const;
void setCtor(RawObject function) const;
RawObject qualname() const;
void setQualname(RawObject qualname) const;
bool isBaseExceptionSubclass() const;
// Check if the type dictionary is mutable. If the current type's dict is
// immutable, its parents' dicts are immutable too.
bool hasMutableDict() const;
// Layout.
static const int kMroOffset = RawAttributeDict::kSize;
static const int kBasesOffset = kMroOffset + kPointerSize;
static const int kInstanceLayoutOffset = kBasesOffset + kPointerSize;
static const int kInstanceLayoutIdOffset =
kInstanceLayoutOffset + kPointerSize;
static const int kNameOffset = kInstanceLayoutIdOffset + kPointerSize;
static const int kDocOffset = kNameOffset + kPointerSize;
static const int kFlagsOffset = kDocOffset + kPointerSize;
static const int kSlotsOffset = kFlagsOffset + kPointerSize;
static const int kAbstractMethodsOffset = kSlotsOffset + kPointerSize;
static const int kSubclassesOffset = kAbstractMethodsOffset + kPointerSize;
static const int kProxyOffset = kSubclassesOffset + kPointerSize;
static const int kCtorOffset = kProxyOffset + kPointerSize;
static const int kQualnameOffset = kCtorOffset + kPointerSize;
static const int kSize = kQualnameOffset + kPointerSize;
static const int kBuiltinBaseMask = 0xff;
RAW_OBJECT_COMMON(Type);
};
class RawContext : public RawInstance {
public:
// Getters and setters
RawObject data() const;
void setData(RawObject data) const;
RawObject prevContext() const;
void setPrevContext(RawObject prev_context) const;
// Layout
static const int kDataOffset = RawHeapObject::kSize;
static const int kPrevContextOffset = kDataOffset + kPointerSize;
static const int kSize = kPrevContextOffset + kPointerSize;
RAW_OBJECT_COMMON(Context);
};
class RawContextVar : public RawInstance {
public:
// Getters and setters
RawObject defaultValue() const;
void setDefaultValue(RawObject default_value) const;
RawObject name() const;
void setName(RawObject name) const;
// Layout
static const int kDefaultValueOffset = RawHeapObject::kSize;
static const int kNameOffset = kDefaultValueOffset + kPointerSize;
static const int kSize = kNameOffset + kPointerSize;
RAW_OBJECT_COMMON(ContextVar);
};
class RawTypeProxy : public RawInstance {
public:
// The type is instance is a proxy to.
RawObject type() const;
void setType(RawObject type) const;
// Layout.
static const int kTypeOffset = RawHeapObject::kSize;
static const int kSize = kTypeOffset + kPointerSize;
RAW_OBJECT_COMMON(TypeProxy);
};
class RawDataArray : public RawHeapObject {
public:
byte byteAt(word index) const;
int32_t codePointAt(word char_index, word* char_length) const;
word codePointLength() const;
word offsetByCodePoints(word index, word count) const;
void copyTo(byte* dst, word length) const;
// Copy length bytes from this to dst, starting at the given index
void copyToStartAt(byte* dst, word length, word index) const;
word compare(RawDataArray that) const;
bool equals(RawDataArray that) const;
bool equalsBytes(View<byte> bytes) const;
bool equalsCStr(const char* c_str) const;
// Returns the index at which value is found in this[start:start+length] (not
// including end), or -1 if not found.
word findByte(byte value, word start, word length) const;
// Check for the presence of a non-zero byte.
bool includesByte(byte b) const;
bool isASCII() const;
word length() const;
// Conversion to an unescaped C string. The underlying memory is allocated
// with malloc and must be freed by the caller.
char* toCStr() const;
// Read adjacent bytes as `uint16_t` integer.
uint16_t uint16At(word index) const;
// Read adjacent bytes as `uint32_t` integer.
uint32_t uint32At(word index) const;
// Read adjacent bytes as `uint64_t` integer.
uint64_t uint64At(word index) const;
// Sizing. Sizing and initialization should only be done by the Runtime.
static word allocationSize(word length);
static RawObject initialize(uword address, word length, LayoutId layout_id);
RAW_OBJECT_COMMON(DataArray);
};
class RawLargeBytes : public RawDataArray {
public:
// Rewrite the header to make UTF-8 conformant bytes look like a Str
RawObject becomeStr() const;
RAW_OBJECT_COMMON(LargeBytes);
// Sizing. Sizing should only be done by the Runtime.
static word allocationSize(word length);
};
class RawLargeStr : public RawDataArray {
public:
bool includes(RawObject that) const;
word occurrencesOf(RawObject that) const;
// Sizing. Sizing should only be done by the Runtime.
static word allocationSize(word length);
RAW_OBJECT_COMMON(LargeStr);
};
class RawMutableBytes : public RawLargeBytes {
public:
void byteAtPut(word index, byte value) const;
void uint16AtPut(word index, uint16_t value) const;
void uint32AtPut(word index, uint32_t value) const;
// Find the first occurrence from a specified start of any byte in the given
// byte sequence, return the number of bytes read before the occurrence
word indexOfAny(View<byte> needle, word start) const;
// Replace the bytes from dst_start with count bytes from src
void replaceFromWith(word dst_start, RawDataArray src, word count) const;
// Replace the bytes from dst_start with count bytes from src, starting at
// src_start in src
void replaceFromWithStartAt(word dst_start, RawDataArray src, word count,
word src_start) const;
// Replace the bytes from dst_start with count bytes from src
void replaceFromWithBytes(word dst_start, RawBytes src, word count) const;
void replaceFromWithByteslike(word dst_start, const Byteslike& byteslike,
word count) const;
void replaceFromWithByteslikeStartAt(word dst_start,
const Byteslike& byteslike, word count,
word src_start) const;
// Replace the bytes from dst_start with count bytes of value
void replaceFromWithByte(word dst_start, byte value, word count) const;
// Replace the bytes from dst_start with count bytes from src, starting at
// src_start in src
void replaceFromWithBytesStartAt(word dst_start, RawBytes src, word count,
word src_start) const;
// Replace the bytes from dst_start with count bytes from src.
void replaceFromWithAll(word dst_start, View<byte> src) const;
// Replace the bytes from index with len bytes from string src
void replaceFromWithStr(word index, RawStr src, word char_length) const;
void replaceFromWithStrStartAt(word dst_start, RawStr src, word char_length,
word src_start_char) const;
RawObject becomeImmutable() const;
RawObject becomeStr() const;
// Sizing. Sizing should only be done by the Runtime.
static word allocationSize(word length);
RAW_OBJECT_COMMON(MutableBytes);
};
// A mutable array, for the array module
//
// RawLayout:
// [Header ]
// [Buffer ] - Pointer to a RawMutableBytes with the underlying data.
// [Length ] - Number of bytes currently in the array.
// [Typecode] - Typecode of the array
class RawArray : public RawInstance {
public:
// Getters and setters
RawObject buffer() const;
void setBuffer(RawObject new_buffer) const;
word length() const;
void setLength(word new_length) const;
RawObject typecode() const;
void setTypecode(RawObject new_typecode) const;
// Layout
static const int kBufferOffset = RawHeapObject::kSize;
static const int kLengthOffset = kBufferOffset + kPointerSize;
static const int kTypecodeOffset = kLengthOffset + kPointerSize;
static const int kSize = kTypecodeOffset + kPointerSize;
RAW_OBJECT_COMMON(Array);
};
// A container for an mmap'd pointer
//
// RawLayout:
// [Header ]
// [Access ] - A bitmask word storing the access permissions for the file
// [Data ] - A RawPointer holding the address + length of the memory
// [Fd ] - The file descriptor opened
class RawMmap : public RawInstance {
public:
enum Property {
kReadable = 0x01,
kWritable = 0x02,
kCopyOnWrite = 0x04,
};
// Getters and setters
word access() const;
void setAccess(word new_access) const;
RawObject data() const;
void setData(RawObject new_data) const;
RawObject fd() const;
void setFd(RawObject new_fd) const;
// Getters and setters for the kAccessOffset bitmask word
bool isReadable() const;
void setReadable() const;
bool isWritable() const;
void setWritable() const;
bool isCopyOnWrite() const;
void setCopyOnWrite() const;
// Layout
static const int kAccessOffset = RawHeapObject::kSize;
static const int kDataOffset = kAccessOffset + kPointerSize;
static const int kFdOffset = kDataOffset + kPointerSize;
static const int kSize = kFdOffset + kPointerSize;
RAW_OBJECT_COMMON(Mmap);
};
class RawTuple : public RawHeapObject {
public:
word length() const;
// Getters and setters.
RawObject at(word index) const;
void atPut(word index, RawObject value) const;
bool contains(RawObject object) const;
RAW_OBJECT_COMMON(Tuple);
};
class RawMutableTuple : public RawTuple {
public:
// Sizing. Sizing should only be done by the Runtime.
static word allocationSize(word length);
// Finalizes this object and turns it into an immutable Tuple.
RawObject becomeImmutable() const;
void fill(RawObject value) const;
// Copy count elements from src to this tuple, starting at index dst_start
void replaceFromWith(word dst_start, RawTuple src, word count) const;
// Copy count elements from src to this tuple, starting at index dst_start in
// this and src_start in src
void replaceFromWithStartAt(word dst_start, RawTuple src, word count,
word src_start) const;
// Swap elements at indices i, j
void swap(word i, word j) const;
// Initialization should only be done by the Runtime.
static RawObject initialize(uword address, word length);
RAW_OBJECT_COMMON(MutableTuple);
};
class RawUserTupleBase : public RawInstance {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
// RawLayout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UserTupleBase);
};
RawTuple tupleUnderlying(RawObject object);
// Arbitrary precision signed integer, with 64 bit digits in two's complement
// representation
class RawLargeInt : public RawHeapObject {
public:
// Getters and setters.
word asWord() const;
// Return whether or not this RawLargeInt obeys the following invariants:
// - numDigits() >= 1
// - The value does not fit in a RawSmallInt
// - Negative numbers do not have redundant sign-extended digits
// - Positive numbers do not have redundant zero-extended digits
bool isValid() const;
// RawLargeInt is also used for storing native pointers.
void* asCPtr() const;
// If this fits in T, get its value as a T. If not, indicate what went wrong.
template <typename T>
if_signed_t<T, OptInt<T>> asInt() const;
template <typename T>
if_unsigned_t<T, OptInt<T>> asInt() const;
// Indexing into digits
uword digitAt(word index) const;
void digitAtPut(word index, uword digit) const;
bool isEven() const;
bool isNegative() const;
bool isPositive() const;
word bitLength() const;
// Number of digits
word numDigits() const;
// Copies digits bytewise to `dst`. Returns number of bytes copied.
word copyTo(byte* dst, word copy_length) const;
// Copy 'bytes' array into digits; if the array is too small set remaining
// data to 'sign_extension' byte.
void copyFrom(RawBytes bytes, byte sign_extension) const;
// Layout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
// Sizing. Sizing and initialization should only be done by the Runtime.
static word allocationSize(word num_digits);
static RawObject initialize(uword address, word num_digits);
RAW_OBJECT_COMMON(LargeInt);
};
class RawFloat : public RawHeapObject {
public:
// Getters and setters.
double value() const;
// Layout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kDoubleSize;
// Instance initialization should only done by the Runtime.
static RawObject initialize(uword address, double value);
static word allocationSize();
RAW_OBJECT_COMMON(Float);
};
class RawFrameProxy : public RawInstance {
public:
// The previous frame on the stack, or None if the current frame object
// represents the bottom-most frame.
RawObject back() const;
void setBack(RawObject back) const;
// The function executed on the frame.
RawObject function() const;
void setFunction(RawObject function) const;
// The last instruction if called.
RawObject lasti() const;
void setLasti(RawObject lasti) const;
// The local symbol table, a dictionary.
RawObject locals() const;
void setLocals(RawObject locals) const;
// Layout.
static const int kBackOffset = RawHeapObject::kSize;
static const int kFunctionOffset = kBackOffset + kPointerSize;
static const int kLastiOffset = kFunctionOffset + kPointerSize;
static const int kLocalsOffset = kLastiOffset + kPointerSize;
static const int kSize = kLocalsOffset + kPointerSize;
RAW_OBJECT_COMMON(FrameProxy);
};
class RawUserBytesBase : public RawInstance {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
// RawLayout
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UserBytesBase);
};
RawBytes bytesUnderlying(RawObject object);
class RawUserFloatBase : public RawInstance {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
// RawLayout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UserFloatBase);
};
RawFloat floatUnderlying(RawObject object);
class RawUserIntBase : public RawInstance {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
// RawLayout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UserIntBase);
};
RawInt intUnderlying(RawObject object);
class RawUserStrBase : public RawInstance {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
// RawLayout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UserStrBase);
};
RawStr strUnderlying(RawObject object);
class RawComplex : public RawHeapObject {
public:
// Getters
double real() const;
double imag() const;
// Layout.
static const int kRealOffset = RawHeapObject::kSize;
static const int kImagOffset = kRealOffset + kDoubleSize;
static const int kSize = kImagOffset + kDoubleSize;
// Instance initialization should only done by the Runtime.
static RawObject initialize(uword address, double real, double imag);
static word allocationSize();
RAW_OBJECT_COMMON(Complex);
};
class RawUserComplexBase : public RawInstance {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
// RawLayout
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UserComplexBase);
};
RawComplex complexUnderlying(RawObject object);
class RawNativeProxy : public RawInstance {
public:
RawObject native() const;
void setNative(RawObject native_ptr) const;
RawObject dict() const;
void setDict(RawObject dict) const;
// A link to another object used by the garbage collector to create sets of
// weak references for delayed processing.
RawObject link() const;
void setLink(RawObject reference) const;
// TODO(eelizondo): Other finalizers will require the same logic. This should
// be moved to a more generic location
static void enqueue(RawObject reference, RawObject* tail);
static RawObject dequeue(RawObject* tail);
// Layout.NativeProxy appends its in-object attributes at the end of the given
// base object.
static const int kNativeOffsetFromEnd = -kPointerSize;
static const int kDictOffsetFromEnd = kNativeOffsetFromEnd - kPointerSize;
static const int kLinkOffsetFromEnd = kDictOffsetFromEnd - kPointerSize;
static const int kSizeFromEnd = -kLinkOffsetFromEnd;
RAW_OBJECT_COMMON_NO_CAST(NativeProxy);
private:
// Added here to prevent this field to be inherited from RawInstance.
static const int kSize = -1;
};
class RawPointer : public RawHeapObject {
public:
// Getters and setters
void* cptr() const;
void setCPtr(void* new_cptr) const;
word length() const;
void setLength(word new_length) const;
// Layout.
static const int kCPtrOffset = RawHeapObject::kSize;
static const int kLengthOffset = kCPtrOffset + kPointerSize;
static const int kSize = kLengthOffset + kPointerSize;
// Instance initialization should only done by the Runtime.
static RawObject initialize(uword address, void* cptr, word length);
static word allocationSize();
RAW_OBJECT_COMMON(Pointer);
};
class RawProperty : public RawInstance {
public:
// Getters and setters
RawObject getter() const;
void setGetter(RawObject function) const;
RawObject setter() const;
void setSetter(RawObject function) const;
RawObject deleter() const;
void setDeleter(RawObject function) const;
// Layout.
static const int kGetterOffset = RawHeapObject::kSize;
static const int kSetterOffset = kGetterOffset + kPointerSize;
static const int kDeleterOffset = kSetterOffset + kPointerSize;
static const int kDocOffset = kDeleterOffset + kPointerSize;
static const int kSize = kDocOffset + kPointerSize;
RAW_OBJECT_COMMON(Property);
};
class RawRange : public RawInstance {
public:
// Getters and setters.
RawObject start() const;
void setStart(RawObject value) const;
RawObject stop() const;
void setStop(RawObject value) const;
RawObject step() const;
void setStep(RawObject value) const;
// Layout.
static const int kStartOffset = RawHeapObject::kSize;
static const int kStopOffset = kStartOffset + kPointerSize;
static const int kStepOffset = kStopOffset + kPointerSize;
static const int kSize = kStepOffset + kPointerSize;
RAW_OBJECT_COMMON(Range);
};
class RawSlice : public RawInstance {
public:
// Getters.
RawObject start() const;
RawObject stop() const;
RawObject step() const;
// Calculate the number of items that a slice addresses
static word length(word start, word stop, word step);
// Adjusts the slice indices to fit a collection with the given length.
// Returns the length of the slice, and modifies start and stop to fit within
// the bounds of the collection.
//
// If start or stop is negative, adjust them relative to length. If they are
// still negative, sets them to zero. Limits start and stop to the length of
// the collection if they are greater than the length.
static word adjustIndices(word length, word* start, word* stop, word step);
// Adjusts the bounds for searching a collection of the given length.
//
// NOTE: While this function is mostly the same as adjustIndices(), it does
// not modify the start index when it is greater than the length.
static void adjustSearchIndices(word* start, word* end, word length);
// Layout.
static const int kStartOffset = RawHeapObject::kSize;
static const int kStopOffset = kStartOffset + kPointerSize;
static const int kStepOffset = kStopOffset + kPointerSize;
static const int kSize = kStepOffset + kPointerSize;
RAW_OBJECT_COMMON(Slice);
private:
// Setters.
void setStart(RawObject value) const;
void setStep(RawObject value) const;
void setStop(RawObject value) const;
friend class Runtime;
};
class RawSlotDescriptor : public RawInstance {
public:
// Setters and getters.
// Type that this descriptor is created for.
RawObject type() const;
void setType(RawObject type) const;
// Name of attribute that this descriptor wraps.
RawObject name() const;
void setName(RawObject name) const;
// Offset of the attribute this descriptor is for.
word offset() const;
void setOffset(word offset) const;
// Layout.
static const int kTypeOffset = RawHeapObject::kSize;
static const int kNameOffset = kTypeOffset + kPointerSize;
static const int kOffsetOffset = kNameOffset + kPointerSize;
static const int kSize = kOffsetOffset + kPointerSize;
RAW_OBJECT_COMMON(SlotDescriptor);
};
class RawStaticMethod : public RawInstance {
public:
// Getters and setters
RawObject function() const;
void setFunction(RawObject function) const;
// Layout.
static const int kFunctionOffset = RawHeapObject::kSize;
static const int kSize = kFunctionOffset + kPointerSize;
RAW_OBJECT_COMMON(StaticMethod);
};
class RawIteratorBase : public RawInstance {
public:
// Getters and setters.
word index() const;
void setIndex(word index) const;
RawObject iterable() const;
void setIterable(RawObject iterable) const;
// Layout.
static const int kIterableOffset = RawHeapObject::kSize;
static const int kIndexOffset = kIterableOffset + kPointerSize;
static const int kSize = kIndexOffset + kPointerSize;
};
class RawEnumerate : public RawInstance {
public:
RAW_OBJECT_COMMON(Enumerate);
static const int kIteratorOffset = RawHeapObject::kSize;
static const int kIndexOffset = kIteratorOffset + kPointerSize;
static const int kSize = kIndexOffset + kPointerSize;
};
class RawBytearrayIterator : public RawIteratorBase {
public:
RAW_OBJECT_COMMON(BytearrayIterator);
};
class RawBytesIterator : public RawIteratorBase {
public:
RAW_OBJECT_COMMON(BytesIterator);
};
class RawDequeIterator : public RawIteratorBase {
public:
// Getters and setters.
word state() const;
void setState(word state) const;
// Layout.
static const int kStateOffset = RawIteratorBase::kSize;
static const int kSize = kStateOffset + kPointerSize;
RAW_OBJECT_COMMON(DequeIterator);
};
class RawDequeReverseIterator : public RawIteratorBase {
public:
// Getters and setters.
word state() const;
void setState(word state) const;
// Layout.
static const int kStateOffset = RawIteratorBase::kSize;
static const int kSize = kStateOffset + kPointerSize;
RAW_OBJECT_COMMON(DequeReverseIterator);
};
class RawDictIteratorBase : public RawIteratorBase {
public:
// Getters and setters.
// This looks similar to index but is different and required in order to
// implement interators properly. We cannot use index in __length_hint__
// because index describes the position inside the internal buckets list of
// our implementation of dict -- not the logical number of iterms. Therefore
// we need an additional piece of state that refers to the logical number of
// items seen so far.
word numFound() const;
void setNumFound(word num_found) const;
// Layout
static const int kNumFoundOffset = RawIteratorBase::kSize;
static const int kSize = kNumFoundOffset + kPointerSize;
};
class RawDictItemIterator : public RawDictIteratorBase {
public:
RAW_OBJECT_COMMON(DictItemIterator);
};
class RawDictKeyIterator : public RawDictIteratorBase {
public:
RAW_OBJECT_COMMON(DictKeyIterator);
};
class RawDictValueIterator : public RawDictIteratorBase {
public:
RAW_OBJECT_COMMON(DictValueIterator);
};
class RawListIterator : public RawIteratorBase {
public:
RAW_OBJECT_COMMON(ListIterator);
};
class RawLongRangeIterator : public RawInstance {
public:
// Getters and setters.
RawObject next() const;
void setNext(RawObject next) const;
RawObject stop() const;
void setStop(RawObject stop) const;
RawObject step() const;
void setStep(RawObject step) const;
// Layout.
static const int kNextOffset = RawHeapObject::kSize;
static const int kStopOffset = kNextOffset + kPointerSize;
static const int kStepOffset = kStopOffset + kPointerSize;
static const int kSize = kStepOffset + kPointerSize;
RAW_OBJECT_COMMON(LongRangeIterator);
};
// RangeIterator guarantees that start, stop, step, and length are all SmallInt.
class RawRangeIterator : public RawInstance {
public:
// Getters and setters.
word next() const;
void setNext(word next) const;
word step() const;
void setStep(word step) const;
word length() const;
void setLength(word length) const;
// Layout.
static const int kNextOffset = RawHeapObject::kSize;
static const int kStepOffset = kNextOffset + kPointerSize;
static const int kLengthOffset = kStepOffset + kPointerSize;
static const int kSize = kLengthOffset + kPointerSize;
RAW_OBJECT_COMMON(RangeIterator);
};
class RawSeqIterator : public RawIteratorBase {
public:
RAW_OBJECT_COMMON(SeqIterator);
};
class RawSetIterator : public RawIteratorBase {
public:
// Getters and setters
word consumedCount() const;
void setConsumedCount(word consumed) const;
// Layout.
static const int kConsumedCountOffset = RawIteratorBase::kSize;
static const int kSize = kConsumedCountOffset + kPointerSize;
RAW_OBJECT_COMMON(SetIterator);
};
class RawStrIterator : public RawIteratorBase {
public:
RAW_OBJECT_COMMON(StrIterator);
};
class RawTupleIterator : public RawIteratorBase {
public:
// Getters and setters.
word length() const;
void setLength(word length) const;
// Layout.
static const int kLengthOffset = RawIteratorBase::kSize;
static const int kSize = kLengthOffset + kPointerSize;
RAW_OBJECT_COMMON(TupleIterator);
};
class RawCode : public RawInstance {
public:
// Matching CPython
enum Flags {
// Local variables are organized in an array and LOAD_FAST/STORE_FAST are
// used when this flag is set. Otherwise local variable accesses use
// LOAD_NAME/STORE_NAME to modify a dictionary ("implicit globals").
kOptimized = 0x0001,
// Local variables start in an uninitialized state. If this is not set then
// the variables are initialized with the values in the implicit globals.
kNewlocals = 0x0002,
kVarargs = 0x0004,
kVarkeyargs = 0x0008,
kNested = 0x0010,
kGenerator = 0x0020,
kNofree = 0x0040, // Shortcut for no free or cell vars
kCoroutine = 0x0080,
kIterableCoroutine = 0x0100,
kAsyncGenerator = 0x0200,
kFutureDivision = 0x20000,
kFutureAbsoluteImport = 0x40000,
kFutureWithStatement = 0x80000,
kFuturePrintFunction = 0x100000,
kFutureUnicodeLiterals = 0x200000,
kFutureBarryAsBdfl = 0x400000,
kFutureGeneratorStop = 0x800000,
kFutureAnnotations = 0x1000000,
kBuiltin = 0x2000000,
kMetadata = 0x4000000,
kLast = kMetadata,
};
// Getters and setters.
word argcount() const;
void setArgcount(word value) const;
word totalArgs() const;
// The number of positional only arguments.
word posonlyargcount() const;
void setPosonlyargcount(word value) const;
RawObject cell2arg() const;
void setCell2arg(RawObject value) const;
RawObject cellvars() const;
void setCellvars(RawObject value) const;
word numCellvars() const;
RawObject code() const;
void setCode(RawObject value) const;
RawObject consts() const;
void setConsts(RawObject value) const;
RawObject filename() const;
void setFilename(RawObject value) const;
word firstlineno() const;
void setFirstlineno(word value) const;
word flags() const;
void setFlags(word value) const;
RawObject freevars() const;
void setFreevars(RawObject value) const;
word numFreevars() const;
bool isAsyncGenerator() const;
bool isGeneratorLike() const;
bool hasFreevarsOrCellvars() const;
bool hasOptimizedAndNewlocals() const;
bool hasOptimizedOrNewlocals() const;
bool isNative() const;
word kwonlyargcount() const;
void setKwonlyargcount(word value) const;
RawObject lnotab() const;
void setLnotab(RawObject value) const;
RawObject name() const;
void setName(RawObject value) const;
RawObject names() const;
void setNames(RawObject value) const;
word nlocals() const;
void setNlocals(word value) const;
// Converts the offset in this code's bytecode into the corresponding line
// number in the backing source file.
word offsetToLineNum(word offset) const;
word stacksize() const;
void setStacksize(word value) const;
RawObject varnames() const;
void setVarnames(RawObject value) const;
// Returns nullptr if the function cannot be executed without a frame.
void* intrinsic() const;
void setIntrinsic(void* fp) const;
// Layout.
static const int kArgcountOffset = RawHeapObject::kSize;
static const int kPosonlyargcountOffset = kArgcountOffset + kPointerSize;
static const int kKwonlyargcountOffset =
kPosonlyargcountOffset + kPointerSize;
static const int kNlocalsOffset = kKwonlyargcountOffset + kPointerSize;
static const int kStacksizeOffset = kNlocalsOffset + kPointerSize;
static const int kFlagsOffset = kStacksizeOffset + kPointerSize;
static const int kFirstlinenoOffset = kFlagsOffset + kPointerSize;
static const int kCodeOffset = kFirstlinenoOffset + kPointerSize;
static const int kConstsOffset = kCodeOffset + kPointerSize;
static const int kNamesOffset = kConstsOffset + kPointerSize;
static const int kVarnamesOffset = kNamesOffset + kPointerSize;
static const int kFreevarsOffset = kVarnamesOffset + kPointerSize;
static const int kCellvarsOffset = kFreevarsOffset + kPointerSize;
static const int kCell2argOffset = kCellvarsOffset + kPointerSize;
static const int kFilenameOffset = kCell2argOffset + kPointerSize;
static const int kNameOffset = kFilenameOffset + kPointerSize;
static const int kLnotabOffset = kNameOffset + kPointerSize;
static const int kIntrinsicOffset = kLnotabOffset + kPointerSize;
static const int kSize = kIntrinsicOffset + kPointerSize;
static const word kCompileFlagsMask =
Flags::kFutureDivision | Flags::kFutureAbsoluteImport |
Flags::kFutureWithStatement | Flags::kFuturePrintFunction |
Flags::kFutureUnicodeLiterals | Flags::kFutureBarryAsBdfl |
Flags::kFutureGeneratorStop | Flags::kFutureAnnotations;
RAW_OBJECT_COMMON(Code);
};
// A function object.
//
// This may contain a user-defined function or a built-in function.
//
// RawFunction objects have a set of pre-defined attributes, only some of which
// are writable outside of the runtime. The full set is defined at
//
// https://docs.python.org/3/reference/datamodel.html
class RawFunction : public RawInstance {
public:
// An entry point into a function.
//
// The entry point is called with the current thread, the caller's stack
// frame, and the number of arguments that have been pushed onto the stack.
using Entry = RawObject (*)(Thread*, word);
enum Flags {
kNone = 0,
// Matching Code::Flags (and CPython)
kOptimized = RawCode::Flags::kOptimized,
kNewlocals = RawCode::Flags::kNewlocals,
kVarargs = RawCode::Flags::kVarargs,
kVarkeyargs = RawCode::Flags::kVarkeyargs,
kNested = RawCode::Flags::kNested,
kGenerator = RawCode::Flags::kGenerator,
kNofree = RawCode::Flags::kNofree,
kCoroutine = RawCode::Flags::kCoroutine,
kIterableCoroutine = RawCode::Flags::kIterableCoroutine,
kAsyncGenerator = RawCode::Flags::kAsyncGenerator,
kSimpleCall = RawCode::Flags::kLast << 1, // Speeds detection of fast call
kInterpreted = RawCode::Flags::kLast << 2, // Executable by the interpreter
kExtension = RawCode::Flags::kLast << 3, // C-API extension function
kCompiled = RawCode::Flags::kLast << 4, // JIT-compiled
kLast = kCompiled,
};
// Getters and setters.
// A dict containing parameter annotations
RawObject annotations() const;
void setAnnotations(RawObject annotations) const;
// The number of positional arguments.
word argcount() const;
void setArgcount(word value) const;
// The code object backing this function or None
RawObject code() const;
void setCode(RawObject code) const;
// A tuple of cell objects that contain bindings for the function's free
// variables. Read-only to user code.
RawObject closure() const;
void setClosure(RawObject closure) const;
// A tuple containing default values for arguments with defaults. Read-only
// to user code.
RawObject defaults() const;
void setDefaults(RawObject defaults) const;
bool hasDefaults() const;
// The function's docstring
RawObject doc() const;
void setDoc(RawObject doc) const;
// Returns the entry to be used when the function is invoked via
// CALL_FUNCTION
Entry entry() const;
void setEntry(Entry thunk) const;
// Returns the entry to be used when the function is invoked via
// CALL_FUNCTION_KW
Entry entryKw() const;
void setEntryKw(Entry thunk) const;
// Returns the entry to be used when the function is invoked via
// CALL_FUNCTION_EX
Entry entryEx() const;
void setEntryEx(Entry thunk) const;
// Returns the entry to be used when the function is invoked in assembly.
void* entryAsm() const;
void setEntryAsm(void* thunk) const;
// Returns the function flags.
word flags() const;
void setFlags(word flags) const;
// Returns true if the function is an async generator.
bool isAsyncGenerator() const;
// Returns true if the function is a coroutine.
bool isCoroutine() const;
// Returns true if function has `kExtension` flag set.
bool isExtension() const;
// Returns true if function has `kCompiled` flag set.
bool isCompiled() const;
// Returns true if the function is a coroutine, a generator, or an async
// generator.
bool isGeneratorLike() const;
// Returns true if the function has free variables or cell variables.
bool hasFreevarsOrCellvars() const;
// Returns true if the function is a generator.
bool isGenerator() const;
// Returns true if the function is an iterable coroutine.
bool isIterableCoroutine() const;
// Returns true if the function has the optimized or newlocals flag.
bool hasOptimizedOrNewlocals() const;
// Returns true if the function has a simple calling convention.
bool hasSimpleCall() const;
// Returns true if the function has varargs.
bool hasVarargs() const;
// Returns true if the function has varargs or varkeyword arguments.
bool hasVarargsOrVarkeyargs() const;
// Returns true if the function has varkeyword arguments.
bool hasVarkeyargs() const;
// Returns true if the function consists of bytecode that can be executed
// normally by the interpreter.
bool isInterpreted() const;
void setIsInterpreted(bool interpreted) const;
// Returns nullptr if the function cannot be executed without a frame.
void* intrinsic() const;
void setIntrinsic(void* fp) const;
// A dict containing defaults for keyword-only parameters
RawObject kwDefaults() const;
void setKwDefaults(RawObject kw_defaults) const;
// The name of the module the function was defined in
RawObject moduleName() const;
void setModuleName(RawObject module_name) const;
// The module where this function was defined
RawObject moduleObject() const;
void setModuleObject(RawObject module) const;
// The function's name
RawObject name() const;
void setName(RawObject name) const;
// The function's qualname
RawObject qualname() const;
void setQualname(RawObject qualname) const;
// Maximum stack size used by the bytecode.
RawObject stacksizeOrBuiltin() const;
void setStacksizeOrBuiltin(RawObject stacksize_or_builtin) const;
// Returns the number of parameters. This includes `code.argcount()`,
// `code.kwonlyargcount()`, and an extra parameter for varargs and for
// varkeyargs argument when necessary.
word totalArgs() const;
void setTotalArgs(word value) const;
// Returns number of variables. This is the number of locals that are not
// parameters plus the number of cell variables and free variables.
word totalVars() const;
void setTotalVars(word value) const;
// Returns the number of locals. This is equivalent to
// `code().nlocals() + code().numFreevars() + code().numCellvars()`.
word totalLocals() const;
// Bytecode rewritten to a variant that uses inline caching.
RawObject rewrittenBytecode() const;
void setRewrittenBytecode(RawObject rewritten_bytecode) const;
// Tuple with values of the inline caches. See `ic.h`.
RawObject caches() const;
void setCaches(RawObject cache) const;
// The function's dictionary
RawObject dict() const;
void setDict(RawObject dict) const;
// Layout.
static const int kCodeOffset = RawHeapObject::kSize;
static const int kFlagsOffset = kCodeOffset + kPointerSize;
static const int kArgcountOffset = kFlagsOffset + kPointerSize;
static const int kTotalArgsOffset = kArgcountOffset + kPointerSize;
static const int kTotalVarsOffset = kTotalArgsOffset + kPointerSize;
static const int kStacksizeOrBuiltinOffset = kTotalVarsOffset + kPointerSize;
static const int kDocOffset = kStacksizeOrBuiltinOffset + kPointerSize;
static const int kNameOffset = kDocOffset + kPointerSize;
static const int kQualnameOffset = kNameOffset + kPointerSize;
static const int kModuleNameOffset = kQualnameOffset + kPointerSize;
static const int kModuleObjectOffset = kModuleNameOffset + kPointerSize;
static const int kDefaultsOffset = kModuleObjectOffset + kPointerSize;
static const int kAnnotationsOffset = kDefaultsOffset + kPointerSize;
static const int kKwDefaultsOffset = kAnnotationsOffset + kPointerSize;
static const int kClosureOffset = kKwDefaultsOffset + kPointerSize;
static const int kEntryOffset = kClosureOffset + kPointerSize;
static const int kEntryKwOffset = kEntryOffset + kPointerSize;
static const int kEntryExOffset = kEntryKwOffset + kPointerSize;
static const int kEntryAsmOffset = kEntryExOffset + kPointerSize;
static const int kRewrittenBytecodeOffset = kEntryAsmOffset + kPointerSize;
static const int kCachesOffset = kRewrittenBytecodeOffset + kPointerSize;
static const int kDictOffset = kCachesOffset + kPointerSize;
static const int kIntrinsicOffset = kDictOffset + kPointerSize;
static const int kSize = kIntrinsicOffset + kPointerSize;
RAW_OBJECT_COMMON(Function);
};
class RawMappingProxy : public RawInstance {
public:
// Setters and getters.
RawObject mapping() const;
void setMapping(RawObject mapping) const;
// Layout.
static const int kMappingOffset = RawHeapObject::kSize;
static const int kSize = kMappingOffset + kPointerSize;
RAW_OBJECT_COMMON(MappingProxy);
};
// Descriptor for a block of memory.
// Contrary to cpython, this is a reference to a `bytes` object which may be
// moved around by the garbage collector.
class RawMemoryView : public RawInstance {
public:
// Setters and getters.
RawObject buffer() const;
void setBuffer(RawObject buffer) const;
RawObject format() const;
void setFormat(RawObject format) const;
// Length in bytes.
word length() const;
void setLength(word length) const;
// Original object that memoryview was created with
RawObject object() const;
void setObject(RawObject object) const;
// An integer indicating how many dimensions of a multi-dimensional array the
// memory represents.
RawObject ndim() const;
void setNdim(RawObject ndim) const;
// Tuple of integers giving the shape of the memory as an N-dimensional array
// In the 1-D case, shape will have one value which is equal to the length
RawObject shape() const;
void setShape(RawObject shape) const;
// Private variable used to store the starting index of a memoryview.
// Default value is 0
word start() const;
void setStart(word start) const;
// Tuple of integers used to keep track of the number of bytes to step in each
// dimension when traversing a memoryview buffer. In the 1-D case, strides
// will will have one value which is equal to the step
// Default value is (1,)
RawObject strides() const;
void setStrides(RawObject strides) const;
bool readOnly() const;
void setReadOnly(bool read_only) const;
// Layout.
static const int kBufferOffset = RawHeapObject::kSize;
static const int kFormatOffset = kBufferOffset + kPointerSize;
static const int kLengthOffset = kFormatOffset + kPointerSize;
static const int kReadOnlyOffset = kLengthOffset + kPointerSize;
static const int kObjectOffset = kReadOnlyOffset + kPointerSize;
static const int kShapeOffset = kObjectOffset + kPointerSize;
static const int kStartOffset = kShapeOffset + kPointerSize;
static const int kStridesOffset = kStartOffset + kPointerSize;
static const int kNdimOffset = kStridesOffset + kPointerSize;
static const int kSize = kNdimOffset + kPointerSize;
RAW_OBJECT_COMMON(MemoryView);
};
class RawModule : public RawAttributeDict {
public:
// Setters and getters.
RawObject name() const;
void setName(RawObject name) const;
// Contains the numeric address of mode definition object for C-API modules or
// zero if the module was not defined through the C-API.
RawObject def() const;
bool hasDef() const;
void setDef(RawObject def) const;
// Contains the numeric address of module state object for C-API modules or
// zero if the module was not defined through the C-API.
RawObject state() const;
bool hasState() const;
void setState(RawObject state) const;
// Lazily allocated ModuleProxy instance that behaves like dict.
RawObject moduleProxy() const;
void setModuleProxy(RawObject module_proxy) const;
// Unique ID allocated at module creation time.
word id() const;
void setId(word id) const;
// Layout.
static const int kNameOffset = RawAttributeDict::kSize;
static const int kDefOffset = kNameOffset + kPointerSize;
static const int kStateOffset = kDefOffset + kPointerSize;
static const int kModuleProxyOffset = kStateOffset + kPointerSize;
static const int kSize = kModuleProxyOffset + kPointerSize;
// Constants.
static const word kMaxModuleId = RawHeader::kHashCodeMask;
RAW_OBJECT_COMMON(Module);
};
class RawModuleProxy : public RawInstance {
public:
// Module that this ModuleProxy is created for.
// moduleproxy.module().moduleproxy() == moduleproxy holds.
RawObject module() const;
void setModule(RawObject module) const;
// Layout.
static const int kModuleOffset = RawHeapObject::kSize;
static const int kSize = kModuleOffset + kPointerSize;
RAW_OBJECT_COMMON(ModuleProxy);
};
// A mutable array of bytes.
//
// Invariant: All allocated bytes past the end of the array are 0.
// Invariant: items() is a MutableBytes.
//
// RawLayout:
// [Header ]
// [Items ] - Pointer to a RawMutableBytes with the underlying data.
// [NumItems] - Number of bytes currently in the array.
class RawBytearray : public RawInstance {
public:
// Getters and setters
byte byteAt(word index) const;
void byteAtPut(word index, byte value) const;
void copyTo(byte* dst, word length) const;
RawObject items() const;
void setItems(RawObject new_items) const;
word numItems() const;
void setNumItems(word num_bytes) const;
void downsize(word new_length) const;
// The size of the underlying bytes
word capacity() const;
// Compares the bytes in this to the bytes in that. Returns a negative value
// if this is less than that, positive if this is greater than that, and zero
// if they have the same bytes. Does not guarantee to return -1, 0, or 1.
word compare(RawBytes that, word that_len);
// Replace the bytes from dst_start with count bytes from src
void replaceFromWith(word dst_start, RawBytearray src, word count) const;
// Replace the bytes from dst_start with count bytes from src, starting at
// src_start in src
void replaceFromWithStartAt(word dst_start, RawBytearray src, word count,
word src_start) const;
// Layout
static const int kItemsOffset = RawHeapObject::kSize;
static const int kNumItemsOffset = kItemsOffset + kPointerSize;
static const int kSize = kNumItemsOffset + kPointerSize;
RAW_OBJECT_COMMON(Bytearray);
};
// A mutable Unicode array, for internal string building.
//
// Invariant: The allocated code units form valid UTF-8.
//
// RawLayout:
// [Header ]
// [Items ] - Pointer to a RawMutableBytes with the underlying data.
// [NumItems] - Number of bytes currently in the array.
class RawStrArray : public RawInstance {
public:
// Getters and setters
RawObject items() const;
void setItems(RawObject new_items) const;
word numItems() const;
void setNumItems(word num_items) const;
void copyTo(byte* dst, word length) const;
int32_t codePointAt(word index, word* length) const;
// Returns an index into a string offset by either a positive or negative
// number of code points. Otherwise, if the new index would be negative, -1
// is returned or if the new index would be greater than the length of the
// string, the length is returned.
word offsetByCodePoints(word char_index, word count) const;
// Rotate the code point from `last` to `first`.
void rotateCodePoint(word first, word last) const;
// The size of the underlying string in bytes.
word capacity() const;
// Layout
static const int kItemsOffset = RawHeapObject::kSize;
static const int kNumItemsOffset = kItemsOffset + kPointerSize;
static const int kSize = kNumItemsOffset + kPointerSize;
RAW_OBJECT_COMMON(StrArray);
};
// A double-ended queue
//
// RawLayout:
// [Header ]
// [Items ] - data
// [Left ] - head element
// [NumItems] - number of elements
// [Maxlen ] - maximum capacity
class RawDeque : public RawInstance {
public:
RawObject at(word index) const;
void atPut(word index, RawObject value) const;
// Returns the total number of elements that may be held without growing
// the underlying MutableTuple
word capacity() const;
void clear() const;
// Getters and Setters
RawObject items() const;
void setItems(RawObject new_items) const;
word left() const;
void setLeft(word left) const;
word numItems() const;
void setNumItems(word num_items) const;
RawObject maxlen() const;
void setMaxlen(RawObject maxlen) const;
word state() const;
void setState(word state) const;
// Layout.
static const int kItemsOffset = RawHeapObject::kSize;
static const int kLeftOffset = kItemsOffset + kPointerSize;
static const int kNumItemsOffset = kLeftOffset + kPointerSize;
static const int kMaxlenOffset = kNumItemsOffset + kPointerSize;
static const int kStateOffset = kMaxlenOffset + kPointerSize;
static const int kSize = kStateOffset + kPointerSize;
RAW_OBJECT_COMMON(Deque);
};
// A simple dict that uses open addressing and linear probing.
//
// RawLayout:
//
// [Header ]
// [NumItems] - Number of items currently in the dict
// [Data ] - RawTuple that stores the underlying data.
// [Indices ] - RawTuple storing indices into the data tuple.
// [FirstEmptyItemIndex] - Index pointing to the first empty item in data.
//
class RawDict : public RawInstance {
public:
// Number of items currently in the dict
word numItems() const;
void setNumItems(word num_items) const;
// Getters and setters.
// RawTuple that stores the underlying data.
RawObject data() const;
void setData(RawObject data) const;
// RawTuple storing indices into the data tuple.
RawObject indices() const;
void setIndices(RawObject index_data) const;
// Index pointing to the first empty item in data.
word firstEmptyItemIndex() const;
void setFirstEmptyItemIndex(word first_empty_item_index) const;
// Number of indices.
word numIndices() const;
// Layout.
static const int kNumItemsOffset = RawHeapObject::kSize;
static const int kDataOffset = kNumItemsOffset + kPointerSize;
static const int kIndicesOffset = kDataOffset + kPointerSize;
static const int kFirstEmptyItemIndexOffset = kIndicesOffset + kPointerSize;
static const int kSize = kFirstEmptyItemIndexOffset + kPointerSize;
RAW_OBJECT_COMMON(Dict);
};
class RawDictViewBase : public RawInstance {
public:
// Getters and setters
RawObject dict() const;
void setDict(RawObject dict) const;
// Layout
static const int kDictOffset = RawHeapObject::kSize;
static const int kSize = kDictOffset + kPointerSize;
};
class RawDictItems : public RawDictViewBase {
public:
RAW_OBJECT_COMMON(DictItems);
};
class RawDictKeys : public RawDictViewBase {
public:
RAW_OBJECT_COMMON(DictKeys);
};
class RawDictValues : public RawDictViewBase {
public:
RAW_OBJECT_COMMON(DictValues);
};
// A simple set implementation. Used by set and frozenset.
class RawSetBase : public RawInstance {
public:
// Getters and setters.
// The RawTuple backing the set
RawObject data() const;
void setData(RawObject data) const;
// Number of items currently in the set
word numItems() const;
void setNumItems(word num_items) const;
// Number of active and tombstone items in the set
word numFilled() const;
void setNumFilled(word num_filled) const;
// Layout.
static const int kDataOffset = RawHeapObject::kSize;
static const int kNumItemsOffset = kDataOffset + kPointerSize;
static const int kNumFilledOffset = kNumItemsOffset + kPointerSize;
static const int kSize = kNumFilledOffset + kPointerSize;
RAW_OBJECT_COMMON(SetBase);
};
class RawSet : public RawSetBase {
public:
RAW_OBJECT_COMMON(Set);
};
class RawFrozenSet : public RawSetBase {
public:
RAW_OBJECT_COMMON(FrozenSet);
};
// A growable array
//
// RawLayout:
//
// [Header ]
// [Items ] - Pointer to an RawTuple that contains list elements
// [NumItems] - Number of elements currently in the list
class RawList : public RawInstance {
public:
// Getters and setters.
RawObject at(word index) const;
void atPut(word index, RawObject value) const;
RawObject items() const;
void setItems(RawObject new_items) const;
word numItems() const;
void setNumItems(word num_items) const;
void clearFrom(word idx) const;
// Return the total number of elements that may be held without growing the
// list
word capacity() const;
// Copy count elements from src to this list, starting at index start
void replaceFromWith(word start, RawList src, word count) const;
// Copy count elements from src to this list, starting at index start in the
// destination and index src_start in the source
void replaceFromWithStartAt(word start, RawList src, word count,
word src_start) const;
// Swap elements at indices i, j
void swap(word i, word j) const;
// Layout.
static const int kItemsOffset = RawHeapObject::kSize;
static const int kNumItemsOffset = kItemsOffset + kPointerSize;
static const int kSize = kNumItemsOffset + kPointerSize;
RAW_OBJECT_COMMON(List);
};
class RawValueCell : public RawInstance {
public:
// Getters and setters
RawObject value() const;
void setValue(RawObject object) const;
RawObject dependencyLink() const;
void setDependencyLink(RawObject object) const;
bool isPlaceholder() const;
void makePlaceholder() const;
// Layout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kDependencyLinkOffset = kValueOffset + kPointerSize;
static const int kSize = kDependencyLinkOffset + kPointerSize;
RAW_OBJECT_COMMON(ValueCell);
};
class RawEllipsis : public RawHeapObject {
public:
static word allocationSize();
// Initialization should only be done by the Runtime.
static RawObject initialize(uword address);
RAW_OBJECT_COMMON(Ellipsis);
};
class RawToken : public RawInstance {
public:
// Getters and setters
RawObject context() const;
void setContext(RawObject context) const;
RawObject oldValue() const;
void setOldValue(RawObject old_value) const;
bool used() const;
void setUsed(bool used) const;
RawObject var() const;
void setVar(RawObject var) const;
// Layout
static const int kContextOffset = RawHeapObject::kSize;
static const int kOldValueOffset = kContextOffset + kPointerSize;
static const int kUsedOffset = kOldValueOffset + kPointerSize;
static const int kVarOffset = kUsedOffset + kPointerSize;
static const int kSize = kVarOffset + kPointerSize;
RAW_OBJECT_COMMON(Token);
};
class RawWeakRef : public RawInstance {
public:
// Getters and setters
// The object weakly-referenced by this instance. Set to None by the garbage
// collector when the referent is being collected.
RawObject referent() const;
void setReferent(RawObject referent) const;
// A callable object invoked with the weakref object as an argument when the
// referent is deemed to be "near death" and only reachable through a weak
// reference.
RawObject callback() const;
void setCallback(RawObject callable) const;
// A link to another object used by the garbage collector to create sets of
// weak references for delayed processing.
RawObject link() const;
void setLink(RawObject reference) const;
// The referent's hash
RawObject hash() const;
void setHash(RawObject hash) const;
static void enqueue(RawObject reference, RawObject* tail);
static RawObject dequeue(RawObject* tail);
static RawObject spliceQueue(RawObject tail1, RawObject tail2);
// Layout.
static const int kReferentOffset = RawHeapObject::kSize;
static const int kCallbackOffset = kReferentOffset + kPointerSize;
static const int kLinkOffset = kCallbackOffset + kPointerSize;
static const int kHashOffset = kLinkOffset + kPointerSize;
static const int kSize = kHashOffset + kPointerSize;
RAW_OBJECT_COMMON(WeakRef);
};
class RawUserWeakRefBase : public RawInstance {
public:
// Getters and setters.
RawObject value() const;
void setValue(RawObject value) const;
// RawLayout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UserWeakRefBase);
};
RawWeakRef weakRefUnderlying(RawObject object);
class RawWeakProxy : public RawInstance {
public:
// Getters and setters
// The object weakly-referenced by this instance. Set to None by the garbage
// collector when the referent is being collected.
RawObject referent() const;
void setReferent(RawObject referent) const;
// Layout.
static const int kReferentOffset = RawHeapObject::kSize;
static const int kSize = kReferentOffset + kPointerSize;
RAW_OBJECT_COMMON(WeakProxy);
};
class RawWeakCallableProxy : public RawInstance {
public:
// Getters and setters
// The object weakly-referenced by this instance. Set to None by the garbage
// collector when the referent is being collected.
RawObject referent() const;
void setReferent(RawObject referent) const;
// Layout.
static const int kReferentOffset = RawHeapObject::kSize;
static const int kSize = kReferentOffset + kPointerSize;
RAW_OBJECT_COMMON(WeakCallableProxy);
};
// RawWeakLink objects are used to form double linked lists where the elements
// can still be garbage collected.
//
// A main usage of this is to maintain a list of function objects
// to be notified of global variable cache invalidation.
class RawWeakLink : public RawWeakRef {
public:
// Getters and setters.
RawObject next() const;
void setNext(RawObject object) const;
RawObject prev() const;
void setPrev(RawObject object) const;
// Layout.
static const int kNextOffset = RawWeakRef::kSize;
static const int kPrevOffset = kNextOffset + kPointerSize;
static const int kSize = kPrevOffset + kPointerSize;
RAW_OBJECT_COMMON(WeakLink);
};
// A RawBoundMethod binds a RawFunction and its first argument (called `self`).
//
// These are typically created as a temporary object during a method call,
// though they may be created and passed around freely.
//
// Consider the following snippet of python code:
//
// class Foo:
// def bar(self):
// return self
// f = Foo()
// f.bar()
//
// The Python 3.6 bytecode produced for the line `f.bar()` is:
//
// LOAD_FAST 0 (f)
// LOAD_ATTR 1 (bar)
// CALL_FUNCTION 0
//
// The LOAD_ATTR for `f.bar` creates a `RawBoundMethod`, which is then called
// directly by the subsequent CALL_FUNCTION opcode.
class RawBoundMethod : public RawInstance {
public:
// Getters and setters
// The function to which "self" is bound
RawObject function() const;
void setFunction(RawObject function) const;
// The instance of "self" being bound
RawObject self() const;
void setSelf(RawObject self) const;
// Layout.
static const int kFunctionOffset = RawHeapObject::kSize;
static const int kSelfOffset = kFunctionOffset + kPointerSize;
static const int kSize = kSelfOffset + kPointerSize;
RAW_OBJECT_COMMON(BoundMethod);
};
class RawCell : public RawInstance {
public:
// Getters and setters
RawObject value() const;
void setValue(RawObject value) const;
// Layout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON(Cell);
};
class RawClassMethod : public RawInstance {
public:
// Getters and setters
RawObject function() const;
void setFunction(RawObject function) const;
// Layout.
static const int kFunctionOffset = RawHeapObject::kSize;
static const int kSize = kFunctionOffset + kPointerSize;
RAW_OBJECT_COMMON(ClassMethod);
};
// A RawLayout describes the in-memory shape of an instance.
//
// RawInstance attributes are split into two classes: in-object attributes,
// which exist directly in the instance, and overflow attributes, which are
// stored in an object array pointed to by the last word of the instance.
// Graphically, this looks like:
//
// RawInstance RawTuple
// +---------------------------+ +------->+--------------------------+
// | First in-object attribute | | | First overflow attribute |
// +---------------------------+ | +--------------------------+
// | ... | | | ... |
// +---------------------------+ | +--------------------------+
// | Last in-object attribute | | | Last overflow attribute |
// +---------------------------+ | +--------------------------+
// | Overflow Attributes +-----+
// +---------------------------+
//
// Each instance is associated with a layout (whose id is stored in the header
// word). The layout acts as a roadmap for the instance; it describes where to
// find each attribute.
//
// In general, instances of the same class will have the same shape. Idiomatic
// Python typically initializes attributes in the same order for instances of
// the same class. Ideally, we would be able to share the same concrete
// RawLayout between two instances of the same shape. This both reduces memory
// overhead and enables effective caching of attribute location.
//
// To achieve structural sharing, layouts form an immutable DAG. Every class
// has a root layout that contains only in-object attributes. When an instance
// is created, it is assigned the root layout of its class. When a shape
// altering mutation to the instance occurs (e.g. adding an attribute), the
// current layout is searched for a corresponding edge. If such an edge exists,
// it is followed and the instance is assigned the resulting layout. If there
// is no such edge, a new layout is created, an edge is inserted between
// the two layouts, and the instance is assigned the new layout.
class RawLayout : public RawInstance {
public:
// Getters and setters.
LayoutId id() const;
void setId(LayoutId id) const;
// Returns the class whose instances are described by this layout
RawObject describedType() const;
void setDescribedType(RawObject type) const;
// Set the number of in-object attributes that may be stored on an instance
// described by this layout.
//
// N.B. - This will always be larger than or equal to the length of the
// RawTuple returned by inObjectAttributes().
void setNumInObjectAttributes(word count) const;
word numInObjectAttributes() const;
// Returns an RawTuple describing the attributes stored directly in
// in the instance.
//
// Each item in the object array is a two element tuple. Each tuple is
// composed of the following elements, in order:
//
// 1. The attribute name (RawStr, or NoneType if unnamed (name is kInvalid))
// 2. The attribute info (AttributeInfo)
RawObject inObjectAttributes() const;
void setInObjectAttributes(RawObject attributes) const;
// Returns an RawTuple describing the attributes stored in the overflow
// array of the instance.
//
// Each item in the object array is a two element tuple. Each tuple is
// composed of the following elements, in order:
//
// 1. The attribute name (RawStr)
// 2. The attribute info (AttributeInfo)
RawObject overflowAttributes() const;
void setOverflowAttributes(RawObject attributes) const;
void setDictOverflowOffset(word offset) const;
word dictOverflowOffset() const;
// Returns a flattened list of tuples. Each tuple is composed of the
// following elements, in order:
//
// 1. The attribute name (RawStr)
// 2. The layout that would result if an attribute with that name
// was added.
RawObject additions() const;
void setAdditions(RawObject additions) const;
// Returns a flattened list of tuples. Each tuple is composed of the
// following elements, in order:
//
// 1. The attribute name (RawStr)
// 2. The layout that would result if an attribute with that name
// was deleted.
RawObject deletions() const;
void setDeletions(RawObject deletions) const;
// Returns the number of bytes in an instance described by this layout,
// including the overflow array. Computed from the number of in-object
// attributes and possible overflow slot.
word instanceSize() const;
// Return the offset, in bytes, of the overflow slot
word overflowOffset() const;
// Seal the attributes of the layout.
void seal() const;
// Returns true if the layout has sealed attributes.
bool isSealed() const;
// Returns true if the layout is for a NativeProxy type.
bool isNativeProxyLayout() const;
// Returns true if the layout stores its overflow attributes in a dictionary.
bool hasDictOverflow() const;
// Returns true if the layout stores its overflow attributes in a tuple.
bool hasTupleOverflow() const;
// Layout.
static const int kDescribedTypeOffset = RawHeapObject::kSize;
static const int kInObjectAttributesOffset =
kDescribedTypeOffset + kPointerSize;
static const int kOverflowAttributesOffset =
kInObjectAttributesOffset + kPointerSize;
static const int kAdditionsOffset = kOverflowAttributesOffset + kPointerSize;
static const int kDeletionsOffset = kAdditionsOffset + kPointerSize;
static const int kNumInObjectAttributesOffset =
kDeletionsOffset + kPointerSize;
static const int kSize = kNumInObjectAttributesOffset + kPointerSize;
RAW_OBJECT_COMMON(Layout);
};
class RawSuper : public RawInstance {
public:
// getters and setters
RawObject type() const;
void setType(RawObject type) const;
RawObject object() const;
void setObject(RawObject obj) const;
RawObject objectType() const;
void setObjectType(RawObject type) const;
// Layout.
static const int kTypeOffset = RawHeapObject::kSize;
static const int kObjectOffset = kTypeOffset + kPointerSize;
static const int kObjectTypeOffset = kObjectOffset + kPointerSize;
static const int kSize = kObjectTypeOffset + kPointerSize;
RAW_OBJECT_COMMON(Super);
};
// TODO(T63568836): Replace GeneratorFrame by moving it variable
// length data into a MutableTuple and moving any other attributes
// into Generator.
// A Frame in a HeapObject, with space allocated before and after for stack and
// locals, respectively. It looks almost exactly like the ascii art diagram for
// Frame (from frame.h), except that there is a fixed amount of space allocated
// for the value stack, which comes from stacksize() on the Code object this is
// created from:
//
// +----------------------+ <--+
// | Arg 0 | |
// | ... | |
// | Arg N | |
// | Local 0 | | (totalArgs() + totalVars()) * kPointerSize
// | ... | |
// | Local N | |
// +----------------------+ <--+
// | | |
// | Frame | | Frame::kSize
// | | |
// +----------------------+ <--+ <-- frame()
// | | |
// | Value stack | | maxStackSize() * kPointerSize
// | | |
// +----------------------+ <--+
// | maxStackSize |
// +----------------------+
class RawGeneratorFrame : public RawInstance {
public:
// The size of the embedded frame + stack and locals, in words.
word numFrameWords() const;
// Get or set the number of words allocated for the value stack. Used to
// derive a pointer to the Frame inside this GeneratorFrame.
word maxStackSize() const;
void setMaxStackSize(word offset) const;
// Returns the function of a heap frame.
// Note that using `frame()->function()` does not work for this!
RawObject function() const;
// Accessors to the contained frame.
RawObject popValue() const;
void setVirtualPC(word value) const;
RawObject* valueStackTop() const;
word virtualPC() const;
word stackSize() const;
void setStackSize(word size) const;
// Sizing.
static word numAttributes(word extra_words);
// Layout.
static const int kMaxStackSizeOffset = RawHeapObject::kSize;
static const int kFrameOffset = kMaxStackSizeOffset + kPointerSize;
// Size and offsets within frame. Keep in sync with `Frame` class!
static const int kFrameSize = 26 * kPointerSize;
static const int kStackSizeFrameOffset = 2 * kPointerSize;
// Number of words that aren't the Frame.
static const int kNumOverheadWords = kFrameOffset / kPointerSize;
RAW_OBJECT_COMMON(GeneratorFrame);
private:
// The Frame contained in this GeneratorFrame.
Frame* frame() const;
};
// The exception currently being handled. Every Generator and Coroutine has its
// own exception state that is installed while it's running, to allow yielding
// from an except block without losing track of the caught exception.
//
// TODO(T38009294): This class won't exist forever. Think very hard about
// adding any more bits of state to it.
class RawExceptionState : public RawInstance {
public:
// Getters and setters.
RawObject type() const;
RawObject value() const;
RawObject traceback() const;
void setType(RawObject type) const;
void setValue(RawObject value) const;
void setTraceback(RawObject tb) const;
RawObject previous() const;
void setPrevious(RawObject prev) const;
// Layout.
static const int kTypeOffset = RawHeapObject::kSize;
static const int kValueOffset = kTypeOffset + kPointerSize;
static const int kTracebackOffset = kValueOffset + kPointerSize;
static const int kPreviousOffset = kTracebackOffset + kPointerSize;
static const int kSize = kPreviousOffset + kPointerSize;
RAW_OBJECT_COMMON(ExceptionState);
};
// Base class containing functionality needed by all objects representing a
// suspended execution frame: RawGenerator, RawCoroutine, and AsyncGenerator.
class RawGeneratorBase : public RawInstance {
public:
// Get or set the RawGeneratorFrame embedded in this RawGeneratorBase.
RawObject generatorFrame() const;
void setGeneratorFrame(RawObject obj) const;
RawObject exceptionState() const;
void setExceptionState(RawObject obj) const;
RawObject name() const;
void setName(RawObject obj) const;
RawObject running() const;
void setRunning(RawObject obj) const;
RawObject qualname() const;
void setQualname(RawObject obj) const;
// Layout.
static const int kFrameOffset = RawHeapObject::kSize;
static const int kExceptionStateOffset = kFrameOffset + kPointerSize;
static const int kNameOffset = kExceptionStateOffset + kPointerSize;
static const int kQualnameOffset = kNameOffset + kPointerSize;
static const int kRunningOffset = kQualnameOffset + kPointerSize;
static const int kSize = kRunningOffset + kPointerSize;
RAW_OBJECT_COMMON(GeneratorBase);
};
class RawGenerator : public RawGeneratorBase {
public:
static const int kYieldFromOffset = RawGeneratorBase::kSize;
static const int kSize = kYieldFromOffset + kPointerSize;
RAW_OBJECT_COMMON(Generator);
};
class RawCoroutine : public RawGeneratorBase {
public:
// Layout.
static const int kAwaitOffset = RawGeneratorBase::kSize;
static const int kOriginOffset = kAwaitOffset + kPointerSize;
static const int kSize = kOriginOffset + kPointerSize;
RAW_OBJECT_COMMON(Coroutine);
};
class RawCoroutineWrapper : public RawInstance {
public:
RawObject coroutine() const;
void setCoroutine(RawObject coroutine) const;
// Layout.
static const int kCoroutineOffset = RawHeapObject::kSize;
static const int kSize = kCoroutineOffset + kPointerSize;
RAW_OBJECT_COMMON(CoroutineWrapper);
};
class RawAsyncGenerator : public RawGeneratorBase {
public:
RawObject finalizer() const;
void setFinalizer(RawObject finalizer) const;
bool hooksInited() const;
void setHooksInited(bool hooks_inited) const;
// Layout.
static const int kFinalizerOffset = RawGeneratorBase::kSize;
static const int kHooksInitedOffset = kFinalizerOffset + kPointerSize;
static const int kSize = kHooksInitedOffset + kPointerSize;
RAW_OBJECT_COMMON(AsyncGenerator);
};
class RawAsyncGeneratorOpIterBase : public RawInstance {
public:
enum class State : word { Init = 0, Iter = 1, Closed = 2 };
RawObject generator() const;
void setGenerator(RawObject generator) const;
State state() const;
void setState(State state) const;
// Layout.
static const int kGeneratorOffset = RawHeapObject::kSize;
static const int kStateOffset = kGeneratorOffset + kPointerSize;
static const int kSize = kStateOffset + kPointerSize;
RAW_OBJECT_COMMON(AsyncGeneratorOpIterBase);
};
class RawAsyncGeneratorAclose : public RawAsyncGeneratorOpIterBase {
public:
// Layout.
static const int kSize = RawAsyncGeneratorOpIterBase::kSize;
RAW_OBJECT_COMMON(AsyncGeneratorAclose);
};
class RawAsyncGeneratorAsend : public RawAsyncGeneratorOpIterBase {
public:
RawObject value() const;
void setValue(RawObject value) const;
// Layout.
static const int kValueOffset = RawAsyncGeneratorOpIterBase::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON(AsyncGeneratorAsend);
};
class RawAsyncGeneratorAthrow : public RawAsyncGeneratorOpIterBase {
public:
RawObject exceptionTraceback() const;
void setExceptionTraceback(RawObject traceback) const;
RawObject exceptionType() const;
void setExceptionType(RawObject exception_type) const;
RawObject exceptionValue() const;
void setExceptionValue(RawObject exception_value) const;
// Layout.
static const int kExceptionTracebackOffset =
RawAsyncGeneratorOpIterBase::kSize;
static const int kExceptionTypeOffset =
kExceptionTracebackOffset + kPointerSize;
static const int kExceptionValueOffset = kExceptionTypeOffset + kPointerSize;
static const int kSize = kExceptionValueOffset + kPointerSize;
RAW_OBJECT_COMMON(AsyncGeneratorAthrow);
};
class RawAsyncGeneratorWrappedValue : public RawInstance {
public:
RawObject value() const;
void setValue(RawObject value) const;
// Layout.
static const int kValueOffset = RawHeapObject::kSize;
static const int kSize = kValueOffset + kPointerSize;
RAW_OBJECT_COMMON(AsyncGeneratorWrappedValue);
};
class RawTraceback : public RawInstance {
public:
RawObject function() const;
void setFunction(RawObject function) const;
RawObject lasti() const;
void setLasti(RawObject lasti) const;
RawObject lineno() const;
void setLineno(RawObject lineno) const;
RawObject next() const;
void setNext(RawObject next) const;
// Layout.
static const int kNextOffset = RawHeapObject::kSize;
static const int kFunctionOffset = kNextOffset + kPointerSize;
static const int kLastiOffset = kFunctionOffset + kPointerSize;
static const int kLinenoOffset = kLastiOffset + kPointerSize;
static const int kSize = kLinenoOffset + kPointerSize;
RAW_OBJECT_COMMON(Traceback);
};
// The primitive IO types
class RawUnderIOBase : public RawInstance {
public:
// Getters and setters
bool closed() const;
void setClosed(bool closed) const;
// Layout
static const int kClosedOffset = RawHeapObject::kSize;
static const int kSize = kClosedOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UnderIOBase);
};
class RawUnderRawIOBase : public RawUnderIOBase {
public:
RAW_OBJECT_COMMON_NO_CAST(UnderRawIOBase);
};
class RawUnderBufferedIOBase : public RawUnderRawIOBase {
public:
RAW_OBJECT_COMMON_NO_CAST(UnderBufferedIOBase);
};
class RawUnderBufferedIOMixin : public RawUnderBufferedIOBase {
public:
// Getters and setters
RawObject underlying() const;
void setUnderlying(RawObject value) const;
// Layout
static const int kUnderlyingOffset = RawUnderBufferedIOBase::kSize;
static const int kSize = kUnderlyingOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(UnderBufferedIOMixin);
};
class RawBufferedRandom : public RawUnderBufferedIOMixin {
public:
// Getters and setters
word bufferSize() const;
void setBufferSize(word buffer_size) const;
RawObject reader() const;
void setReader(RawObject reader) const;
RawObject writeBuf() const;
void setWriteBuf(RawObject under_write_buf) const;
RawObject writeLock() const;
void setWriteLock(RawObject under_write_lock) const;
// Layout
static const int kBufferSizeOffset = RawUnderBufferedIOMixin::kSize;
static const int kReaderOffset = kBufferSizeOffset + kPointerSize;
static const int kWriteBufOffset = kReaderOffset + kPointerSize;
static const int kWriteLockOffset = kWriteBufOffset + kPointerSize;
static const int kSize = kWriteLockOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(BufferedRandom);
};
class RawBufferedReader : public RawUnderBufferedIOMixin {
public:
// Getters and setters
word bufferSize() const;
void setBufferSize(word buffer_size) const;
RawObject readBuf() const;
void setReadBuf(RawObject read_buf) const;
word readPos() const;
void setReadPos(word read_pos) const;
word bufferNumBytes() const;
void setBufferNumBytes(word buffer_num_bytes) const;
// Layout
static const int kBufferSizeOffset = RawUnderBufferedIOMixin::kSize;
static const int kReadBufOffset = kBufferSizeOffset + kPointerSize;
static const int kReadPosOffset = kReadBufOffset + kPointerSize;
static const int kBufferNumBytesOffset = kReadPosOffset + kPointerSize;
static const int kSize = kBufferNumBytesOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(BufferedReader);
};
class RawBufferedWriter : public RawUnderBufferedIOMixin {
public:
// Getters and setters
word bufferSize() const;
void setBufferSize(RawObject buffer_size) const;
RawObject writeBuf() const;
void setWriteBuf(RawObject under_write_buf) const;
RawObject writeLock() const;
void setWriteLock(RawObject under_write_lock) const;
// Layout
static const int kBufferSizeOffset = RawUnderBufferedIOMixin::kSize;
static const int kWriteBufOffset = kBufferSizeOffset + kPointerSize;
static const int kWriteLockOffset = kWriteBufOffset + kPointerSize;
static const int kSize = kWriteLockOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(BufferedWriter);
};
class RawBytesIO : public RawUnderBufferedIOBase {
public:
// Getters and setters
RawObject buffer() const;
void setBuffer(RawObject buffer) const;
word numItems() const;
void setNumItems(word num_items) const;
word pos() const;
void setPos(word pos) const;
// Layout
static const int kBufferOffset = RawUnderBufferedIOBase::kSize;
static const int kNumItemsOffset = kBufferOffset + kPointerSize;
static const int kPosOffset = kNumItemsOffset + kPointerSize;
static const int kSize = kPosOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(BytesIO);
};
class RawFileIO : public RawUnderRawIOBase {
public:
// Getters and setters
RawObject fd() const;
void setFd(RawObject fd) const;
RawObject name() const;
void setName(RawObject value) const;
RawObject isCreated() const;
void setCreated(RawObject value) const;
RawObject isReadable() const;
void setReadable(RawObject value) const;
RawObject isWritable() const;
void setWritable(RawObject value) const;
RawObject isAppending() const;
void setAppending(RawObject value) const;
RawObject seekable() const;
void setSeekable(RawObject value) const;
RawObject shouldCloseFd() const;
void setShouldCloseFd(RawObject value) const;
// Layout
static const int kFdOffset = RawUnderRawIOBase::kSize;
static const int kNameOffset = kFdOffset + kPointerSize;
static const int kCreatedOffset = kNameOffset + kPointerSize;
static const int kReadableOffset = kCreatedOffset + kPointerSize;
static const int kWritableOffset = kReadableOffset + kPointerSize;
static const int kAppendingOffset = kWritableOffset + kPointerSize;
static const int kSeekableOffset = kAppendingOffset + kPointerSize;
static const int kCloseFdOffset = kSeekableOffset + kPointerSize;
static const int kSize = kCloseFdOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(FileIO);
};
class RawInstanceMethod : public RawInstance {
public:
// Getters and setters
RawObject function() const;
void setFunction(RawObject function) const;
// Layout.
static const int kFunctionOffset = RawHeapObject::kSize;
static const int kSize = kFunctionOffset + kPointerSize;
RAW_OBJECT_COMMON(InstanceMethod);
};
class RawInstanceProxy : public RawInstance {
public:
// Getters and setters
RawObject instance() const;
void setInstance(RawObject instance) const;
// Layout
static const int kInstanceOffset = RawHeapObject::kSize;
static const int kSize = kInstanceOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(InstanceProxy);
};
class RawIncrementalNewlineDecoder : public RawInstance {
public:
// Getters and setters
RawObject errors() const;
void setErrors(RawObject errors) const;
RawObject translate() const;
void setTranslate(RawObject translate) const;
RawObject decoder() const;
void setDecoder(RawObject decoder) const;
RawObject seennl() const;
void setSeennl(RawObject seennl) const;
RawObject pendingcr() const;
void setPendingcr(RawObject pendingcr) const;
// Layout
static const int kErrorsOffset = RawHeapObject::kSize;
static const int kTranslateOffset = kErrorsOffset + kPointerSize;
static const int kDecoderOffset = kTranslateOffset + kPointerSize;
static const int kSeennlOffset = kDecoderOffset + kPointerSize;
static const int kPendingcrOffset = kSeennlOffset + kPointerSize;
static const int kSize = kPendingcrOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(IncrementalNewlineDecoder);
};
// RawUnderTextIOBase
class RawUnderTextIOBase : public RawUnderIOBase {
public:
RAW_OBJECT_COMMON_NO_CAST(UnderTextIOBase);
};
// RawTextIOWrapper
class RawTextIOWrapper : public RawUnderTextIOBase {
public:
// Getters and setters
RawObject buffer() const;
void setBuffer(RawObject buffer) const;
bool detached() const;
bool lineBuffering() const;
void setLineBuffering(RawObject line_buffering) const;
RawObject encoding() const;
void setEncoding(RawObject encoding) const;
RawObject errors() const;
void setErrors(RawObject errors) const;
bool readuniversal() const;
void setReaduniversal(RawObject readuniversal) const;
bool readtranslate() const;
void setReadtranslate(RawObject readtranslate) const;
RawObject readnl() const;
void setReadnl(RawObject readnl) const;
bool writetranslate() const;
void setWritetranslate(RawObject writetranslate) const;
RawObject writenl() const;
void setWritenl(RawObject writenl) const;
RawObject encoder() const;
void setEncoder(RawObject encoder) const;
RawObject decoder() const;
void setDecoder(RawObject decoder) const;
RawObject decodedChars() const;
void setDecodedChars(RawObject decoded_chars) const;
RawObject decodedCharsUsed() const;
void setDecodedCharsUsed(RawObject decoded_chars_used) const;
RawObject snapshot() const;
void setSnapshot(RawObject snapshot) const;
RawObject seekable() const;
void setSeekable(RawObject seekable) const;
RawObject hasRead1() const;
void setHasRead1(RawObject has_read1) const;
RawObject b2cratio() const;
void setB2cratio(RawObject b2cratio) const;
RawObject telling() const;
void setTelling(RawObject telling) const;
// Layout
static const int kBufferOffset = RawUnderTextIOBase::kSize;
static const int kLineBufferingOffset = kBufferOffset + kPointerSize;
static const int kEncodingOffset = kLineBufferingOffset + kPointerSize;
static const int kErrorsOffset = kEncodingOffset + kPointerSize;
static const int kReaduniversalOffset = kErrorsOffset + kPointerSize;
static const int kReadtranslateOffset = kReaduniversalOffset + kPointerSize;
static const int kReadnlOffset = kReadtranslateOffset + kPointerSize;
static const int kWritetranslateOffset = kReadnlOffset + kPointerSize;
static const int kWritenlOffset = kWritetranslateOffset + kPointerSize;
static const int kEncoderOffset = kWritenlOffset + kPointerSize;
static const int kDecoderOffset = kEncoderOffset + kPointerSize;
static const int kDecodedCharsOffset = kDecoderOffset + kPointerSize;
static const int kDecodedCharsUsedOffset = kDecodedCharsOffset + kPointerSize;
static const int kSnapshotOffset = kDecodedCharsUsedOffset + kPointerSize;
static const int kSeekableOffset = kSnapshotOffset + kPointerSize;
static const int kHasRead1Offset = kSeekableOffset + kPointerSize;
static const int kB2cratioOffset = kHasRead1Offset + kPointerSize;
static const int kTellingOffset = kB2cratioOffset + kPointerSize;
// TODO(T54575279): make mode an overflow attribute
static const int kModeOffset = kTellingOffset + kPointerSize;
static const int kSize = kModeOffset + kPointerSize;
RAW_OBJECT_COMMON_NO_CAST(TextIOWrapper);
};
// RawStringIO
class RawStringIO : public RawUnderTextIOBase {
public:
RawObject buffer() const;
void setBuffer(RawObject buffer) const;
word pos() const;
void setPos(word new_pos) const;
// TODO(T59697642): don't use a whole attribute, just read and write a bit in
// a bitfield.
RawObject readnl() const;
void setReadnl(RawObject readnl) const;
// TODO(T59697642): don't use a whole attribute, just read and write a bit in
// a bitfield.
bool hasReadtranslate() const;
void setReadtranslate(bool readtranslate) const;
// TODO(T59697642): don't use a whole attribute, just read and write a bit in
// a bitfield.
bool hasReaduniversal() const;
void setReaduniversal(bool readuniversal) const;
// TODO(T59697642): don't use a whole attribute, just read and write bits in a
// bitfield.
RawObject seennl() const;
void setSeennl(RawObject seennl) const;
// TODO(T59697642): don't use a whole attribute, just read and write a bit in
// a bitfield.
RawObject writenl() const;
void setWritenl(RawObject writenl) const;
// TODO(T59697642): don't use a whole attribute, just read and write a bit in
// a bitfield.
bool hasWritetranslate() const;
void setWritetranslate(bool writetranslate) const;
// Layout
static const int kBufferOffset = RawUnderTextIOBase::kSize;
static const int kPosOffset = kBufferOffset + kPointerSize;
static const int kReadnlOffset = kPosOffset + kPointerSize;
static const int kReadtranslateOffset = kReadnlOffset + kPointerSize;
static const int kReaduniversalOffset = kReadtranslateOffset + kPointerSize;
static const int kSeennlOffset = kReaduniversalOffset + kPointerSize;
static const int kWritenlOffset = kSeennlOffset + kPointerSize;
static const int kWritetranslateOffset = kWritenlOffset + kPointerSize;
static const int kSize = kWritetranslateOffset + kPointerSize;
RAW_OBJECT_COMMON(StringIO);
};
// RawObject
inline word roundAllocationSize(word size) {
return Utils::roundUp(size, kObjectAlignment);
}
inline bool isInstanceLayout(LayoutId id) {
return id > LayoutId::kLastNonInstance;
}
inline RawObject::RawObject(uword raw) : raw_{raw} {}
inline uword RawObject::raw() const { return raw_; }
inline bool RawObject::isObject() const { return true; }
inline LayoutId RawObject::layoutId() const {
if (isHeapObject()) {
return RawHeapObject::cast(*this).header().layoutId();
}
if (isSmallInt()) {
return LayoutId::kSmallInt;
}
return static_cast<LayoutId>(raw() & kImmediateTagMask);
}
inline bool RawObject::isBool() const {
return (raw() & RawBool::kTagMask) == kBoolTag;
}
inline bool RawObject::isError() const {
return (raw() & RawError::kTagMask) == kErrorTag;
}
inline bool RawObject::isErrorError() const {
return raw() == RawError::error().raw();
}
inline bool RawObject::isErrorException() const {
return raw() == RawError::exception().raw();
}
inline bool RawObject::isErrorNotFound() const {
return raw() == RawError::notFound().raw();
}
inline bool RawObject::isErrorOutOfBounds() const {
return raw() == RawError::outOfBounds().raw();
}
inline bool RawObject::isErrorOutOfMemory() const {
return raw() == RawError::outOfMemory().raw();
}
inline bool RawObject::isErrorNoMoreItems() const {
return raw() == RawError::noMoreItems().raw();
}
inline bool RawObject::isHeader() const {
return (raw() & kPrimaryTagMask) == kHeaderTag;
}
inline bool RawObject::isNoneType() const {
return *this == RawNoneType::object();
}
inline bool RawObject::isNotImplementedType() const {
return *this == RawNotImplementedType::object();
}
inline bool RawObject::isSmallBytes() const {
return (raw() & kImmediateTagMask) == kSmallBytesTag;
}
inline bool RawObject::isSmallInt() const {
return (raw() & kSmallIntTagMask) == kSmallIntTag;
}
inline bool RawObject::isSmallStr() const {
return (raw() & kImmediateTagMask) == kSmallStrTag;
}
inline bool RawObject::isUnbound() const {
return *this == RawUnbound::object();
}
inline bool RawObject::isHeapObject() const {
return (raw() & kPrimaryTagMask) == kHeapObjectTag;
}
inline bool RawObject::isHeapObjectWithLayout(LayoutId layout_id) const {
return isHeapObject() &&
RawHeapObject::cast(*this).header().layoutId() == layout_id;
}
inline bool RawObject::isInternal() const {
// Test whether an object is unsafe to expose to managed code
return isError() || isMutableBytes() || isMutableTuple() || isLayout() ||
isUnbound();
}
inline bool RawObject::isImmediateObjectNotSmallInt() const {
// Test whether object is not a heap object when it is known that it is not a
// SmallInt (the lowest bit is guaranteed to be one so we don't need to
// re-test that).
static_assert((kHeapObjectTag & ~kSmallIntTagMask) == 0,
"assumed heapobject tag bits outside smallint bit are 0");
return (raw() & (kPrimaryTagMask & ~kSmallIntTagMask)) != 0;
}
inline bool RawObject::isInstance() const {
return isHeapObject() && (RawHeapObject::cast(*this).header().layoutId() >
LayoutId::kLastNonInstance);
}
inline bool RawObject::isArray() const {
return isHeapObjectWithLayout(LayoutId::kArray);
}
inline bool RawObject::isAsyncGenerator() const {
return isHeapObjectWithLayout(LayoutId::kAsyncGenerator);
}
inline bool RawObject::isAsyncGeneratorOpIterBase() const {
return isAsyncGeneratorAclose() || isAsyncGeneratorAsend() ||
isAsyncGeneratorAthrow();
}
inline bool RawObject::isAsyncGeneratorAclose() const {
return isHeapObjectWithLayout(LayoutId::kAsyncGeneratorAclose);
}
inline bool RawObject::isAsyncGeneratorAsend() const {
return isHeapObjectWithLayout(LayoutId::kAsyncGeneratorAsend);
}
inline bool RawObject::isAsyncGeneratorAthrow() const {
return isHeapObjectWithLayout(LayoutId::kAsyncGeneratorAthrow);
}
inline bool RawObject::isAsyncGeneratorWrappedValue() const {
return isHeapObjectWithLayout(LayoutId::kAsyncGeneratorWrappedValue);
}
inline bool RawObject::isAttributeDict() const {
return isType() || isModule();
}
inline bool RawObject::isBaseException() const {
return isHeapObjectWithLayout(LayoutId::kBaseException);
}
inline bool RawObject::isBoundMethod() const {
return isHeapObjectWithLayout(LayoutId::kBoundMethod);
}
inline bool RawObject::isBufferedRandom() const {
return isHeapObjectWithLayout(LayoutId::kBufferedRandom);
}
inline bool RawObject::isBufferedReader() const {
return isHeapObjectWithLayout(LayoutId::kBufferedReader);
}
inline bool RawObject::isBufferedWriter() const {
return isHeapObjectWithLayout(LayoutId::kBufferedWriter);
}
inline bool RawObject::isUnderBufferedIOBase() const {
return isHeapObjectWithLayout(LayoutId::kUnderBufferedIOBase);
}
inline bool RawObject::isUnderBufferedIOMixin() const {
return isHeapObjectWithLayout(LayoutId::kUnderBufferedIOMixin);
}
inline bool RawObject::isBytearray() const {
return isHeapObjectWithLayout(LayoutId::kBytearray);
}
inline bool RawObject::isBytearrayIterator() const {
return isHeapObjectWithLayout(LayoutId::kBytearrayIterator);
}
inline bool RawObject::isBytesIO() const {
return isHeapObjectWithLayout(LayoutId::kBytesIO);
}
inline bool RawObject::isBytesIterator() const {
return isHeapObjectWithLayout(LayoutId::kBytesIterator);
}
inline bool RawObject::isCell() const {
return isHeapObjectWithLayout(LayoutId::kCell);
}
inline bool RawObject::isClassMethod() const {
return isHeapObjectWithLayout(LayoutId::kClassMethod);
}
inline bool RawObject::isCode() const {
return isHeapObjectWithLayout(LayoutId::kCode);
}
inline bool RawObject::isComplex() const {
return isHeapObjectWithLayout(LayoutId::kComplex);
}
inline bool RawObject::isContext() const {
return isHeapObjectWithLayout(LayoutId::kContext);
}
inline bool RawObject::isContextVar() const {
return isHeapObjectWithLayout(LayoutId::kContextVar);
}
inline bool RawObject::isCoroutine() const {
return isHeapObjectWithLayout(LayoutId::kCoroutine);
}
inline bool RawObject::isCoroutineWrapper() const {
return isHeapObjectWithLayout(LayoutId::kCoroutineWrapper);
}
inline bool RawObject::isDataArray() const {
return isLargeBytes() || isLargeStr() || isMutableBytes();
}
inline bool RawObject::isDeque() const {
return isHeapObjectWithLayout(LayoutId::kDeque);
}
inline bool RawObject::isDequeIterator() const {
return isHeapObjectWithLayout(LayoutId::kDequeIterator);
}
inline bool RawObject::isDequeReverseIterator() const {
return isHeapObjectWithLayout(LayoutId::kDequeReverseIterator);
}
inline bool RawObject::isDict() const {
return isHeapObjectWithLayout(LayoutId::kDict);
}
inline bool RawObject::isDictItemIterator() const {
return isHeapObjectWithLayout(LayoutId::kDictItemIterator);
}
inline bool RawObject::isDictItems() const {
return isHeapObjectWithLayout(LayoutId::kDictItems);
}
inline bool RawObject::isDictKeyIterator() const {
return isHeapObjectWithLayout(LayoutId::kDictKeyIterator);
}
inline bool RawObject::isDictKeys() const {
return isHeapObjectWithLayout(LayoutId::kDictKeys);
}
inline bool RawObject::isDictValueIterator() const {
return isHeapObjectWithLayout(LayoutId::kDictValueIterator);
}
inline bool RawObject::isDictValues() const {
return isHeapObjectWithLayout(LayoutId::kDictValues);
}
inline bool RawObject::isEllipsis() const {
return isHeapObjectWithLayout(LayoutId::kEllipsis);
}
inline bool RawObject::isEnumerate() const {
return isHeapObjectWithLayout(LayoutId::kEnumerate);
}
inline bool RawObject::isException() const {
return isHeapObjectWithLayout(LayoutId::kException);
}
inline bool RawObject::isExceptionState() const {
return isHeapObjectWithLayout(LayoutId::kExceptionState);
}
inline bool RawObject::isFileIO() const {
return isHeapObjectWithLayout(LayoutId::kFileIO);
}
inline bool RawObject::isFloat() const {
return isHeapObjectWithLayout(LayoutId::kFloat);
}
inline bool RawObject::isFrameProxy() const {
return isHeapObjectWithLayout(LayoutId::kFrameProxy);
}
inline bool RawObject::isFrozenSet() const {
return isHeapObjectWithLayout(LayoutId::kFrozenSet);
}
inline bool RawObject::isFunction() const {
return isHeapObjectWithLayout(LayoutId::kFunction);
}
inline bool RawObject::isGenerator() const {
return isHeapObjectWithLayout(LayoutId::kGenerator);
}
inline bool RawObject::isGeneratorFrame() const {
return isHeapObjectWithLayout(LayoutId::kGeneratorFrame);
}
inline bool RawObject::isIncrementalNewlineDecoder() const {
return isHeapObjectWithLayout(LayoutId::kIncrementalNewlineDecoder);
}
inline bool RawObject::isInstanceMethod() const {
return isHeapObjectWithLayout(LayoutId::kInstanceMethod);
}
inline bool RawObject::isInstanceProxy() const {
return isHeapObjectWithLayout(LayoutId::kInstanceProxy);
}
inline bool RawObject::isImportError() const {
return isHeapObjectWithLayout(LayoutId::kImportError);
}
inline bool RawObject::isIndexError() const {
return isHeapObjectWithLayout(LayoutId::kIndexError);
}
inline bool RawObject::isUnderIOBase() const {
return isHeapObjectWithLayout(LayoutId::kUnderIOBase);
}
inline bool RawObject::isKeyError() const {
return isHeapObjectWithLayout(LayoutId::kKeyError);
}
inline bool RawObject::isLargeBytes() const {
return isHeapObjectWithLayout(LayoutId::kLargeBytes) || isMutableBytes();
}
inline bool RawObject::isLargeInt() const {
return isHeapObjectWithLayout(LayoutId::kLargeInt);
}
inline bool RawObject::isLargeStr() const {
return isHeapObjectWithLayout(LayoutId::kLargeStr);
}
inline bool RawObject::isLayout() const {
return isHeapObjectWithLayout(LayoutId::kLayout);
}
inline bool RawObject::isList() const {
return isHeapObjectWithLayout(LayoutId::kList);
}
inline bool RawObject::isListIterator() const {
return isHeapObjectWithLayout(LayoutId::kListIterator);
}
inline bool RawObject::isLongRangeIterator() const {
return isHeapObjectWithLayout(LayoutId::kLongRangeIterator);
}
inline bool RawObject::isLookupError() const {
return isHeapObjectWithLayout(LayoutId::kLookupError);
}
inline bool RawObject::isMappingProxy() const {
return isHeapObjectWithLayout(LayoutId::kMappingProxy);
}
inline bool RawObject::isMemoryView() const {
return isHeapObjectWithLayout(LayoutId::kMemoryView);
}
inline bool RawObject::isMmap() const {
return isHeapObjectWithLayout(LayoutId::kMmap);
}
inline bool RawObject::isModule() const {
return isHeapObjectWithLayout(LayoutId::kModule);
}
inline bool RawObject::isModuleProxy() const {
return isHeapObjectWithLayout(LayoutId::kModuleProxy);
}
inline bool RawObject::isModuleNotFoundError() const {
return isHeapObjectWithLayout(LayoutId::kModuleNotFoundError);
}
inline bool RawObject::isMutableBytes() const {
return isHeapObjectWithLayout(LayoutId::kMutableBytes);
}
inline bool RawObject::isMutableTuple() const {
return isHeapObjectWithLayout(LayoutId::kMutableTuple);
}
inline bool RawObject::isNotImplementedError() const {
return isHeapObjectWithLayout(LayoutId::kNotImplementedError);
}
inline bool RawObject::isPointer() const {
return isHeapObjectWithLayout(LayoutId::kPointer);
}
inline bool RawObject::isProperty() const {
return isHeapObjectWithLayout(LayoutId::kProperty);
}
inline bool RawObject::isRange() const {
return isHeapObjectWithLayout(LayoutId::kRange);
}
inline bool RawObject::isRangeIterator() const {
return isHeapObjectWithLayout(LayoutId::kRangeIterator);
}
inline bool RawObject::isUnderRawIOBase() const {
return isHeapObjectWithLayout(LayoutId::kUnderRawIOBase);
}
inline bool RawObject::isRuntimeError() const {
return isHeapObjectWithLayout(LayoutId::kRuntimeError);
}
inline bool RawObject::isSeqIterator() const {
return isHeapObjectWithLayout(LayoutId::kSeqIterator);
}
inline bool RawObject::isSet() const {
return isHeapObjectWithLayout(LayoutId::kSet);
}
inline bool RawObject::isSetIterator() const {
return isHeapObjectWithLayout(LayoutId::kSetIterator);
}
inline bool RawObject::isSlice() const {
return isHeapObjectWithLayout(LayoutId::kSlice);
}
inline bool RawObject::isSlotDescriptor() const {
return isHeapObjectWithLayout(LayoutId::kSlotDescriptor);
}
inline bool RawObject::isStaticMethod() const {
return isHeapObjectWithLayout(LayoutId::kStaticMethod);
}
inline bool RawObject::isStopIteration() const {
return isHeapObjectWithLayout(LayoutId::kStopIteration);
}
inline bool RawObject::isStrArray() const {
return isHeapObjectWithLayout(LayoutId::kStrArray);
}
inline bool RawObject::isStringIO() const {
return isHeapObjectWithLayout(LayoutId::kStringIO);
}
inline bool RawObject::isStrIterator() const {
return isHeapObjectWithLayout(LayoutId::kStrIterator);
}
inline bool RawObject::isSuper() const {
return isHeapObjectWithLayout(LayoutId::kSuper);
}
inline bool RawObject::isSyntaxError() const {
return isHeapObjectWithLayout(LayoutId::kSyntaxError);
}
inline bool RawObject::isSystemExit() const {
return isHeapObjectWithLayout(LayoutId::kSystemExit);
}
inline bool RawObject::isTextIOWrapper() const {
return isHeapObjectWithLayout(LayoutId::kTextIOWrapper);
}
inline bool RawObject::isToken() const {
return isHeapObjectWithLayout(LayoutId::kToken);
}
inline bool RawObject::isTraceback() const {
return isHeapObjectWithLayout(LayoutId::kTraceback);
}
inline bool RawObject::isTuple() const {
return isHeapObjectWithLayout(LayoutId::kTuple) || isMutableTuple();
}
inline bool RawObject::isTupleIterator() const {
return isHeapObjectWithLayout(LayoutId::kTupleIterator);
}
inline bool RawObject::isType() const {
return isHeapObjectWithLayout(LayoutId::kType);
}
inline bool RawObject::isTypeProxy() const {
return isHeapObjectWithLayout(LayoutId::kTypeProxy);
}
inline bool RawObject::isUnicodeDecodeError() const {
return isHeapObjectWithLayout(LayoutId::kUnicodeDecodeError);
}
inline bool RawObject::isUnicodeEncodeError() const {
return isHeapObjectWithLayout(LayoutId::kUnicodeEncodeError);
}
inline bool RawObject::isUnicodeError() const {
return isHeapObjectWithLayout(LayoutId::kUnicodeError);
}
inline bool RawObject::isUnicodeErrorBase() const {
return isUnicodeDecodeError() || isUnicodeEncodeError() ||
isUnicodeTranslateError();
}
inline bool RawObject::isUnicodeTranslateError() const {
return isHeapObjectWithLayout(LayoutId::kUnicodeTranslateError);
}
inline bool RawObject::isValueCell() const {
return isHeapObjectWithLayout(LayoutId::kValueCell);
}
inline bool RawObject::isWeakCallableProxy() const {
return isHeapObjectWithLayout(LayoutId::kWeakCallableProxy);
}
inline bool RawObject::isWeakProxy() const {
return isHeapObjectWithLayout(LayoutId::kWeakProxy);
}
inline bool RawObject::isWeakLink() const {
return isHeapObjectWithLayout(LayoutId::kWeakLink);
}
inline bool RawObject::isWeakRef() const {
// WeakLink is a subclass of WeakLink sharing its layout, so this is safe.
return isHeapObjectWithLayout(LayoutId::kWeakRef) ||
isHeapObjectWithLayout(LayoutId::kWeakLink);
}
inline bool RawObject::isBytes() const {
return isSmallBytes() || isLargeBytes();
}
inline bool RawObject::isGeneratorBase() const {
return isGenerator() || isCoroutine() || isAsyncGenerator();
}
inline bool RawObject::isInt() const {
return isSmallInt() || isLargeInt() || isBool();
}
inline bool RawObject::isSetBase() const { return isSet() || isFrozenSet(); }
inline bool RawObject::isStr() const { return isSmallStr() || isLargeStr(); }
inline bool RawObject::operator==(const RawObject& other) const {
return raw() == other.raw();
}
inline bool RawObject::operator!=(const RawObject& other) const {
return !operator==(other);
}
template <typename T>
T RawObject::rawCast() const {
return *static_cast<const T*>(this);
}
// RawBytes
inline word RawBytes::findByte(byte value, word start, word length) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).findByte(value, start, length);
}
return RawLargeBytes::cast(*this).findByte(value, start, length);
}
inline RawBytes RawBytes::empty() {
return RawSmallBytes::empty().rawCast<RawBytes>();
}
inline word RawBytes::length() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).length();
}
return RawLargeBytes::cast(*this).length();
}
ALWAYS_INLINE byte RawBytes::byteAt(word index) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).byteAt(index);
}
return RawLargeBytes::cast(*this).byteAt(index);
}
inline RawObject RawBytes::becomeStr() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).becomeStr();
}
return RawLargeBytes::cast(*this).becomeStr();
}
inline void RawBytes::copyTo(byte* dst, word length) const {
if (isImmediateObjectNotSmallInt()) {
RawSmallBytes::cast(*this).copyTo(dst, length);
return;
}
RawLargeBytes::cast(*this).copyTo(dst, length);
}
inline void RawBytes::copyToStartAt(byte* dst, word length, word index) const {
if (isImmediateObjectNotSmallInt()) {
RawSmallBytes::cast(*this).copyToStartAt(dst, length, index);
return;
}
RawLargeBytes::cast(*this).copyToStartAt(dst, length, index);
}
inline bool RawBytes::includesByte(byte b) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).includesByte(b);
}
return RawLargeBytes::cast(*this).includesByte(b);
}
inline bool RawBytes::isASCII() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).isASCII();
}
return RawLargeBytes::cast(*this).isASCII();
}
inline char* RawBytes::toCStr() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).toCStr();
}
return RawLargeBytes::cast(*this).toCStr();
}
inline uint16_t RawBytes::uint16At(word index) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).uint16At(index);
}
return RawLargeBytes::cast(*this).uint16At(index);
}
inline uint32_t RawBytes::uint32At(word index) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallBytes::cast(*this).uint32At(index);
}
return RawLargeBytes::cast(*this).uint32At(index);
}
inline uint64_t RawBytes::uint64At(word index) const {
DCHECK(!isSmallBytes(), "uint64_t cannot fit into SmallBytes");
return RawLargeBytes::cast(*this).uint64At(index);
}
// RawInt
inline word RawInt::asWord() const {
if (isSmallInt()) {
return RawSmallInt::cast(*this).value();
}
if (isBool()) {
return RawBool::cast(*this).value();
}
return RawLargeInt::cast(*this).asWord();
}
inline word RawInt::asWordSaturated() const {
if (numDigits() == 1) return asWord();
return isNegative() ? kMinWord : kMaxWord;
}
inline void* RawInt::asCPtr() const {
if (isSmallInt()) {
return RawSmallInt::cast(*this).asCPtr();
}
return RawLargeInt::cast(*this).asCPtr();
}
template <typename T>
OptInt<T> RawInt::asInt() const {
if (isSmallInt()) {
return RawSmallInt::cast(*this).asInt<T>();
}
if (isBool()) {
return OptInt<T>::valid(RawBool::cast(*this).value() ? 1 : 0);
}
return RawLargeInt::cast(*this).asInt<T>();
}
inline word RawInt::bitLength() const {
if (isSmallInt()) {
uword self = static_cast<uword>(std::abs(RawSmallInt::cast(*this).value()));
return Utils::highestBit(self);
}
if (isBool()) {
return RawBool::cast(*this) == RawBool::trueObj() ? 1 : 0;
}
return RawLargeInt::cast(*this).bitLength();
}
inline bool RawInt::isEven() const {
if (isSmallInt()) {
return (RawSmallInt::cast(*this).value() & 1) == 0;
}
if (isBool()) {
return *this == RawBool::falseObj();
}
return RawLargeInt::cast(*this).isEven();
}
inline bool RawInt::isNegative() const {
if (isSmallInt()) {
return RawSmallInt::cast(*this).value() < 0;
}
if (isBool()) {
return false;
}
return RawLargeInt::cast(*this).isNegative();
}
inline bool RawInt::isOdd() const {
if (isSmallInt()) {
return (RawSmallInt::cast(*this).value() & 1) != 0;
}
if (isBool()) {
return *this == RawBool::trueObj();
}
return !RawLargeInt::cast(*this).isEven();
}
inline bool RawInt::isPositive() const {
if (isSmallInt()) {
return RawSmallInt::cast(*this).value() > 0;
}
if (isBool()) {
return RawBool::cast(*this) == RawBool::trueObj();
}
return RawLargeInt::cast(*this).isPositive();
}
inline bool RawInt::isZero() const {
if (isSmallInt()) {
return RawSmallInt::cast(*this).value() == 0;
}
if (isBool()) {
return RawBool::cast(*this) == RawBool::falseObj();
}
// A RawLargeInt can never be zero
DCHECK(isLargeInt(), "RawObject must be a RawLargeInt");
return false;
}
inline word RawInt::numDigits() const {
if (isSmallInt() || isBool()) {
return 1;
}
return RawLargeInt::cast(*this).numDigits();
}
inline uword RawInt::digitAt(word index) const {
if (isSmallInt()) {
DCHECK(index == 0, "RawSmallInt digit index out of bounds");
return RawSmallInt::cast(*this).value();
}
if (isBool()) {
DCHECK(index == 0, "RawBool digit index out of bounds");
return RawBool::cast(*this).value();
}
return RawLargeInt::cast(*this).digitAt(index);
}
// RawSmallInt
inline word RawSmallInt::value() const {
return static_cast<word>(raw()) >> kSmallIntTagBits;
}
inline void* RawSmallInt::asCPtr() const {
return reinterpret_cast<void*>(value());
}
inline void* RawSmallInt::asAlignedCPtr() const {
return reinterpret_cast<void*>(asReinterpretedWord());
}
inline word RawSmallInt::asReinterpretedWord() const {
return static_cast<word>(raw());
}
template <typename T>
if_signed_t<T, OptInt<T>> RawSmallInt::asInt() const {
static_assert(sizeof(T) <= sizeof(word), "T must not be larger than word");
auto const value = this->value();
if (value > std::numeric_limits<T>::max()) return OptInt<T>::overflow();
if (value < std::numeric_limits<T>::min()) return OptInt<T>::underflow();
return OptInt<T>::valid(value);
}
template <typename T>
if_unsigned_t<T, OptInt<T>> RawSmallInt::asInt() const {
static_assert(sizeof(T) <= sizeof(word), "T must not be larger than word");
auto const max = std::numeric_limits<T>::max();
auto const value = this->value();
if (value < 0) return OptInt<T>::underflow();
if (max >= RawSmallInt::kMaxValue || static_cast<uword>(value) <= max) {
return OptInt<T>::valid(value);
}
return OptInt<T>::overflow();
}
inline RawSmallInt RawSmallInt::fromWord(word value) {
DCHECK(RawSmallInt::isValid(value), "invalid cast");
return cast(RawObject{static_cast<uword>(value) << kSmallIntTagBits});
}
inline RawSmallInt RawSmallInt::fromWordTruncated(word value) {
return cast(RawObject{static_cast<uword>(value) << kSmallIntTagBits});
}
inline RawSmallInt RawSmallInt::fromReinterpretedWord(word value) {
return cast(RawObject{static_cast<uword>(value)});
}
inline RawSmallInt RawSmallInt::fromAlignedCPtr(void* ptr) {
return fromReinterpretedWord(reinterpret_cast<word>(ptr));
}
inline word RawSmallInt::truncate(word value) {
return (value << kSmallIntTagBits) >> kSmallIntTagBits;
}
inline word RawSmallInt::hash() const {
word val = value();
uword abs = static_cast<uword>(val);
// Shortcut for positive values smaller than `kArithmeticHashModulus`.
if (abs < kArithmeticHashModulus) {
return value();
}
// Compute `value % kArithmeticHashModulus` (with C/C++ style modulo). This
// uses the algorithm from `longIntHash()` simplified for a single word.
const word bits_per_half = kBitsPerWord / 2;
if (val < 0) {
abs = -abs;
}
// The `longIntHash()` formula is simplified using the following equivalences:
// (1) ((abs >> bits_per_half) & p) << bits_per_half
// <=> abs & ((p >> bits_per_half) << bits_per_half)
// (2) (abs >> bits_per_half) >> (kArithmeticHashBits - bits_per_half)
// <=> abs >> kArithmeticHashBits
uword result =
(abs & ((kArithmeticHashModulus >> bits_per_half) << bits_per_half)) |
abs >> kArithmeticHashBits;
result += abs & ((uword{1} << bits_per_half) - 1);
if (result >= kArithmeticHashModulus) {
result -= kArithmeticHashModulus;
}
if (val < 0) {
result = -result;
// cpython replaces `-1` results with -2, because -1 is used as an
// "uninitialized hash" marker in some situations. We do not use the same
// marker, but do the same to match behavior.
if (result == static_cast<uword>(word{-1})) {
result -= 1;
}
}
return result;
}
// RawHeader
inline word RawHeader::count() const {
return static_cast<word>((raw() >> kCountOffset) & kCountMask);
}
inline bool RawHeader::hasOverflow() const {
return count() == kCountOverflowFlag;
}
inline word RawHeader::hashCode() const {
return static_cast<word>((raw() >> kHashCodeOffset) & kHashCodeMask);
}
inline RawHeader RawHeader::withHashCode(word value) const {
auto header = raw();
header &= ~(kHashCodeMask << kHashCodeOffset);
header |= (value & kHashCodeMask) << kHashCodeOffset;
return cast(RawObject{header});
}
inline LayoutId RawHeader::layoutId() const {
return static_cast<LayoutId>((raw() >> kLayoutIdOffset) & kLayoutIdMask);
}
inline RawHeader RawHeader::withLayoutId(LayoutId layout_id) const {
DCHECK_BOUND(static_cast<word>(layout_id), kMaxLayoutId);
auto header = raw();
header &= ~(kLayoutIdMask << kLayoutIdOffset);
header |= (static_cast<word>(layout_id) & kLayoutIdMask) << kLayoutIdOffset;
return cast(RawObject{header});
}
inline ObjectFormat RawHeader::format() const {
return static_cast<ObjectFormat>((raw() >> kFormatOffset) & kFormatMask);
}
inline RawHeader RawHeader::from(word count, word hash, LayoutId id,
ObjectFormat format) {
DCHECK(
(count >= 0) && ((count <= kCountMax) || (count == kCountOverflowFlag)),
"bounds violation, %ld not in 0..%d", count, kCountMax);
uword result = kHeaderTag;
result |= ((count > kCountMax) ? kCountOverflowFlag : count) << kCountOffset;
result |= hash << kHashCodeOffset;
result |= static_cast<uword>(id) << kLayoutIdOffset;
result |= static_cast<uword>(format) << kFormatOffset;
return cast(RawObject{result});
}
// RawSmallData
// Access data within a SmallData reference. This gives direct low-level
// access. It is only apropriate to use in code to build up higher abstractions.
inline const byte* smallDataData(const RawSmallData* obj) {
static_assert(endian::native == endian::little, "big endian not implemented");
return reinterpret_cast<const byte*>(obj) + RawSmallData::kDataOffset;
}
inline RawSmallData::RawSmallData(uword raw) : RawObject(raw) {}
inline word RawSmallData::length() const {
return (raw() >> kImmediateTagBits) & kMaxLength;
}
inline byte RawSmallData::byteAt(word index) const {
DCHECK_INDEX(index, length());
return smallDataData(this)[index];
}
inline void RawSmallData::copyTo(byte* dst, word length) const {
DCHECK_BOUND(length, this->length());
std::memcpy(dst, smallDataData(this), length);
}
inline void RawSmallData::copyToStartAt(byte* dst, word length,
word index) const {
DCHECK_BOUND(index, this->length());
DCHECK_BOUND(length, this->length() - index);
std::memcpy(dst, smallDataData(this) + index, length);
}
inline uint16_t RawSmallData::uint16At(word index) const {
uint16_t result;
DCHECK_INDEX(index, length() - word{sizeof(result) - 1});
std::memcpy(&result, smallDataData(this) + index, sizeof(result));
return result;
}
inline uint32_t RawSmallData::uint32At(word index) const {
uint32_t result;
DCHECK(kMaxLength >= sizeof(result), "SmallBytes cannot fit uint32_t");
DCHECK_INDEX(index, length() - word{sizeof(result) - 1});
std::memcpy(&result, smallDataData(this) + index, sizeof(result));
return result;
}
inline word RawSmallData::hash() const {
return static_cast<word>(raw() >> RawObject::kImmediateTagBits);
}
// RawSmallBytes
inline RawSmallBytes::RawSmallBytes(uword raw) : RawSmallData(raw) {}
inline RawSmallBytes RawSmallBytes::empty() {
return RawSmallBytes(kSmallBytesTag);
}
// RawSmallStr
inline RawSmallStr::RawSmallStr(uword raw) : RawSmallData(raw) {}
inline RawSmallStr RawSmallStr::empty() { return RawSmallStr(kSmallStrTag); }
// RawError
inline RawError::RawError(ErrorKind kind)
: RawObject{(static_cast<uword>(kind) << kKindOffset) | kErrorTag} {}
inline RawError RawError::error() { return RawError{ErrorKind::kNone}; }
inline RawError RawError::exception() {
return RawError{ErrorKind::kException};
}
inline RawError RawError::notFound() { return RawError{ErrorKind::kNotFound}; }
inline RawError RawError::noMoreItems() {
return RawError{ErrorKind::kNoMoreItems};
}
inline RawError RawError::outOfMemory() {
return RawError{ErrorKind::kOutOfMemory};
}
inline RawError RawError::outOfBounds() {
return RawError{ErrorKind::kOutOfBounds};
}
inline ErrorKind RawError::kind() const {
return static_cast<ErrorKind>(raw() >> kKindOffset);
}
// RawBool
inline RawBool RawBool::trueObj() { return fromBool(true); }
inline RawBool RawBool::falseObj() { return fromBool(false); }
inline word RawBool::hash() const { return value(); }
inline RawBool RawBool::negate(RawObject value) {
DCHECK(value.isBool(), "not a boolean instance");
return (value == trueObj()) ? falseObj() : trueObj();
}
inline RawBool RawBool::fromBool(bool value) {
return cast(
RawObject{(static_cast<uword>(value) << kValueOffset) | kBoolTag});
}
inline bool RawBool::value() const {
return static_cast<byte>(raw() >> kValueOffset) ? true : false;
}
// RawNotImplementedType
inline RawNotImplementedType RawNotImplementedType::object() {
return RawObject{kNotImplementedTag}.rawCast<RawNotImplementedType>();
}
// RawUnbound
inline RawUnbound RawUnbound::object() {
return RawObject{kUnboundTag}.rawCast<RawUnbound>();
}
// RawNoneType
inline RawNoneType RawNoneType::object() {
return RawObject{kMaxUword}.rawCast<RawNoneType>();
}
// RawHeapObject
inline uword RawHeapObject::address() const { return raw() - kHeapObjectTag; }
inline uword RawHeapObject::baseAddress() const {
uword result = address() - RawHeader::kSize;
if (header().hasOverflow()) {
result -= kPointerSize;
}
return result;
}
inline RawHeader RawHeapObject::header() const {
return *reinterpret_cast<RawHeader*>(address() + kHeaderOffset);
}
inline void RawHeapObject::setHeader(RawHeader header) const {
*reinterpret_cast<RawHeader*>(address() + kHeaderOffset) = header;
}
inline word RawHeapObject::headerOverflow() const {
DCHECK(header().hasOverflow(), "expected Overflow");
return reinterpret_cast<RawSmallInt*>(address() + kHeaderOverflowOffset)
->value();
}
inline RawHeapObject RawHeapObject::initializeHeader(uword address, word count,
word hash, LayoutId id,
ObjectFormat format) {
if (count > RawHeader::kCountMax) {
*reinterpret_cast<RawSmallInt*>(address) = RawSmallInt::fromWord(count);
address += kPointerSize;
count = RawHeader::kCountOverflowFlag;
}
*reinterpret_cast<RawHeader*>(address) =
RawHeader::from(count, hash, id, format);
address += kPointerSize;
return fromAddress(address);
}
inline RawHeapObject RawHeapObject::fromAddress(uword address) {
DCHECK((address & kPrimaryTagMask) == 0,
"invalid cast, expected heap address");
return cast(RawObject{address + kHeapObjectTag});
}
inline word RawHeapObject::headerCountOrOverflow() const {
if (header().hasOverflow()) {
return headerOverflow();
}
return header().count();
}
inline word RawHeapObject::size() const {
word count = headerCountOrOverflow();
word result = headerSize(count);
switch (header().format()) {
case ObjectFormat::kData:
result += count;
break;
case ObjectFormat::kObjects:
result += count * kPointerSize;
break;
}
return roundAllocationSize(result);
}
inline word RawHeapObject::headerSize(word count) {
word result = kPointerSize;
if (count > RawHeader::kCountMax) {
result += kPointerSize;
}
return result;
}
inline RawObject RawInstance::initializeWithNone(uword address,
word num_attributes,
LayoutId layout_id) {
RawHeapObject result = RawHeapObject::initializeHeader(
address, /*count=*/num_attributes, /*hash=*/0, layout_id,
ObjectFormat::kObjects);
word start = RawHeapObject::kSize;
word size = num_attributes * kPointerSize;
std::memset(reinterpret_cast<byte*>(result.address() + start), -1,
size - start);
return result;
}
inline RawObject RawInstance::initializeWithZero(uword address,
word num_attributes,
LayoutId layout_id) {
// No memset necessary here, as the memory is guaranteed to be zero already.
return RawHeapObject::initializeHeader(address, /*count=*/num_attributes,
/*hash=*/0, layout_id,
ObjectFormat::kObjects);
}
inline bool RawHeapObject::isRoot() const {
return header().format() == ObjectFormat::kObjects;
}
inline bool RawHeapObject::isForwarding() const {
// In case of forwarded objects the header was replaced with a reference
// to the forwarded HeapObject.
return !reinterpret_cast<RawObject*>(address() + kHeaderOffset)->isHeader();
}
inline RawObject RawHeapObject::forward() const {
return *reinterpret_cast<RawObject*>(address() + kHeaderOffset);
}
inline void RawHeapObject::forwardTo(RawObject object) const {
// Overwrite the header with the forwarding address.
*reinterpret_cast<RawObject*>(address() + kHeaderOffset) = object;
}
inline RawObject RawInstance::instanceVariableAt(word offset) const {
DCHECK_INDEX(offset, headerCountOrOverflow() * kPointerSize);
return *reinterpret_cast<RawObject*>(address() + offset);
}
inline void RawInstance::instanceVariableAtPut(word offset,
RawObject value) const {
DCHECK_INDEX(offset, headerCountOrOverflow() * kPointerSize);
*reinterpret_cast<RawObject*>(address() + offset) = value;
}
inline void RawInstance::setLayoutId(LayoutId layout_id) const {
setHeader(header().withLayoutId(layout_id));
}
// RawBaseException
inline RawObject RawBaseException::args() const {
return instanceVariableAt(kArgsOffset);
}
inline void RawBaseException::setArgs(RawObject args) const {
instanceVariableAtPut(kArgsOffset, args);
}
inline RawObject RawBaseException::traceback() const {
RawObject o = tracebackOrUnbound();
return o.isUnbound() ? RawNoneType::object() : o;
}
inline RawObject RawBaseException::tracebackOrUnbound() const {
return instanceVariableAt(kTracebackOffset);
}
inline void RawBaseException::setTraceback(RawObject traceback) const {
instanceVariableAtPut(kTracebackOffset, traceback);
}
inline RawObject RawBaseException::cause() const {
RawObject o = causeOrUnbound();
return o.isUnbound() ? RawNoneType::object() : o;
}
inline RawObject RawBaseException::causeOrUnbound() const {
return instanceVariableAt(kCauseOffset);
}
inline void RawBaseException::setCause(RawObject cause) const {
instanceVariableAtPut(kCauseOffset, cause);
}
inline RawObject RawBaseException::context() const {
RawObject o = contextOrUnbound();
return o.isUnbound() ? RawNoneType::object() : o;
}
inline RawObject RawBaseException::contextOrUnbound() const {
return instanceVariableAt(kContextOffset);
}
inline void RawBaseException::setContext(RawObject context) const {
instanceVariableAtPut(kContextOffset, context);
}
inline RawObject RawBaseException::suppressContext() const {
return instanceVariableAt(kSuppressContextOffset);
}
inline void RawBaseException::setSuppressContext(RawObject suppress) const {
instanceVariableAtPut(kSuppressContextOffset, suppress);
}
// RawStopIteration
inline RawObject RawStopIteration::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawStopIteration::setValue(RawObject value) const {
instanceVariableAtPut(kValueOffset, value);
}
// RawSystemExit
inline RawObject RawSystemExit::code() const {
return instanceVariableAt(kCodeOffset);
}
inline void RawSystemExit::setCode(RawObject code) const {
instanceVariableAtPut(kCodeOffset, code);
}
// RawImportError
inline RawObject RawImportError::msg() const {
return instanceVariableAt(kMsgOffset);
}
inline void RawImportError::setMsg(RawObject msg) const {
instanceVariableAtPut(kMsgOffset, msg);
}
inline RawObject RawImportError::name() const {
return instanceVariableAt(kNameOffset);
}
inline void RawImportError::setName(RawObject name) const {
instanceVariableAtPut(kNameOffset, name);
}
inline RawObject RawImportError::path() const {
return instanceVariableAt(kPathOffset);
}
inline void RawImportError::setPath(RawObject path) const {
instanceVariableAtPut(kPathOffset, path);
}
// RawAttributeDict
inline RawObject RawAttributeDict::attributes() const {
return instanceVariableAt(kAttributesOffset);
}
inline void RawAttributeDict::setAttributes(RawObject mutable_tuple) const {
instanceVariableAtPut(kAttributesOffset, mutable_tuple);
}
inline word RawAttributeDict::attributesRemaining() const {
return RawSmallInt::cast(instanceVariableAt(kAttributesRemainingOffset))
.value();
}
inline void RawAttributeDict::setAttributesRemaining(word free) const {
instanceVariableAtPut(kAttributesRemainingOffset,
RawSmallInt::fromWord(free));
}
// RawType
inline RawObject RawType::bases() const {
return instanceVariableAt(kBasesOffset);
}
inline void RawType::setBases(RawObject bases_tuple) const {
instanceVariableAtPut(kBasesOffset, bases_tuple);
}
inline RawObject RawType::doc() const { return instanceVariableAt(kDocOffset); }
inline void RawType::setDoc(RawObject doc) const {
instanceVariableAtPut(kDocOffset, doc);
}
inline RawObject RawType::mro() const { return instanceVariableAt(kMroOffset); }
inline void RawType::setMro(RawObject object_array) const {
instanceVariableAtPut(kMroOffset, object_array);
}
inline RawObject RawType::instanceLayout() const {
return instanceVariableAt(kInstanceLayoutOffset);
}
inline void RawType::setInstanceLayout(RawObject layout) const {
instanceVariableAtPut(kInstanceLayoutOffset, layout);
}
inline LayoutId RawType::instanceLayoutId() const {
return static_cast<LayoutId>(
RawSmallInt::cast(instanceVariableAt(kInstanceLayoutIdOffset)).value());
}
inline void RawType::setInstanceLayoutId(LayoutId id) const {
instanceVariableAtPut(kInstanceLayoutIdOffset,
RawSmallInt::fromWord(static_cast<word>(id)));
}
inline RawObject RawType::name() const {
return instanceVariableAt(kNameOffset);
}
inline void RawType::setName(RawObject name) const {
instanceVariableAtPut(kNameOffset, name);
}
inline RawType::Flag RawType::flags() const {
return static_cast<Flag>(
RawSmallInt::cast(instanceVariableAt(kFlagsOffset)).value());
}
inline void RawType::setFlagsAndBuiltinBase(Flag value, LayoutId base) const {
auto raw_base = static_cast<int>(base);
DCHECK((raw_base & kBuiltinBaseMask) == raw_base,
"Builtin base LayoutId too high");
setFlags(static_cast<Flag>((value & ~kBuiltinBaseMask) | raw_base));
}
inline void RawType::setFlags(Flag value) const {
instanceVariableAtPut(kFlagsOffset, RawSmallInt::fromWord(value));
}
inline void RawType::setBuiltinBase(LayoutId base) const {
auto raw = static_cast<int>(base);
DCHECK((raw & kBuiltinBaseMask) == raw, "Builtin base LayoutId too high");
setFlags(static_cast<Flag>((flags() & ~kBuiltinBaseMask) | raw));
}
inline bool RawType::hasFlag(Flag bit) const { return (flags() & bit) != 0; }
inline LayoutId RawType::builtinBase() const {
return static_cast<LayoutId>(flags() & kBuiltinBaseMask);
}
inline bool RawType::hasCustomDict() const {
return hasFlag(RawType::Flag::kHasCustomDict);
}
inline bool RawType::hasNativeData() const {
return hasFlag(RawType::Flag::kHasNativeData);
}
inline bool RawType::isCPythonHeaptype() const {
return hasFlag(RawType::Flag::kIsCPythonHeaptype);
}
inline bool RawType::isBasetype() const {
return hasFlag(RawType::Flag::kIsBasetype);
}
inline RawObject RawType::slots() const {
return instanceVariableAt(kSlotsOffset);
}
inline void RawType::setSlots(RawObject slots) const {
instanceVariableAtPut(kSlotsOffset, slots);
}
inline RawObject RawType::abstractMethods() const {
return instanceVariableAt(kAbstractMethodsOffset);
}
inline void RawType::setAbstractMethods(RawObject methods) const {
instanceVariableAtPut(kAbstractMethodsOffset, methods);
}
inline RawObject RawType::subclasses() const {
return instanceVariableAt(kSubclassesOffset);
}
inline void RawType::setSubclasses(RawObject subclasses) const {
instanceVariableAtPut(kSubclassesOffset, subclasses);
}
inline RawObject RawType::proxy() const {
return instanceVariableAt(kProxyOffset);
}
inline void RawType::setProxy(RawObject proxy) const {
instanceVariableAtPut(kProxyOffset, proxy);
}
inline RawObject RawType::ctor() const {
return instanceVariableAt(kCtorOffset);
}
inline void RawType::setCtor(RawObject function) const {
instanceVariableAtPut(kCtorOffset, function);
}
inline RawObject RawType::qualname() const {
return instanceVariableAt(kQualnameOffset);
}
inline void RawType::setQualname(RawObject qualname) const {
instanceVariableAtPut(kQualnameOffset, qualname);
}
inline bool RawType::isBuiltin() const {
return instanceLayoutId() <= LayoutId::kLastBuiltinId;
}
inline bool RawType::isBaseExceptionSubclass() const {
LayoutId base = builtinBase();
return base >= LayoutId::kFirstException && base <= LayoutId::kLastException;
}
inline bool RawType::hasMutableDict() const { return isCPythonHeaptype(); }
// RawContext
inline RawObject RawContext::data() const {
return instanceVariableAt(kDataOffset);
}
inline void RawContext::setData(RawObject data) const {
instanceVariableAtPut(kDataOffset, data);
}
inline RawObject RawContext::prevContext() const {
return instanceVariableAt(kPrevContextOffset);
}
inline void RawContext::setPrevContext(RawObject prev_context) const {
instanceVariableAtPut(kPrevContextOffset, prev_context);
}
// RawContextVar
inline RawObject RawContextVar::defaultValue() const {
return instanceVariableAt(kDefaultValueOffset);
}
inline void RawContextVar::setDefaultValue(RawObject default_value) const {
instanceVariableAtPut(kDefaultValueOffset, default_value);
}
inline RawObject RawContextVar::name() const {
return instanceVariableAt(kNameOffset);
}
inline void RawContextVar::setName(RawObject name) const {
instanceVariableAtPut(kNameOffset, name);
}
// RawTypeProxy
inline RawObject RawTypeProxy::type() const {
return instanceVariableAt(kTypeOffset);
}
inline void RawTypeProxy::setType(RawObject type) const {
instanceVariableAtPut(kTypeOffset, type);
}
// RawDataArray
inline word RawDataArray::allocationSize(word length) {
DCHECK(length >= 0, "invalid length %ld", length);
word size = headerSize(length) + length;
return roundAllocationSize(size);
}
inline byte RawDataArray::byteAt(word index) const {
DCHECK_INDEX(index, length());
return *reinterpret_cast<byte*>(address() + index);
}
inline void RawDataArray::copyTo(byte* dst, word length) const {
DCHECK_BOUND(length, this->length());
copyToStartAt(dst, length, 0);
}
inline void RawDataArray::copyToStartAt(byte* dst, word length,
word index) const {
DCHECK_BOUND(index + length, this->length());
std::memmove(dst, reinterpret_cast<const byte*>(address() + index), length);
}
inline word RawDataArray::length() const { return headerCountOrOverflow(); }
inline uint16_t RawDataArray::uint16At(word index) const {
uint16_t result;
DCHECK_INDEX(index, length() - static_cast<word>(sizeof(result) - 1));
std::memcpy(&result, reinterpret_cast<const char*>(address() + index),
sizeof(result));
return result;
}
inline uint32_t RawDataArray::uint32At(word index) const {
uint32_t result;
DCHECK_INDEX(index, length() - static_cast<word>(sizeof(result) - 1));
std::memcpy(&result, reinterpret_cast<const char*>(address() + index),
sizeof(result));
return result;
}
inline uint64_t RawDataArray::uint64At(word index) const {
uint64_t result;
DCHECK_INDEX(index, length() - static_cast<word>(sizeof(result) - 1));
std::memcpy(&result, reinterpret_cast<const char*>(address() + index),
sizeof(result));
return result;
}
inline RawObject RawDataArray::initialize(uword address, word length,
LayoutId layout_id) {
return initializeHeader(address, /*count=*/length, /*hash=*/0, layout_id,
ObjectFormat::kData);
}
// RawLargeBytes
inline word RawLargeBytes::allocationSize(word length) {
DCHECK(length > RawSmallBytes::kMaxLength, "length %ld is too small",
(long)length);
return RawDataArray::allocationSize(length);
}
// RawMutableBytes
inline word RawMutableBytes::allocationSize(word length) {
return RawDataArray::allocationSize(length);
}
inline void RawMutableBytes::byteAtPut(word index, byte value) const {
DCHECK_INDEX(index, length());
*reinterpret_cast<byte*>(address() + index) = value;
}
inline void RawMutableBytes::uint16AtPut(word index, uint16_t value) const {
DCHECK_INDEX(index, length() - static_cast<word>(sizeof(value) - 1));
std::memcpy(reinterpret_cast<char*>(address() + index), &value,
sizeof(value));
}
inline void RawMutableBytes::uint32AtPut(word index, uint32_t value) const {
DCHECK_INDEX(index, length() - static_cast<word>(sizeof(value) - 1));
std::memcpy(reinterpret_cast<char*>(address() + index), &value,
sizeof(value));
}
// RawArray
inline RawObject RawArray::buffer() const {
return instanceVariableAt(kBufferOffset);
}
inline void RawArray::setBuffer(RawObject new_buffer) const {
DCHECK(new_buffer.isMutableBytes(), "Array must be backed by MutableBytes");
instanceVariableAtPut(kBufferOffset, new_buffer);
}
inline word RawArray::length() const {
return RawSmallInt::cast(instanceVariableAt(kLengthOffset)).value();
}
inline void RawArray::setLength(word new_length) const {
instanceVariableAtPut(kLengthOffset, RawSmallInt::fromWord(new_length));
}
inline RawObject RawArray::typecode() const {
return instanceVariableAt(kTypecodeOffset);
}
inline void RawArray::setTypecode(RawObject new_typecode) const {
instanceVariableAtPut(kTypecodeOffset, new_typecode);
}
// RawMutableTuple
inline word RawMutableTuple::allocationSize(word length) {
DCHECK(length >= 0, "invalid length %ld", length);
word size = headerSize(length) + length * kPointerSize;
return roundAllocationSize(size);
}
inline RawObject RawMutableTuple::becomeImmutable() const {
setHeader(header().withLayoutId(LayoutId::kTuple));
return *this;
}
inline void RawMutableTuple::swap(word i, word j) const {
RawObject tmp = at(i);
atPut(i, at(j));
atPut(j, tmp);
}
inline RawObject RawMutableTuple::initialize(uword address, word length) {
return initializeHeader(address, /*count=*/length, /*hash=*/0,
LayoutId::kMutableTuple, ObjectFormat::kObjects);
}
// RawTuple
inline word RawTuple::length() const { return headerCountOrOverflow(); }
inline RawObject RawTuple::at(word index) const {
DCHECK_INDEX(index, length());
return *reinterpret_cast<RawObject*>(address() + (index * kPointerSize));
}
inline void RawTuple::atPut(word index, RawObject value) const {
DCHECK_INDEX(index, length());
*reinterpret_cast<RawObject*>(address() + (index * kPointerSize)) = value;
}
// RawUserTupleBase
inline RawObject RawUserTupleBase::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawUserTupleBase::setValue(RawObject value) const {
DCHECK(value.isTuple(), "Only tuple type is permitted as a value");
instanceVariableAtPut(kValueOffset, value);
}
inline RawTuple tupleUnderlying(RawObject object) {
if (object.isTuple()) {
return RawTuple::cast(object);
}
return RawTuple::cast(object.rawCast<RawUserTupleBase>().value());
}
// RawUnicodeError
inline RawObject RawUnicodeErrorBase::encoding() const {
return instanceVariableAt(kEncodingOffset);
}
inline void RawUnicodeErrorBase::setEncoding(RawObject encoding_name) const {
DCHECK(encoding_name.isStr(), "Only string type is permitted as a value");
instanceVariableAtPut(kEncodingOffset, encoding_name);
}
inline RawObject RawUnicodeErrorBase::object() const {
return instanceVariableAt(kObjectOffset);
}
inline void RawUnicodeErrorBase::setObject(RawObject value) const {
DCHECK(value.isBytes() || value.isBytearray() || value.isStr(),
"Only str or bytes-like types are permitted as values");
instanceVariableAtPut(kObjectOffset, value);
}
inline RawObject RawUnicodeErrorBase::start() const {
return instanceVariableAt(kStartOffset);
}
inline void RawUnicodeErrorBase::setStart(RawObject index) const {
DCHECK(index.isInt(), "Only int type is permitted as a value");
instanceVariableAtPut(kStartOffset, index);
}
inline RawObject RawUnicodeErrorBase::end() const {
return instanceVariableAt(kEndOffset);
}
inline void RawUnicodeErrorBase::setEnd(RawObject index) const {
DCHECK(index.isInt(), "Only int type is permitted as a value");
instanceVariableAtPut(kEndOffset, index);
}
inline RawObject RawUnicodeErrorBase::reason() const {
return instanceVariableAt(kReasonOffset);
}
inline void RawUnicodeErrorBase::setReason(RawObject error_description) const {
DCHECK(error_description.isStr(), "Only string type is permitted as a value");
instanceVariableAtPut(kReasonOffset, error_description);
}
// RawCode
inline word RawCode::argcount() const {
return RawSmallInt::cast(instanceVariableAt(kArgcountOffset)).value();
}
inline void RawCode::setArgcount(word value) const {
instanceVariableAtPut(kArgcountOffset, RawSmallInt::fromWord(value));
}
inline word RawCode::posonlyargcount() const {
return RawSmallInt::cast(instanceVariableAt(kPosonlyargcountOffset)).value();
}
inline void RawCode::setPosonlyargcount(word value) const {
instanceVariableAtPut(kPosonlyargcountOffset, RawSmallInt::fromWord(value));
}
inline RawObject RawCode::cell2arg() const {
return instanceVariableAt(kCell2argOffset);
}
inline word RawCode::totalArgs() const {
uword f = flags();
word res = argcount() + kwonlyargcount();
if (f & kVarargs) {
res++;
}
if (f & kVarkeyargs) {
res++;
}
return res;
}
inline void RawCode::setCell2arg(RawObject value) const {
instanceVariableAtPut(kCell2argOffset, value);
}
inline RawObject RawCode::cellvars() const {
return instanceVariableAt(kCellvarsOffset);
}
inline void RawCode::setCellvars(RawObject value) const {
instanceVariableAtPut(kCellvarsOffset, value);
}
inline word RawCode::numCellvars() const {
RawObject object = cellvars();
DCHECK(object.isNoneType() || object.isTuple(), "not an object array");
if (object.isNoneType()) {
return 0;
}
return RawTuple::cast(object).length();
}
inline RawObject RawCode::code() const {
return instanceVariableAt(kCodeOffset);
}
inline void RawCode::setCode(RawObject value) const {
instanceVariableAtPut(kCodeOffset, value);
}
inline RawObject RawCode::consts() const {
return instanceVariableAt(kConstsOffset);
}
inline void RawCode::setConsts(RawObject value) const {
instanceVariableAtPut(kConstsOffset, value);
}
inline RawObject RawCode::filename() const {
return instanceVariableAt(kFilenameOffset);
}
inline void RawCode::setFilename(RawObject value) const {
instanceVariableAtPut(kFilenameOffset, value);
}
inline word RawCode::firstlineno() const {
return RawSmallInt::cast(instanceVariableAt(kFirstlinenoOffset)).value();
}
inline void RawCode::setFirstlineno(word value) const {
instanceVariableAtPut(kFirstlinenoOffset, RawSmallInt::fromWord(value));
}
inline word RawCode::flags() const {
return RawSmallInt::cast(instanceVariableAt(kFlagsOffset)).value();
}
inline void RawCode::setFlags(word value) const {
instanceVariableAtPut(kFlagsOffset, RawSmallInt::fromWord(value));
}
inline RawObject RawCode::freevars() const {
return instanceVariableAt(kFreevarsOffset);
}
inline void RawCode::setFreevars(RawObject value) const {
instanceVariableAtPut(kFreevarsOffset, value);
}
inline word RawCode::numFreevars() const {
RawObject object = freevars();
DCHECK(object.isNoneType() || object.isTuple(), "not an object array");
if (object.isNoneType()) {
return 0;
}
return RawTuple::cast(object).length();
}
inline word RawCode::kwonlyargcount() const {
return RawSmallInt::cast(instanceVariableAt(kKwonlyargcountOffset)).value();
}
inline void RawCode::setKwonlyargcount(word value) const {
instanceVariableAtPut(kKwonlyargcountOffset, RawSmallInt::fromWord(value));
}
inline RawObject RawCode::lnotab() const {
return instanceVariableAt(kLnotabOffset);
}
inline void RawCode::setLnotab(RawObject value) const {
instanceVariableAtPut(kLnotabOffset, value);
}
inline RawObject RawCode::name() const {
return instanceVariableAt(kNameOffset);
}
inline void RawCode::setName(RawObject value) const {
instanceVariableAtPut(kNameOffset, value);
}
inline RawObject RawCode::names() const {
return instanceVariableAt(kNamesOffset);
}
inline void RawCode::setNames(RawObject value) const {
instanceVariableAtPut(kNamesOffset, value);
}
inline word RawCode::nlocals() const {
return RawSmallInt::cast(instanceVariableAt(kNlocalsOffset)).value();
}
inline void RawCode::setNlocals(word value) const {
instanceVariableAtPut(kNlocalsOffset, RawSmallInt::fromWord(value));
}
inline word RawCode::stacksize() const {
return RawSmallInt::cast(instanceVariableAt(kStacksizeOffset)).value();
}
inline void RawCode::setStacksize(word value) const {
instanceVariableAtPut(kStacksizeOffset, RawSmallInt::fromWord(value));
}
inline RawObject RawCode::varnames() const {
return instanceVariableAt(kVarnamesOffset);
}
inline void RawCode::setVarnames(RawObject value) const {
instanceVariableAtPut(kVarnamesOffset, value);
}
inline bool RawCode::isAsyncGenerator() const {
return flags() & RawFunction::Flags::kAsyncGenerator;
}
inline bool RawCode::isGeneratorLike() const {
return flags() &
(Flags::kCoroutine | Flags::kGenerator | Flags::kAsyncGenerator);
}
inline bool RawCode::hasFreevarsOrCellvars() const {
return !(flags() & Flags::kNofree);
}
inline bool RawCode::hasOptimizedAndNewlocals() const {
return (flags() & (Flags::kOptimized | Flags::kNewlocals)) ==
(Flags::kOptimized | Flags::kNewlocals);
}
inline bool RawCode::hasOptimizedOrNewlocals() const {
return flags() & (Flags::kOptimized | Flags::kNewlocals);
}
inline bool RawCode::isNative() const { return code().isInt(); }
inline void* RawCode::intrinsic() const {
return RawSmallInt::cast(instanceVariableAt(kIntrinsicOffset))
.asAlignedCPtr();
}
inline void RawCode::setIntrinsic(void* fp) const {
instanceVariableAtPut(kIntrinsicOffset, RawSmallInt::fromAlignedCPtr(fp));
}
// RawLargeInt
inline word RawLargeInt::asWord() const {
DCHECK(numDigits() == 1, "RawLargeInt cannot fit in a word");
return static_cast<word>(digitAt(0));
}
inline void* RawLargeInt::asCPtr() const {
DCHECK(numDigits() == 1, "Large integer cannot fit in a pointer");
DCHECK(isPositive(), "Cannot cast a negative value to a C pointer");
return reinterpret_cast<void*>(asWord());
}
template <typename T>
if_signed_t<T, OptInt<T>> RawLargeInt::asInt() const {
static_assert(sizeof(T) <= sizeof(word), "T must not be larger than word");
if (numDigits() > 1) {
auto const high_digit = static_cast<word>(digitAt(numDigits() - 1));
return high_digit < 0 ? OptInt<T>::underflow() : OptInt<T>::overflow();
}
if (numDigits() == 1) {
auto const value = asWord();
if (value <= std::numeric_limits<T>::max() &&
value >= std::numeric_limits<T>::min()) {
return OptInt<T>::valid(value);
}
}
return OptInt<T>::overflow();
}
template <typename T>
if_unsigned_t<T, OptInt<T>> RawLargeInt::asInt() const {
static_assert(sizeof(T) <= sizeof(word), "T must not be larger than word");
if (isNegative()) return OptInt<T>::underflow();
if (static_cast<size_t>(bitLength()) > sizeof(T) * kBitsPerByte) {
return OptInt<T>::overflow();
}
// No T accepted by this function needs more than one digit.
return OptInt<T>::valid(digitAt(0));
}
inline bool RawLargeInt::isEven() const {
word lowest_digit = digitAt(0);
return (lowest_digit & 1) == 0;
}
inline bool RawLargeInt::isNegative() const {
word highest_digit = digitAt(numDigits() - 1);
return highest_digit < 0;
}
inline bool RawLargeInt::isPositive() const {
word highest_digit = digitAt(numDigits() - 1);
return highest_digit >= 0;
}
inline uword RawLargeInt::digitAt(word index) const {
DCHECK_INDEX(index, numDigits());
return reinterpret_cast<uword*>(address() + kValueOffset)[index];
}
inline void RawLargeInt::digitAtPut(word index, uword digit) const {
DCHECK_INDEX(index, numDigits());
reinterpret_cast<uword*>(address() + kValueOffset)[index] = digit;
}
inline word RawLargeInt::numDigits() const {
return headerCountOrOverflow() / kWordSize;
}
inline word RawLargeInt::allocationSize(word num_digits) {
word size = headerSize(num_digits * kWordSize) + num_digits * kWordSize;
return roundAllocationSize(size);
}
inline RawObject RawLargeInt::initialize(uword address, word num_digits) {
return initializeHeader(address, num_digits * kWordSize, 0,
LayoutId::kLargeInt, ObjectFormat::kData);
}
// RawFloat
inline word RawFloat::allocationSize() {
return roundAllocationSize(RawHeader::kSize + kSize);
}
inline double RawFloat::value() const {
return *reinterpret_cast<double*>(address() + kValueOffset);
}
inline RawObject RawFloat::initialize(uword address, double value) {
RawHeapObject raw =
initializeHeader(address, /*count=*/RawFloat::kSize,
/*hash=*/0, LayoutId::kFloat, ObjectFormat::kData);
*reinterpret_cast<double*>(raw.address() + kValueOffset) = value;
return raw;
}
// RawComplex
inline word RawComplex::allocationSize() {
return roundAllocationSize(RawHeader::kSize + kSize);
}
inline double RawComplex::real() const {
return *reinterpret_cast<double*>(address() + kRealOffset);
}
inline double RawComplex::imag() const {
return *reinterpret_cast<double*>(address() + kImagOffset);
}
inline RawObject RawComplex::initialize(uword address, double real,
double imag) {
RawHeapObject raw =
initializeHeader(address, /*count=*/RawComplex::kSize,
/*hash=*/0, LayoutId::kComplex, ObjectFormat::kData);
*reinterpret_cast<double*>(raw.address() + kRealOffset) = real;
*reinterpret_cast<double*>(raw.address() + kImagOffset) = imag;
return raw;
}
// RawFrameProxy
inline RawObject RawFrameProxy::back() const {
return instanceVariableAt(kBackOffset);
}
inline void RawFrameProxy::setBack(RawObject back) const {
instanceVariableAtPut(kBackOffset, back);
}
inline RawObject RawFrameProxy::function() const {
return instanceVariableAt(kFunctionOffset);
}
inline void RawFrameProxy::setFunction(RawObject function) const {
instanceVariableAtPut(kFunctionOffset, function);
}
inline RawObject RawFrameProxy::lasti() const {
return instanceVariableAt(kLastiOffset);
}
inline void RawFrameProxy::setLasti(RawObject lasti) const {
instanceVariableAtPut(kLastiOffset, lasti);
}
inline RawObject RawFrameProxy::locals() const {
return instanceVariableAt(kLocalsOffset);
}
inline void RawFrameProxy::setLocals(RawObject locals) const {
instanceVariableAtPut(kLocalsOffset, locals);
}
// RawUserBytesBase
inline RawObject RawUserBytesBase::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawUserBytesBase::setValue(RawObject value) const {
DCHECK(value.isBytes(), "Only bytes type is permitted as a value.");
instanceVariableAtPut(kValueOffset, value);
}
inline RawBytes bytesUnderlying(RawObject object) {
if (object.isBytes()) {
return RawBytes::cast(object);
}
return RawBytes::cast(object.rawCast<RawUserBytesBase>().value());
}
// RawUserComplexBase
inline RawObject RawUserComplexBase::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawUserComplexBase::setValue(RawObject value) const {
DCHECK(value.isComplex(), "Only complex type is permitted as a value.");
instanceVariableAtPut(kValueOffset, value);
}
inline RawComplex complexUnderlying(RawObject object) {
if (object.isComplex()) {
return RawComplex::cast(object);
}
return RawComplex::cast(object.rawCast<RawUserComplexBase>().value());
}
// RawUserFloatBase
inline RawObject RawUserFloatBase::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawUserFloatBase::setValue(RawObject value) const {
DCHECK(value.isFloat(), "Only float type is permitted as a value");
instanceVariableAtPut(kValueOffset, value);
}
inline RawFloat floatUnderlying(RawObject object) {
if (object.isFloat()) {
return RawFloat::cast(object);
}
return RawFloat::cast(object.rawCast<RawUserFloatBase>().value());
}
// RawUserIntBase
inline RawObject RawUserIntBase::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawUserIntBase::setValue(RawObject value) const {
DCHECK(value.isSmallInt() || value.isLargeInt(),
"Only int types, not bool, are permitted as a value.");
instanceVariableAtPut(kValueOffset, value);
}
inline RawInt intUnderlying(RawObject object) {
if (object.isInt()) {
return RawInt::cast(object);
}
return RawInt::cast(object.rawCast<RawUserIntBase>().value());
}
// RawUserStrBase
inline RawObject RawUserStrBase::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawUserStrBase::setValue(RawObject value) const {
DCHECK(value.isStr(), "Only str type is permitted as a value.");
instanceVariableAtPut(kValueOffset, value);
}
inline RawStr strUnderlying(RawObject object) {
if (object.isStr()) {
return RawStr::cast(object);
}
return RawStr::cast(object.rawCast<RawUserStrBase>().value());
}
// RawRange
inline RawObject RawRange::start() const {
return instanceVariableAt(kStartOffset);
}
inline void RawRange::setStart(RawObject value) const {
instanceVariableAtPut(kStartOffset, value);
}
inline RawObject RawRange::stop() const {
return instanceVariableAt(kStopOffset);
}
inline void RawRange::setStop(RawObject value) const {
instanceVariableAtPut(kStopOffset, value);
}
inline RawObject RawRange::step() const {
return instanceVariableAt(kStepOffset);
}
inline void RawRange::setStep(RawObject value) const {
instanceVariableAtPut(kStepOffset, value);
}
// RawPointer
inline word RawPointer::allocationSize() {
return roundAllocationSize(RawHeader::kSize + kSize);
}
inline void* RawPointer::cptr() const {
return *reinterpret_cast<void**>(address() + kCPtrOffset);
}
inline void RawPointer::setCPtr(void* new_cptr) const {
*reinterpret_cast<void**>(address() + kCPtrOffset) = new_cptr;
}
inline word RawPointer::length() const {
return *reinterpret_cast<word*>(address() + kLengthOffset);
}
inline void RawPointer::setLength(word new_length) const {
*reinterpret_cast<word*>(address() + kLengthOffset) = new_length;
}
inline RawObject RawPointer::initialize(uword address, void* cptr,
word length) {
RawHeapObject raw =
initializeHeader(address, /*count=*/RawPointer::kSize,
/*hash=*/0, LayoutId::kPointer, ObjectFormat::kData);
*reinterpret_cast<void**>(raw.address() + kCPtrOffset) = cptr;
*reinterpret_cast<word*>(raw.address() + kLengthOffset) = length;
return raw;
}
// RawProperty
inline RawObject RawProperty::getter() const {
return instanceVariableAt(kGetterOffset);
}
inline void RawProperty::setGetter(RawObject function) const {
instanceVariableAtPut(kGetterOffset, function);
}
inline RawObject RawProperty::setter() const {
return instanceVariableAt(kSetterOffset);
}
inline void RawProperty::setSetter(RawObject function) const {
instanceVariableAtPut(kSetterOffset, function);
}
inline RawObject RawProperty::deleter() const {
return instanceVariableAt(kDeleterOffset);
}
inline void RawProperty::setDeleter(RawObject function) const {
instanceVariableAtPut(kDeleterOffset, function);
}
// RawSlice
inline RawObject RawSlice::start() const {
return instanceVariableAt(kStartOffset);
}
inline void RawSlice::setStart(RawObject value) const {
instanceVariableAtPut(kStartOffset, value);
}
inline RawObject RawSlice::stop() const {
return instanceVariableAt(kStopOffset);
}
inline void RawSlice::setStop(RawObject value) const {
instanceVariableAtPut(kStopOffset, value);
}
inline RawObject RawSlice::step() const {
return instanceVariableAt(kStepOffset);
}
inline void RawSlice::setStep(RawObject value) const {
instanceVariableAtPut(kStepOffset, value);
}
// RawSlotDescriptor
inline RawObject RawSlotDescriptor::type() const {
return RawSlotDescriptor::instanceVariableAt(kTypeOffset);
}
inline void RawSlotDescriptor::setType(RawObject type) const {
instanceVariableAtPut(kTypeOffset, type);
}
inline RawObject RawSlotDescriptor::name() const {
return RawSlotDescriptor::instanceVariableAt(kNameOffset);
}
inline void RawSlotDescriptor::setName(RawObject name) const {
instanceVariableAtPut(kNameOffset, name);
}
inline word RawSlotDescriptor::offset() const {
return RawSmallInt::cast(RawSlotDescriptor::instanceVariableAt(kOffsetOffset))
.value();
}
inline void RawSlotDescriptor::setOffset(word offset) const {
instanceVariableAtPut(kOffsetOffset, RawSmallInt::fromWord(offset));
}
// RawStaticMethod
inline RawObject RawStaticMethod::function() const {
return instanceVariableAt(kFunctionOffset);
}
inline void RawStaticMethod::setFunction(RawObject function) const {
instanceVariableAtPut(kFunctionOffset, function);
}
// RawBytearray
inline byte RawBytearray::byteAt(word index) const {
DCHECK_INDEX(index, numItems());
return RawMutableBytes::cast(items()).byteAt(index);
}
inline void RawBytearray::byteAtPut(word index, byte value) const {
DCHECK_INDEX(index, numItems());
RawMutableBytes::cast(items()).byteAtPut(index, value);
}
inline void RawBytearray::copyTo(byte* dst, word length) const {
DCHECK_BOUND(length, numItems());
RawMutableBytes::cast(items()).copyTo(dst, length);
}
inline word RawBytearray::numItems() const {
return RawSmallInt::cast(instanceVariableAt(kNumItemsOffset)).value();
}
inline void RawBytearray::setNumItems(word num_bytes) const {
DCHECK_BOUND(num_bytes, capacity());
instanceVariableAtPut(kNumItemsOffset, RawSmallInt::fromWord(num_bytes));
}
inline RawObject RawBytearray::items() const {
return instanceVariableAt(kItemsOffset);
}
inline void RawBytearray::setItems(RawObject new_items) const {
DCHECK(new_items.isMutableBytes(), "backed by mutable bytes");
instanceVariableAtPut(kItemsOffset, new_items);
}
inline word RawBytearray::capacity() const {
return RawMutableBytes::cast(items()).length();
}
// RawStrArray
inline RawObject RawStrArray::items() const {
return instanceVariableAt(kItemsOffset);
}
inline void RawStrArray::setItems(RawObject new_items) const {
DCHECK(new_items.isMutableBytes(), "StrArray must be backed by MutableBytes");
instanceVariableAtPut(kItemsOffset, new_items);
}
inline word RawStrArray::numItems() const {
return RawSmallInt::cast(instanceVariableAt(kNumItemsOffset)).value();
}
inline void RawStrArray::setNumItems(word num_items) const {
DCHECK_BOUND(num_items, capacity());
instanceVariableAtPut(kNumItemsOffset, RawSmallInt::fromWord(num_items));
}
inline void RawStrArray::copyTo(byte* dst, word length) const {
DCHECK_BOUND(length, numItems());
RawMutableBytes::cast(items()).copyTo(dst, length);
}
inline word RawStrArray::capacity() const {
return RawMutableBytes::cast(items()).length();
}
// RawDeque
inline RawObject RawDeque::at(word index) const {
DCHECK_INDEX(index, capacity());
return RawTuple::cast(items()).at(index);
}
inline void RawDeque::atPut(word index, RawObject value) const {
DCHECK_INDEX(index, capacity());
RawTuple::cast(items()).atPut(index, value);
}
inline word RawDeque::capacity() const {
RawObject raw_items = items();
if (raw_items == RawSmallInt::fromWord(0)) return 0;
return RawTuple::cast(raw_items).length();
}
inline void RawDeque::clear() const {
if (numItems() == 0) return;
RawMutableTuple::cast(items()).fill(RawNoneType::object());
setLeft(0);
setNumItems(0);
}
inline RawObject RawDeque::items() const {
return instanceVariableAt(kItemsOffset);
}
inline void RawDeque::setItems(RawObject new_items) const {
instanceVariableAtPut(kItemsOffset, new_items);
}
inline word RawDeque::left() const {
return RawSmallInt::cast(instanceVariableAt(kLeftOffset)).value();
}
inline void RawDeque::setLeft(word left) const {
instanceVariableAtPut(kLeftOffset, RawSmallInt::fromWord(left));
}
inline word RawDeque::numItems() const {
return RawSmallInt::cast(instanceVariableAt(kNumItemsOffset)).value();
}
inline void RawDeque::setNumItems(word num_items) const {
instanceVariableAtPut(kNumItemsOffset, RawSmallInt::fromWord(num_items));
}
inline RawObject RawDeque::maxlen() const {
return instanceVariableAt(kMaxlenOffset);
}
inline void RawDeque::setMaxlen(RawObject maxlen) const {
instanceVariableAtPut(kMaxlenOffset, maxlen);
}
inline word RawDeque::state() const {
return RawSmallInt::cast(instanceVariableAt(kStateOffset)).value();
}
inline void RawDeque::setState(word state) const {
instanceVariableAtPut(kStateOffset, RawSmallInt::fromWord(state));
}
// RawDequeIterator
inline word RawDequeIterator::state() const {
return RawSmallInt::cast(instanceVariableAt(kStateOffset)).value();
}
inline void RawDequeIterator::setState(word state) const {
instanceVariableAtPut(kStateOffset, RawSmallInt::fromWord(state));
}
// RawDequeReverseIterator
inline word RawDequeReverseIterator::state() const {
return RawSmallInt::cast(instanceVariableAt(kStateOffset)).value();
}
inline void RawDequeReverseIterator::setState(word state) const {
instanceVariableAtPut(kStateOffset, RawSmallInt::fromWord(state));
}
// RawDict
inline word RawDict::numItems() const {
return RawSmallInt::cast(instanceVariableAt(kNumItemsOffset)).value();
}
inline void RawDict::setNumItems(word num_items) const {
instanceVariableAtPut(kNumItemsOffset, RawSmallInt::fromWord(num_items));
}
inline RawObject RawDict::data() const {
return instanceVariableAt(kDataOffset);
}
inline void RawDict::setData(RawObject data) const {
instanceVariableAtPut(kDataOffset, data);
}
inline RawObject RawDict::indices() const {
return instanceVariableAt(kIndicesOffset);
}
inline void RawDict::setIndices(RawObject index_data) const {
instanceVariableAtPut(kIndicesOffset, index_data);
}
inline word RawDict::firstEmptyItemIndex() const {
return RawSmallInt::cast(instanceVariableAt(kFirstEmptyItemIndexOffset))
.value();
}
inline void RawDict::setFirstEmptyItemIndex(word first_empty_item_index) const {
instanceVariableAtPut(kFirstEmptyItemIndexOffset,
RawSmallInt::fromWord(first_empty_item_index));
}
inline word RawDict::numIndices() const {
RawObject indices_obj = indices();
if (indices_obj == RawSmallInt::fromWord(0)) return 0;
return RawMutableBytes::cast(indices_obj).length() >> 2;
}
// RawDictIteratorBase
inline word RawDictIteratorBase::numFound() const {
return RawSmallInt::cast(instanceVariableAt(kNumFoundOffset)).value();
}
inline void RawDictIteratorBase::setNumFound(word num_found) const {
instanceVariableAtPut(kNumFoundOffset, RawSmallInt::fromWord(num_found));
}
// RawDictViewBase
inline RawObject RawDictViewBase::dict() const {
return instanceVariableAt(kDictOffset);
}
inline void RawDictViewBase::setDict(RawObject dict) const {
instanceVariableAtPut(kDictOffset, dict);
}
// RawFunction
inline RawObject RawFunction::annotations() const {
return instanceVariableAt(kAnnotationsOffset);
}
inline void RawFunction::setAnnotations(RawObject annotations) const {
instanceVariableAtPut(kAnnotationsOffset, annotations);
}
inline word RawFunction::argcount() const {
return RawSmallInt::cast(instanceVariableAt(kArgcountOffset)).value();
}
inline void RawFunction::setArgcount(word value) const {
instanceVariableAtPut(kArgcountOffset, RawSmallInt::fromWord(value));
}
inline RawObject RawFunction::closure() const {
return instanceVariableAt(kClosureOffset);
}
inline void RawFunction::setClosure(RawObject closure) const {
instanceVariableAtPut(kClosureOffset, closure);
}
inline RawObject RawFunction::code() const {
return instanceVariableAt(kCodeOffset);
}
inline void RawFunction::setCode(RawObject code) const {
instanceVariableAtPut(kCodeOffset, code);
}
inline RawObject RawFunction::defaults() const {
return instanceVariableAt(kDefaultsOffset);
}
inline void RawFunction::setDefaults(RawObject defaults) const {
instanceVariableAtPut(kDefaultsOffset, defaults);
}
inline bool RawFunction::hasDefaults() const {
return !defaults().isNoneType();
}
inline RawObject RawFunction::doc() const {
return instanceVariableAt(kDocOffset);
}
inline void RawFunction::setDoc(RawObject doc) const {
instanceVariableAtPut(kDocOffset, doc);
}
inline RawFunction::Entry RawFunction::entry() const {
RawObject object = instanceVariableAt(kEntryOffset);
return reinterpret_cast<Entry>(RawSmallInt::cast(object).asAlignedCPtr());
}
inline void RawFunction::setEntry(RawFunction::Entry thunk) const {
RawObject object =
RawSmallInt::fromAlignedCPtr(reinterpret_cast<void*>(thunk));
instanceVariableAtPut(kEntryOffset, object);
}
inline RawFunction::Entry RawFunction::entryKw() const {
RawObject object = instanceVariableAt(kEntryKwOffset);
return reinterpret_cast<Entry>(RawSmallInt::cast(object).asAlignedCPtr());
}
inline void RawFunction::setEntryKw(RawFunction::Entry thunk) const {
RawObject object =
RawSmallInt::fromAlignedCPtr(reinterpret_cast<void*>(thunk));
instanceVariableAtPut(kEntryKwOffset, object);
}
inline RawFunction::Entry RawFunction::entryEx() const {
RawObject object = instanceVariableAt(kEntryExOffset);
return reinterpret_cast<Entry>(RawSmallInt::cast(object).asAlignedCPtr());
}
inline void RawFunction::setEntryEx(RawFunction::Entry thunk) const {
RawObject object =
RawSmallInt::fromAlignedCPtr(reinterpret_cast<void*>(thunk));
instanceVariableAtPut(kEntryExOffset, object);
}
inline void* RawFunction::entryAsm() const {
RawObject object = instanceVariableAt(kEntryAsmOffset);
return reinterpret_cast<void*>(RawSmallInt::cast(object).asAlignedCPtr());
}
inline void RawFunction::setEntryAsm(void* thunk) const {
RawObject object = RawSmallInt::fromAlignedCPtr(thunk);
instanceVariableAtPut(kEntryAsmOffset, object);
}
inline word RawFunction::flags() const {
return RawSmallInt::cast(instanceVariableAt(kFlagsOffset)).value();
}
inline void RawFunction::setFlags(word flags) const {
instanceVariableAtPut(kFlagsOffset, RawSmallInt::fromWord(flags));
}
inline bool RawFunction::isAsyncGenerator() const {
return flags() & Flags::kAsyncGenerator;
}
inline bool RawFunction::isCoroutine() const {
return flags() & Flags::kCoroutine;
}
inline bool RawFunction::isExtension() const {
return flags() & Flags::kExtension;
}
inline bool RawFunction::isCompiled() const {
return flags() & Flags::kCompiled;
}
inline bool RawFunction::isGeneratorLike() const {
return flags() &
(Flags::kCoroutine | Flags::kGenerator | Flags::kAsyncGenerator);
}
inline bool RawFunction::hasFreevarsOrCellvars() const {
return !(flags() & Flags::kNofree);
}
inline bool RawFunction::isGenerator() const {
return flags() & Flags::kGenerator;
}
inline bool RawFunction::isIterableCoroutine() const {
return flags() & Flags::kIterableCoroutine;
}
inline bool RawFunction::hasOptimizedOrNewlocals() const {
return flags() & (Flags::kOptimized | Flags::kNewlocals);
}
inline bool RawFunction::hasSimpleCall() const {
return flags() & Flags::kSimpleCall;
}
inline bool RawFunction::hasVarargs() const {
return flags() & Flags::kVarargs;
}
inline bool RawFunction::hasVarkeyargs() const {
return flags() & Flags::kVarkeyargs;
}
inline bool RawFunction::hasVarargsOrVarkeyargs() const {
return flags() & (Flags::kVarargs | Flags::kVarkeyargs);
}
inline bool RawFunction::isInterpreted() const {
return flags() & Flags::kInterpreted;
}
inline void RawFunction::setIsInterpreted(bool interpreted) const {
setFlags(interpreted ? flags() | Flags::kInterpreted
: flags() & ~Flags::kInterpreted);
}
inline void* RawFunction::intrinsic() const {
return RawSmallInt::cast(instanceVariableAt(kIntrinsicOffset))
.asAlignedCPtr();
}
inline void RawFunction::setIntrinsic(void* fp) const {
instanceVariableAtPut(kIntrinsicOffset, RawSmallInt::fromAlignedCPtr(fp));
}
inline RawObject RawFunction::kwDefaults() const {
return instanceVariableAt(kKwDefaultsOffset);
}
inline void RawFunction::setKwDefaults(RawObject kw_defaults) const {
instanceVariableAtPut(kKwDefaultsOffset, kw_defaults);
}
inline RawObject RawFunction::moduleName() const {
return instanceVariableAt(kModuleNameOffset);
}
inline void RawFunction::setModuleName(RawObject module_name) const {
DCHECK(module_name.isStr(), "module_name is expected to be a Str");
instanceVariableAtPut(kModuleNameOffset, module_name);
}
inline RawObject RawFunction::moduleObject() const {
return instanceVariableAt(kModuleObjectOffset);
}
inline void RawFunction::setModuleObject(RawObject module_object) const {
instanceVariableAtPut(kModuleObjectOffset, module_object);
}
inline RawObject RawFunction::name() const {
return instanceVariableAt(kNameOffset);
}
inline void RawFunction::setName(RawObject name) const {
instanceVariableAtPut(kNameOffset, name);
}
inline RawObject RawFunction::qualname() const {
return instanceVariableAt(kQualnameOffset);
}
inline void RawFunction::setQualname(RawObject qualname) const {
instanceVariableAtPut(kQualnameOffset, qualname);
}
inline word RawFunction::totalArgs() const {
return RawSmallInt::cast(instanceVariableAt(kTotalArgsOffset)).value();
}
inline void RawFunction::setTotalArgs(word value) const {
instanceVariableAtPut(kTotalArgsOffset, RawSmallInt::fromWord(value));
}
inline word RawFunction::totalVars() const {
return RawSmallInt::cast(instanceVariableAt(kTotalVarsOffset)).value();
}
inline void RawFunction::setTotalVars(word value) const {
instanceVariableAtPut(kTotalVarsOffset, RawSmallInt::fromWord(value));
}
inline word RawFunction::totalLocals() const {
return totalArgs() + totalVars();
}
inline RawObject RawFunction::stacksizeOrBuiltin() const {
return instanceVariableAt(kStacksizeOrBuiltinOffset);
}
inline void RawFunction::setStacksizeOrBuiltin(
RawObject stacksize_or_builtin) const {
instanceVariableAtPut(kStacksizeOrBuiltinOffset, stacksize_or_builtin);
}
inline RawObject RawFunction::rewrittenBytecode() const {
return instanceVariableAt(kRewrittenBytecodeOffset);
}
inline void RawFunction::setRewrittenBytecode(
RawObject rewritten_bytecode) const {
instanceVariableAtPut(kRewrittenBytecodeOffset, rewritten_bytecode);
}
inline RawObject RawFunction::caches() const {
return instanceVariableAt(kCachesOffset);
}
inline void RawFunction::setCaches(RawObject cache) const {
instanceVariableAtPut(kCachesOffset, cache);
}
inline RawObject RawFunction::dict() const {
return instanceVariableAt(kDictOffset);
}
inline void RawFunction::setDict(RawObject dict) const {
instanceVariableAtPut(kDictOffset, dict);
}
// RawInstance
inline word RawInstance::allocationSize(word num_attr) {
DCHECK(num_attr >= 0, "invalid number of attributes %ld", num_attr);
word size = headerSize(num_attr) + num_attr * kPointerSize;
return roundAllocationSize(size);
}
// RawList
inline RawObject RawList::items() const {
return instanceVariableAt(kItemsOffset);
}
inline void RawList::setItems(RawObject new_items) const {
instanceVariableAtPut(kItemsOffset, new_items);
}
inline word RawList::capacity() const {
return RawTuple::cast(items()).length();
}
inline word RawList::numItems() const {
return RawSmallInt::cast(instanceVariableAt(kNumItemsOffset)).value();
}
inline void RawList::setNumItems(word num_items) const {
instanceVariableAtPut(kNumItemsOffset, RawSmallInt::fromWord(num_items));
}
inline void RawList::clearFrom(word idx) const {
if (numItems() == 0) return;
DCHECK_INDEX(idx, numItems());
std::memset(reinterpret_cast<byte*>(RawTuple::cast(items()).address()) +
idx * kPointerSize,
-1, (numItems() - idx) * kWordSize);
setNumItems(idx);
}
inline void RawList::atPut(word index, RawObject value) const {
DCHECK_INDEX(index, numItems());
RawObject items = instanceVariableAt(kItemsOffset);
RawTuple::cast(items).atPut(index, value);
}
inline RawObject RawList::at(word index) const {
DCHECK_INDEX(index, numItems());
return RawTuple::cast(items()).at(index);
}
inline void RawList::swap(word i, word j) const {
DCHECK_INDEX(i, numItems());
DCHECK_INDEX(j, numItems());
RawMutableTuple::cast(items()).swap(i, j);
}
// RawMappingProxy
inline RawObject RawMappingProxy::mapping() const {
return RawMappingProxy::instanceVariableAt(kMappingOffset);
}
inline void RawMappingProxy::setMapping(RawObject mapping) const {
instanceVariableAtPut(kMappingOffset, mapping);
}
// RawMemoryView
inline RawObject RawMemoryView::buffer() const {
return RawMemoryView::instanceVariableAt(kBufferOffset);
}
inline void RawMemoryView::setBuffer(RawObject buffer) const {
instanceVariableAtPut(kBufferOffset, buffer);
}
inline RawObject RawMemoryView::format() const {
return RawMemoryView::instanceVariableAt(kFormatOffset);
}
inline void RawMemoryView::setFormat(RawObject format) const {
instanceVariableAtPut(kFormatOffset, format);
}
inline bool RawMemoryView::readOnly() const {
return RawBool::cast(instanceVariableAt(kReadOnlyOffset)).value();
}
inline void RawMemoryView::setReadOnly(bool read_only) const {
instanceVariableAtPut(kReadOnlyOffset, RawBool::fromBool(read_only));
}
inline word RawMemoryView::length() const {
return RawSmallInt::cast(instanceVariableAt(kLengthOffset)).value();
}
inline void RawMemoryView::setLength(word length) const {
instanceVariableAtPut(kLengthOffset, RawSmallInt::fromWord(length));
}
inline RawObject RawMemoryView::object() const {
return RawMemoryView::instanceVariableAt(kObjectOffset);
}
inline void RawMemoryView::setObject(RawObject object) const {
instanceVariableAtPut(kObjectOffset, object);
}
inline RawObject RawMemoryView::ndim() const {
return RawMemoryView::instanceVariableAt(kNdimOffset);
}
inline void RawMemoryView::setNdim(RawObject ndim) const {
instanceVariableAtPut(kNdimOffset, ndim);
}
inline RawObject RawMemoryView::shape() const {
return RawMemoryView::instanceVariableAt(kShapeOffset);
}
inline void RawMemoryView::setShape(RawObject shape) const {
instanceVariableAtPut(kShapeOffset, shape);
}
inline word RawMemoryView::start() const {
return RawSmallInt::cast(instanceVariableAt(kStartOffset)).value();
}
inline void RawMemoryView::setStart(word start) const {
instanceVariableAtPut(kStartOffset, RawSmallInt::fromWord(start));
}
inline RawObject RawMemoryView::strides() const {
return RawMemoryView::instanceVariableAt(kStridesOffset);
}
inline void RawMemoryView::setStrides(RawObject strides) const {
instanceVariableAtPut(kStridesOffset, strides);
}
// RawMmap
inline word RawMmap::access() const {
return RawSmallInt::cast(instanceVariableAt(kAccessOffset)).value();
}
inline void RawMmap::setAccess(word new_access) const {
instanceVariableAtPut(kAccessOffset, RawSmallInt::fromWord(new_access));
}
inline RawObject RawMmap::data() const {
return instanceVariableAt(kDataOffset);
}
inline void RawMmap::setData(RawObject new_data) const {
instanceVariableAtPut(kDataOffset, new_data);
}
inline RawObject RawMmap::fd() const { return instanceVariableAt(kFdOffset); }
inline void RawMmap::setFd(RawObject new_fd) const {
instanceVariableAtPut(kFdOffset, new_fd);
}
inline bool RawMmap::isReadable() const {
return RawSmallInt::cast(instanceVariableAt(kAccessOffset)).value() &
Property::kReadable;
}
inline void RawMmap::setReadable() const {
word mask = RawSmallInt::cast(instanceVariableAt(kAccessOffset)).value();
instanceVariableAtPut(kAccessOffset,
RawSmallInt::fromWord(mask | Property::kReadable));
}
inline bool RawMmap::isWritable() const {
return RawSmallInt::cast(instanceVariableAt(kAccessOffset)).value() &
Property::kWritable;
}
inline void RawMmap::setWritable() const {
word mask = RawSmallInt::cast(instanceVariableAt(kAccessOffset)).value();
instanceVariableAtPut(kAccessOffset,
RawSmallInt::fromWord(mask | Property::kWritable));
}
inline bool RawMmap::isCopyOnWrite() const {
return RawSmallInt::cast(instanceVariableAt(kAccessOffset)).value() &
Property::kCopyOnWrite;
}
inline void RawMmap::setCopyOnWrite() const {
word mask = RawSmallInt::cast(instanceVariableAt(kAccessOffset)).value();
instanceVariableAtPut(kAccessOffset,
RawSmallInt::fromWord(mask | Property::kCopyOnWrite));
}
// RawModule
inline RawObject RawModule::name() const {
return instanceVariableAt(kNameOffset);
}
inline void RawModule::setName(RawObject name) const {
instanceVariableAtPut(kNameOffset, name);
}
inline RawObject RawModule::def() const {
return instanceVariableAt(kDefOffset);
}
inline bool RawModule::hasDef() const {
RawObject def_value = def();
return def_value.isInt() && RawInt::cast(def_value).asCPtr() != nullptr;
}
inline void RawModule::setDef(RawObject def) const {
instanceVariableAtPut(kDefOffset, def);
}
inline RawObject RawModule::state() const {
return instanceVariableAt(kStateOffset);
}
inline bool RawModule::hasState() const {
RawObject state_value = state();
return state_value.isInt() && RawInt::cast(state_value).asCPtr() != nullptr;
}
inline void RawModule::setState(RawObject state) const {
instanceVariableAtPut(kStateOffset, state);
}
inline RawObject RawModule::moduleProxy() const {
return instanceVariableAt(kModuleProxyOffset);
}
inline void RawModule::setModuleProxy(RawObject module_proxy) const {
instanceVariableAtPut(kModuleProxyOffset, module_proxy);
}
inline word RawModule::id() const {
word index = header().hashCode();
DCHECK(index != RawHeader::kUninitializedHash,
"Module header hash field should contain a valid ID");
return index;
}
inline void RawModule::setId(word id) const {
DCHECK(static_cast<word>(id & RawHeader::kHashCodeMask) == id,
"Module ID %ld doesn't fit in hash code", id);
setHeader(header().withHashCode(id));
}
// RawModuleProxy
inline RawObject RawModuleProxy::module() const {
return instanceVariableAt(kModuleOffset);
}
inline void RawModuleProxy::setModule(RawObject module) const {
instanceVariableAtPut(kModuleOffset, module);
}
// RawStr
inline byte RawStr::byteAt(word index) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).byteAt(index);
}
return RawLargeStr::cast(*this).byteAt(index);
}
inline int32_t RawStr::codePointAt(word index, word* char_length) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).codePointAt(index, char_length);
}
return RawLargeStr::cast(*this).codePointAt(index, char_length);
}
inline word RawStr::length() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).length();
}
return RawLargeStr::cast(*this).length();
}
inline word RawStr::compare(RawStr that) const {
if (*this == that) {
return 0;
}
if (isImmediateObjectNotSmallInt()) {
if (that.isSmallStr()) {
word result = __builtin_bswap64(this->raw() & ~uword{0xFF}) -
__builtin_bswap64(that.raw() & ~uword{0xFF});
return LIKELY(result != 0)
? result
: this->length() - RawSmallStr::cast(that).length();
}
return RawSmallStr::cast(*this).compare(that);
}
if (that.isImmediateObjectNotSmallInt()) {
return -RawSmallStr::cast(that).compare(*this);
}
return RawLargeStr::cast(*this).compare(RawLargeStr::cast(that));
}
inline void RawStr::copyTo(byte* dst, word length) const {
if (isImmediateObjectNotSmallInt()) {
RawSmallStr::cast(*this).copyTo(dst, length);
return;
}
return RawLargeStr::cast(*this).copyTo(dst, length);
}
inline void RawStr::copyToStartAt(byte* dst, word char_length,
word char_start) const {
if (isImmediateObjectNotSmallInt()) {
RawSmallStr::cast(*this).copyToStartAt(dst, char_length, char_start);
return;
}
return RawLargeStr::cast(*this).copyToStartAt(dst, char_length, char_start);
}
inline word RawStr::codePointLength() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).codePointLength();
}
return RawLargeStr::cast(*this).codePointLength();
}
inline RawStr RawStr::empty() { return RawSmallStr::empty().rawCast<RawStr>(); }
inline bool RawStr::equals(RawStr that) const {
if (*this == that) return true;
if (isImmediateObjectNotSmallInt()) return false;
if (that.isImmediateObjectNotSmallInt()) return false;
return RawLargeStr::cast(*this).equals(RawLargeStr::cast(that));
}
inline bool RawStr::equalsCStr(const char* c_str) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).equalsCStr(c_str);
}
return RawLargeStr::cast(*this).equalsCStr(c_str);
}
inline bool RawStr::includes(RawObject that) const {
if (*this == that) return true;
if (isSmallStr()) {
return RawSmallStr::cast(*this).includes(that);
}
return RawLargeStr::cast(*this).includes(that);
}
inline bool RawStr::includesByte(byte b) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).includesByte(b);
}
return RawLargeStr::cast(*this).includesByte(b);
}
inline bool RawStr::isASCII() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).isASCII();
}
return RawLargeStr::cast(*this).isASCII();
}
inline word RawStr::occurrencesOf(RawObject that) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).occurrencesOf(that);
}
return RawLargeStr::cast(*this).occurrencesOf(that);
}
inline word RawStr::offsetByCodePoints(word index, word count) const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).offsetByCodePoints(index, count);
}
return RawLargeStr::cast(*this).offsetByCodePoints(index, count);
}
inline char* RawStr::toCStr() const {
if (isImmediateObjectNotSmallInt()) {
return RawSmallStr::cast(*this).toCStr();
}
return RawLargeStr::cast(*this).toCStr();
}
// RawLargeStr
inline word RawLargeStr::allocationSize(word length) {
DCHECK(length > RawSmallStr::kMaxLength, "length %ld is too small",
(long)length);
return RawDataArray::allocationSize(length);
}
// RawValueCell
inline RawObject RawValueCell::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawValueCell::setValue(RawObject object) const {
// TODO(T44801497): Disallow a ValueCell in another ValueCell.
DCHECK(*this != object, "ValueCell can't self-reference itself");
instanceVariableAtPut(kValueOffset, object);
}
inline RawObject RawValueCell::dependencyLink() const {
return instanceVariableAt(kDependencyLinkOffset);
}
inline void RawValueCell::setDependencyLink(RawObject object) const {
instanceVariableAtPut(kDependencyLinkOffset, object);
}
inline void RawValueCell::makePlaceholder() const {
instanceVariableAtPut(kValueOffset, *this);
}
inline bool RawValueCell::isPlaceholder() const { return *this == value(); }
// RawEllipsis
inline word RawEllipsis::allocationSize() {
return roundAllocationSize(RawHeader::kSize);
}
inline RawObject RawEllipsis::initialize(uword address) {
return initializeHeader(address, /*count=*/0,
/*hash=*/0, LayoutId::kEllipsis, ObjectFormat::kData);
}
// RawSetBase
inline word RawSetBase::numItems() const {
return RawSmallInt::cast(instanceVariableAt(kNumItemsOffset)).value();
}
inline void RawSetBase::setNumItems(word num_items) const {
instanceVariableAtPut(kNumItemsOffset, RawSmallInt::fromWord(num_items));
}
inline word RawSetBase::numFilled() const {
return RawSmallInt::cast(instanceVariableAt(kNumFilledOffset)).value();
}
inline void RawSetBase::setNumFilled(word num_filled) const {
instanceVariableAtPut(kNumFilledOffset, RawSmallInt::fromWord(num_filled));
}
inline RawObject RawSetBase::data() const {
return instanceVariableAt(kDataOffset);
}
inline void RawSetBase::setData(RawObject data) const {
instanceVariableAtPut(kDataOffset, data);
}
// RawBoundMethod
inline RawObject RawBoundMethod::function() const {
return instanceVariableAt(kFunctionOffset);
}
inline void RawBoundMethod::setFunction(RawObject function) const {
instanceVariableAtPut(kFunctionOffset, function);
}
inline RawObject RawBoundMethod::self() const {
return instanceVariableAt(kSelfOffset);
}
inline void RawBoundMethod::setSelf(RawObject self) const {
instanceVariableAtPut(kSelfOffset, self);
}
// RawCell
inline RawObject RawCell::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawCell::setValue(RawObject value) const {
instanceVariableAtPut(kValueOffset, value);
}
// RawClassMethod
inline RawObject RawClassMethod::function() const {
return instanceVariableAt(kFunctionOffset);
}
inline void RawClassMethod::setFunction(RawObject function) const {
instanceVariableAtPut(kFunctionOffset, function);
}
// RawToken
inline RawObject RawToken::context() const {
return instanceVariableAt(kContextOffset);
}
inline void RawToken::setContext(RawObject context) const {
instanceVariableAtPut(kContextOffset, context);
}
inline RawObject RawToken::oldValue() const {
return instanceVariableAt(kOldValueOffset);
}
inline void RawToken::setOldValue(RawObject old_value) const {
instanceVariableAtPut(kOldValueOffset, old_value);
}
inline bool RawToken::used() const {
return RawBool::cast(instanceVariableAt(kUsedOffset)).value();
}
inline void RawToken::setUsed(bool used) const {
instanceVariableAtPut(kUsedOffset, RawBool::fromBool(used));
}
inline RawObject RawToken::var() const {
return instanceVariableAt(kVarOffset);
}
inline void RawToken::setVar(RawObject var) const {
instanceVariableAtPut(kVarOffset, var);
}
// RawWeakRef
inline RawObject RawWeakRef::referent() const {
return instanceVariableAt(kReferentOffset);
}
inline void RawWeakRef::setReferent(RawObject referent) const {
instanceVariableAtPut(kReferentOffset, referent);
}
inline RawObject RawWeakRef::callback() const {
return instanceVariableAt(kCallbackOffset);
}
inline void RawWeakRef::setCallback(RawObject callable) const {
instanceVariableAtPut(kCallbackOffset, callable);
}
inline RawObject RawWeakRef::link() const {
return instanceVariableAt(kLinkOffset);
}
inline void RawWeakRef::setLink(RawObject reference) const {
instanceVariableAtPut(kLinkOffset, reference);
}
inline RawObject RawWeakRef::hash() const {
return instanceVariableAt(kHashOffset);
}
inline void RawWeakRef::setHash(RawObject hash) const {
instanceVariableAtPut(kHashOffset, hash);
}
// RawUserWeakRefBase
inline RawObject RawUserWeakRefBase::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawUserWeakRefBase::setValue(RawObject value) const {
DCHECK(value.isWeakRef(), "Only tuple type is permitted as a value");
instanceVariableAtPut(kValueOffset, value);
}
inline RawWeakRef weakRefUnderlying(RawObject object) {
if (object.isWeakRef()) {
return RawWeakRef::cast(object);
}
return RawWeakRef::cast(object.rawCast<RawUserWeakRefBase>().value());
}
// RawWeakLink
inline RawObject RawWeakLink::next() const {
return instanceVariableAt(kNextOffset);
}
inline void RawWeakLink::setNext(RawObject object) const {
instanceVariableAtPut(kNextOffset, object);
}
inline RawObject RawWeakLink::prev() const {
return instanceVariableAt(kPrevOffset);
}
inline void RawWeakLink::setPrev(RawObject object) const {
instanceVariableAtPut(kPrevOffset, object);
}
// RawLayout
inline LayoutId RawLayout::id() const {
return static_cast<LayoutId>(header().hashCode());
}
inline void RawLayout::setId(LayoutId id) const {
setHeader(header().withHashCode(static_cast<word>(id)));
}
inline void RawLayout::setDescribedType(RawObject type) const {
instanceVariableAtPut(kDescribedTypeOffset, type);
}
inline RawObject RawLayout::describedType() const {
return instanceVariableAt(kDescribedTypeOffset);
}
inline void RawLayout::setInObjectAttributes(RawObject attributes) const {
instanceVariableAtPut(kInObjectAttributesOffset, attributes);
}
inline RawObject RawLayout::inObjectAttributes() const {
return instanceVariableAt(kInObjectAttributesOffset);
}
inline void RawLayout::setOverflowAttributes(RawObject attributes) const {
instanceVariableAtPut(kOverflowAttributesOffset, attributes);
}
inline void RawLayout::setDictOverflowOffset(word offset) const {
instanceVariableAtPut(kOverflowAttributesOffset,
RawSmallInt::fromWord(offset));
}
inline word RawLayout::dictOverflowOffset() const {
return RawSmallInt::cast(instanceVariableAt(kOverflowAttributesOffset))
.value();
}
inline word RawLayout::instanceSize() const {
word instance_size_in_words = numInObjectAttributes();
if (!isSealed()) {
instance_size_in_words += 1;
}
if (isNativeProxyLayout()) {
instance_size_in_words += RawNativeProxy::kSizeFromEnd / kPointerSize;
}
return instance_size_in_words * kPointerSize;
}
inline bool RawLayout::hasDictOverflow() const {
return overflowAttributes().isSmallInt();
}
inline bool RawLayout::hasTupleOverflow() const {
return overflowAttributes().isTuple();
}
inline RawObject RawLayout::overflowAttributes() const {
return instanceVariableAt(kOverflowAttributesOffset);
}
inline void RawLayout::setAdditions(RawObject additions) const {
instanceVariableAtPut(kAdditionsOffset, additions);
}
inline RawObject RawLayout::additions() const {
return instanceVariableAt(kAdditionsOffset);
}
inline void RawLayout::setDeletions(RawObject deletions) const {
instanceVariableAtPut(kDeletionsOffset, deletions);
}
inline RawObject RawLayout::deletions() const {
return instanceVariableAt(kDeletionsOffset);
}
inline word RawLayout::overflowOffset() const {
DCHECK(hasTupleOverflow() || hasDictOverflow(),
"must have tuple or dict overflow");
return numInObjectAttributes() * kPointerSize;
}
inline word RawLayout::numInObjectAttributes() const {
return RawSmallInt::cast(instanceVariableAt(kNumInObjectAttributesOffset))
.value();
}
inline void RawLayout::setNumInObjectAttributes(word count) const {
instanceVariableAtPut(kNumInObjectAttributesOffset,
RawSmallInt::fromWord(count));
}
inline void RawLayout::seal() const {
setOverflowAttributes(RawNoneType::object());
}
inline bool RawLayout::isSealed() const {
return overflowAttributes().isNoneType();
}
inline bool RawLayout::isNativeProxyLayout() const {
RawObject described_type = describedType();
if (described_type.isNoneType()) {
return false;
}
return described_type.rawCast<RawType>().hasNativeData();
}
// RawSetIterator
inline word RawSetIterator::consumedCount() const {
return RawSmallInt::cast(instanceVariableAt(kConsumedCountOffset)).value();
}
inline void RawSetIterator::setConsumedCount(word consumed) const {
instanceVariableAtPut(kConsumedCountOffset, RawSmallInt::fromWord(consumed));
}
// RawIteratorBase
inline RawObject RawIteratorBase::iterable() const {
return instanceVariableAt(kIterableOffset);
}
inline void RawIteratorBase::setIterable(RawObject iterable) const {
instanceVariableAtPut(kIterableOffset, iterable);
}
inline word RawIteratorBase::index() const {
return RawSmallInt::cast(instanceVariableAt(kIndexOffset)).value();
}
inline void RawIteratorBase::setIndex(word index) const {
instanceVariableAtPut(kIndexOffset, RawSmallInt::fromWord(index));
}
// RawLongRangeIterator
inline RawObject RawLongRangeIterator::next() const {
return instanceVariableAt(kNextOffset);
}
inline void RawLongRangeIterator::setNext(RawObject next) const {
return instanceVariableAtPut(kNextOffset, next);
}
inline RawObject RawLongRangeIterator::stop() const {
return instanceVariableAt(kStopOffset);
}
inline void RawLongRangeIterator::setStop(RawObject stop) const {
return instanceVariableAtPut(kStopOffset, stop);
}
inline RawObject RawLongRangeIterator::step() const {
return instanceVariableAt(kStepOffset);
}
inline void RawLongRangeIterator::setStep(RawObject step) const {
return instanceVariableAtPut(kStepOffset, step);
}
// RawRangeIterator
inline word RawRangeIterator::next() const {
return RawSmallInt::cast(instanceVariableAt(kNextOffset)).value();
}
inline void RawRangeIterator::setNext(word next) const {
return instanceVariableAtPut(kNextOffset, RawSmallInt::fromWord(next));
}
inline word RawRangeIterator::step() const {
return RawSmallInt::cast(instanceVariableAt(kStepOffset)).value();
}
inline void RawRangeIterator::setStep(word step) const {
return instanceVariableAtPut(kStepOffset, RawSmallInt::fromWord(step));
}
inline word RawRangeIterator::length() const {
return RawSmallInt::cast(instanceVariableAt(kLengthOffset)).value();
}
inline void RawRangeIterator::setLength(word length) const {
return instanceVariableAtPut(kLengthOffset, RawSmallInt::fromWord(length));
}
// RawSuper
inline RawObject RawSuper::type() const {
return instanceVariableAt(kTypeOffset);
}
inline void RawSuper::setType(RawObject type) const {
instanceVariableAtPut(kTypeOffset, type);
}
inline RawObject RawSuper::object() const {
return instanceVariableAt(kObjectOffset);
}
inline void RawSuper::setObject(RawObject obj) const {
instanceVariableAtPut(kObjectOffset, obj);
}
inline RawObject RawSuper::objectType() const {
return instanceVariableAt(kObjectTypeOffset);
}
inline void RawSuper::setObjectType(RawObject type) const {
instanceVariableAtPut(kObjectTypeOffset, type);
}
// RawTupleIterator
inline word RawTupleIterator::length() const {
return RawSmallInt::cast(instanceVariableAt(kLengthOffset)).value();
}
inline void RawTupleIterator::setLength(word length) const {
instanceVariableAtPut(kLengthOffset, RawSmallInt::fromWord(length));
}
// RawExceptionState
inline RawObject RawExceptionState::type() const {
return instanceVariableAt(kTypeOffset);
}
inline RawObject RawExceptionState::value() const {
return instanceVariableAt(kValueOffset);
}
inline RawObject RawExceptionState::traceback() const {
return instanceVariableAt(kTracebackOffset);
}
inline void RawExceptionState::setType(RawObject type) const {
instanceVariableAtPut(kTypeOffset, type);
}
inline void RawExceptionState::setValue(RawObject value) const {
instanceVariableAtPut(kValueOffset, value);
}
inline void RawExceptionState::setTraceback(RawObject tb) const {
instanceVariableAtPut(kTracebackOffset, tb);
}
inline RawObject RawExceptionState::previous() const {
return instanceVariableAt(kPreviousOffset);
}
inline void RawExceptionState::setPrevious(RawObject prev) const {
instanceVariableAtPut(kPreviousOffset, prev);
}
// RawGeneratorBase
inline RawObject RawGeneratorBase::generatorFrame() const {
return instanceVariableAt(kFrameOffset);
}
inline void RawGeneratorBase::setGeneratorFrame(RawObject obj) const {
instanceVariableAtPut(kFrameOffset, obj);
}
inline RawObject RawGeneratorBase::exceptionState() const {
return instanceVariableAt(kExceptionStateOffset);
}
inline void RawGeneratorBase::setExceptionState(RawObject obj) const {
instanceVariableAtPut(kExceptionStateOffset, obj);
}
inline RawObject RawGeneratorBase::name() const {
return instanceVariableAt(kNameOffset);
}
inline void RawGeneratorBase::setName(RawObject obj) const {
instanceVariableAtPut(kNameOffset, obj);
}
inline RawObject RawGeneratorBase::running() const {
return instanceVariableAt(kRunningOffset);
}
inline void RawGeneratorBase::setRunning(RawObject obj) const {
instanceVariableAtPut(kRunningOffset, obj);
}
inline RawObject RawGeneratorBase::qualname() const {
return instanceVariableAt(kQualnameOffset);
}
inline void RawGeneratorBase::setQualname(RawObject obj) const {
instanceVariableAtPut(kQualnameOffset, obj);
}
// RawGeneratorFrame
inline Frame* RawGeneratorFrame::frame() const {
return reinterpret_cast<Frame*>(address() + kFrameOffset +
maxStackSize() * kPointerSize);
}
inline RawObject RawGeneratorFrame::function() const {
return instanceVariableAt(kFrameOffset +
(numFrameWords() - 1) * kPointerSize);
}
inline word RawGeneratorFrame::numAttributes(word extra_words) {
return kNumOverheadWords + kFrameSize / kPointerSize + extra_words;
}
inline word RawGeneratorFrame::numFrameWords() const {
return headerCountOrOverflow() - kNumOverheadWords;
}
inline word RawGeneratorFrame::maxStackSize() const {
return RawSmallInt::cast(instanceVariableAt(kMaxStackSizeOffset)).value();
}
inline void RawGeneratorFrame::setMaxStackSize(word offset) const {
instanceVariableAtPut(kMaxStackSizeOffset, RawSmallInt::fromWord(offset));
}
inline void RawGeneratorFrame::setStackSize(word size) const {
word offset =
maxStackSize() * kPointerSize + kFrameOffset + kStackSizeFrameOffset;
instanceVariableAtPut(offset, RawSmallInt::fromWord(size));
}
inline word RawGeneratorFrame::stackSize() const {
word offset =
maxStackSize() * kPointerSize + kFrameOffset + kStackSizeFrameOffset;
return RawSmallInt::cast(instanceVariableAt(offset)).value();
}
// RawCoroutineWrapper
inline RawObject RawCoroutineWrapper::coroutine() const {
return instanceVariableAt(kCoroutineOffset);
}
inline void RawCoroutineWrapper::setCoroutine(RawObject coroutine) const {
instanceVariableAtPut(kCoroutineOffset, coroutine);
}
// RawUnderIOBase
inline bool RawUnderIOBase::closed() const {
RawObject closed = instanceVariableAt(kClosedOffset);
return closed.isBool() && RawBool::cast(closed).value();
}
inline void RawUnderIOBase::setClosed(bool closed) const {
instanceVariableAtPut(kClosedOffset, RawBool::fromBool(closed));
}
// RawUnderBufferedIOMixin
inline RawObject RawUnderBufferedIOMixin::underlying() const {
return instanceVariableAt(kUnderlyingOffset);
}
inline void RawUnderBufferedIOMixin::setUnderlying(RawObject value) const {
instanceVariableAtPut(kUnderlyingOffset, value);
}
// RawBufferedRandom
inline word RawBufferedRandom::bufferSize() const {
return RawSmallInt::cast(instanceVariableAt(kBufferSizeOffset)).value();
}
inline void RawBufferedRandom::setBufferSize(word buffer_size) const {
instanceVariableAtPut(kBufferSizeOffset, RawSmallInt::fromWord(buffer_size));
}
inline RawObject RawBufferedRandom::reader() const {
return instanceVariableAt(kReaderOffset);
}
inline void RawBufferedRandom::setReader(RawObject reader) const {
instanceVariableAtPut(kReaderOffset, reader);
}
inline RawObject RawBufferedRandom::writeBuf() const {
return instanceVariableAt(kWriteBufOffset);
}
inline void RawBufferedRandom::setWriteBuf(RawObject write_buf) const {
instanceVariableAtPut(kWriteBufOffset, write_buf);
}
inline RawObject RawBufferedRandom::writeLock() const {
return instanceVariableAt(kWriteLockOffset);
}
inline void RawBufferedRandom::setWriteLock(RawObject write_lock) const {
instanceVariableAtPut(kWriteLockOffset, write_lock);
}
// RawBufferedReader
inline word RawBufferedReader::bufferSize() const {
return RawSmallInt::cast(instanceVariableAt(kBufferSizeOffset)).value();
}
inline void RawBufferedReader::setBufferSize(word buffer_size) const {
instanceVariableAtPut(kBufferSizeOffset, RawSmallInt::fromWord(buffer_size));
}
inline RawObject RawBufferedReader::readBuf() const {
return instanceVariableAt(kReadBufOffset);
}
inline void RawBufferedReader::setReadBuf(RawObject read_buf) const {
instanceVariableAtPut(kReadBufOffset, read_buf);
}
inline word RawBufferedReader::readPos() const {
return RawSmallInt::cast(instanceVariableAt(kReadPosOffset)).value();
}
inline void RawBufferedReader::setReadPos(word read_pos) const {
instanceVariableAtPut(kReadPosOffset, RawSmallInt::fromWord(read_pos));
}
inline word RawBufferedReader::bufferNumBytes() const {
return RawSmallInt::cast(instanceVariableAt(kBufferNumBytesOffset)).value();
}
inline void RawBufferedReader::setBufferNumBytes(word buffer_num_bytes) const {
instanceVariableAtPut(kBufferNumBytesOffset,
RawSmallInt::fromWord(buffer_num_bytes));
}
// RawBufferedWriter
inline word RawBufferedWriter::bufferSize() const {
return RawSmallInt::cast(instanceVariableAt(kBufferSizeOffset)).value();
}
inline void RawBufferedWriter::setBufferSize(RawObject buffer_size) const {
instanceVariableAtPut(kBufferSizeOffset, buffer_size);
}
inline RawObject RawBufferedWriter::writeBuf() const {
return instanceVariableAt(kWriteBufOffset);
}
inline void RawBufferedWriter::setWriteBuf(RawObject write_buf) const {
instanceVariableAtPut(kWriteBufOffset, write_buf);
}
inline RawObject RawBufferedWriter::writeLock() const {
return instanceVariableAt(kWriteLockOffset);
}
inline void RawBufferedWriter::setWriteLock(RawObject write_lock) const {
instanceVariableAtPut(kWriteLockOffset, write_lock);
}
// RawBytesIO
inline RawObject RawBytesIO::buffer() const {
return instanceVariableAt(kBufferOffset);
}
inline void RawBytesIO::setBuffer(RawObject buffer) const {
instanceVariableAtPut(kBufferOffset, buffer);
}
inline word RawBytesIO::numItems() const {
return RawSmallInt::cast(instanceVariableAt(kNumItemsOffset)).value();
}
inline void RawBytesIO::setNumItems(word num_items) const {
instanceVariableAtPut(kNumItemsOffset, RawSmallInt::fromWord(num_items));
}
inline word RawBytesIO::pos() const {
return RawSmallInt::cast(instanceVariableAt(kPosOffset)).value();
}
inline void RawBytesIO::setPos(word pos) const {
instanceVariableAtPut(kPosOffset, RawSmallInt::fromWord(pos));
}
// RawFileIO
inline RawObject RawFileIO::fd() const { return instanceVariableAt(kFdOffset); }
inline void RawFileIO::setFd(RawObject fd) const {
instanceVariableAtPut(kFdOffset, fd);
}
inline RawObject RawFileIO::isCreated() const {
return instanceVariableAt(kCreatedOffset);
}
inline void RawFileIO::setCreated(RawObject value) const {
instanceVariableAtPut(kCreatedOffset, value);
}
inline RawObject RawFileIO::isReadable() const {
return instanceVariableAt(kReadableOffset);
}
inline void RawFileIO::setReadable(RawObject value) const {
instanceVariableAtPut(kReadableOffset, value);
}
inline RawObject RawFileIO::isWritable() const {
return instanceVariableAt(kWritableOffset);
}
inline void RawFileIO::setWritable(RawObject value) const {
instanceVariableAtPut(kWritableOffset, value);
}
inline RawObject RawFileIO::isAppending() const {
return instanceVariableAt(kAppendingOffset);
}
inline void RawFileIO::setAppending(RawObject value) const {
instanceVariableAtPut(kAppendingOffset, value);
}
inline RawObject RawFileIO::seekable() const {
return instanceVariableAt(kSeekableOffset);
}
inline void RawFileIO::setSeekable(RawObject value) const {
instanceVariableAtPut(kSeekableOffset, value);
}
inline RawObject RawFileIO::shouldCloseFd() const {
return instanceVariableAt(kCloseFdOffset);
}
inline void RawFileIO::setShouldCloseFd(RawObject value) const {
instanceVariableAtPut(kCloseFdOffset, value);
}
// RawStringIO
inline RawObject RawStringIO::buffer() const {
return instanceVariableAt(kBufferOffset);
}
inline void RawStringIO::setBuffer(RawObject buffer) const {
instanceVariableAtPut(kBufferOffset, buffer);
}
inline word RawStringIO::pos() const {
return RawSmallInt::cast(instanceVariableAt(kPosOffset)).value();
}
inline void RawStringIO::setPos(word new_pos) const {
instanceVariableAtPut(kPosOffset, RawSmallInt::fromWord(new_pos));
}
inline RawObject RawStringIO::readnl() const {
return instanceVariableAt(kReadnlOffset);
}
inline void RawStringIO::setReadnl(RawObject readnl) const {
instanceVariableAtPut(kReadnlOffset, readnl);
}
inline bool RawStringIO::hasReadtranslate() const {
return RawBool::cast(instanceVariableAt(kReadtranslateOffset)).value();
}
inline void RawStringIO::setReadtranslate(bool readtranslate) const {
instanceVariableAtPut(kReadtranslateOffset, RawBool::fromBool(readtranslate));
}
inline bool RawStringIO::hasReaduniversal() const {
return RawBool::cast(instanceVariableAt(kReaduniversalOffset)).value();
}
inline void RawStringIO::setReaduniversal(bool readuniversal) const {
instanceVariableAtPut(kReaduniversalOffset, RawBool::fromBool(readuniversal));
}
inline RawObject RawStringIO::seennl() const {
return instanceVariableAt(kSeennlOffset);
}
inline void RawStringIO::setSeennl(RawObject seennl) const {
instanceVariableAtPut(kSeennlOffset, seennl);
}
inline RawObject RawStringIO::writenl() const {
return instanceVariableAt(kWritenlOffset);
}
inline void RawStringIO::setWritenl(RawObject writenl) const {
instanceVariableAtPut(kWritenlOffset, writenl);
}
inline bool RawStringIO::hasWritetranslate() const {
return RawBool::cast(instanceVariableAt(kWritetranslateOffset)).value();
}
inline void RawStringIO::setWritetranslate(bool writetranslate) const {
instanceVariableAtPut(kWritetranslateOffset,
RawBool::fromBool(writetranslate));
}
// RawInstanceMethod
inline RawObject RawInstanceMethod::function() const {
return instanceVariableAt(kFunctionOffset);
}
inline void RawInstanceMethod::setFunction(RawObject function) const {
return instanceVariableAtPut(kFunctionOffset, function);
}
// RawIncrementalNewlineDecoder
inline RawObject RawIncrementalNewlineDecoder::errors() const {
return instanceVariableAt(kErrorsOffset);
}
inline void RawIncrementalNewlineDecoder::setErrors(RawObject errors) const {
instanceVariableAtPut(kErrorsOffset, errors);
}
inline RawObject RawIncrementalNewlineDecoder::translate() const {
return instanceVariableAt(kTranslateOffset);
}
inline void RawIncrementalNewlineDecoder::setTranslate(
RawObject translate) const {
instanceVariableAtPut(kTranslateOffset, translate);
}
inline RawObject RawIncrementalNewlineDecoder::decoder() const {
return instanceVariableAt(kDecoderOffset);
}
inline void RawIncrementalNewlineDecoder::setDecoder(RawObject decoder) const {
instanceVariableAtPut(kDecoderOffset, decoder);
}
inline RawObject RawIncrementalNewlineDecoder::seennl() const {
return instanceVariableAt(kSeennlOffset);
}
inline void RawIncrementalNewlineDecoder::setSeennl(RawObject seennl) const {
instanceVariableAtPut(kSeennlOffset, seennl);
}
inline RawObject RawIncrementalNewlineDecoder::pendingcr() const {
return instanceVariableAt(kPendingcrOffset);
}
inline void RawIncrementalNewlineDecoder::setPendingcr(
RawObject pendingcr) const {
instanceVariableAtPut(kPendingcrOffset, pendingcr);
}
// RawTextIOWrapper
inline RawObject RawTextIOWrapper::buffer() const {
return instanceVariableAt(kBufferOffset);
}
inline void RawTextIOWrapper::setBuffer(RawObject buffer) const {
instanceVariableAtPut(kBufferOffset, buffer);
}
inline bool RawTextIOWrapper::detached() const { return buffer().isNoneType(); }
inline bool RawTextIOWrapper::lineBuffering() const {
return RawBool::cast(instanceVariableAt(kLineBufferingOffset)).value();
}
inline void RawTextIOWrapper::setLineBuffering(RawObject line_buffering) const {
instanceVariableAtPut(kLineBufferingOffset, line_buffering);
}
inline RawObject RawTextIOWrapper::encoding() const {
return instanceVariableAt(kEncodingOffset);
}
inline void RawTextIOWrapper::setEncoding(RawObject encoding) const {
instanceVariableAtPut(kEncodingOffset, encoding);
}
inline RawObject RawTextIOWrapper::errors() const {
return instanceVariableAt(kErrorsOffset);
}
inline void RawTextIOWrapper::setErrors(RawObject errors) const {
instanceVariableAtPut(kErrorsOffset, errors);
}
inline bool RawTextIOWrapper::readuniversal() const {
return RawBool::cast(instanceVariableAt(kReaduniversalOffset)).value();
}
inline void RawTextIOWrapper::setReaduniversal(RawObject readuniversal) const {
instanceVariableAtPut(kReaduniversalOffset, readuniversal);
}
inline bool RawTextIOWrapper::readtranslate() const {
return RawBool::cast(instanceVariableAt(kReadtranslateOffset)).value();
}
inline void RawTextIOWrapper::setReadtranslate(RawObject readtranslate) const {
instanceVariableAtPut(kReadtranslateOffset, readtranslate);
}
inline RawObject RawTextIOWrapper::readnl() const {
return instanceVariableAt(kReadnlOffset);
}
inline void RawTextIOWrapper::setReadnl(RawObject readnl) const {
instanceVariableAtPut(kReadnlOffset, readnl);
}
inline bool RawTextIOWrapper::writetranslate() const {
return RawBool::cast(instanceVariableAt(kWritetranslateOffset)).value();
}
inline void RawTextIOWrapper::setWritetranslate(
RawObject writetranslate) const {
instanceVariableAtPut(kWritetranslateOffset, writetranslate);
}
inline RawObject RawTextIOWrapper::writenl() const {
return instanceVariableAt(kWritenlOffset);
}
inline void RawTextIOWrapper::setWritenl(RawObject writenl) const {
instanceVariableAtPut(kWritenlOffset, writenl);
}
inline RawObject RawTextIOWrapper::encoder() const {
return instanceVariableAt(kEncoderOffset);
}
inline void RawTextIOWrapper::setEncoder(RawObject encoder) const {
instanceVariableAtPut(kEncoderOffset, encoder);
}
inline RawObject RawTextIOWrapper::decoder() const {
return instanceVariableAt(kDecoderOffset);
}
inline void RawTextIOWrapper::setDecoder(RawObject decoder) const {
instanceVariableAtPut(kDecoderOffset, decoder);
}
inline RawObject RawTextIOWrapper::decodedChars() const {
return instanceVariableAt(kDecodedCharsOffset);
}
inline void RawTextIOWrapper::setDecodedChars(RawObject decoded_chars) const {
instanceVariableAtPut(kDecodedCharsOffset, decoded_chars);
}
inline RawObject RawTextIOWrapper::decodedCharsUsed() const {
return instanceVariableAt(kDecodedCharsUsedOffset);
}
inline void RawTextIOWrapper::setDecodedCharsUsed(
RawObject decoded_chars_used) const {
instanceVariableAtPut(kDecodedCharsUsedOffset, decoded_chars_used);
}
inline RawObject RawTextIOWrapper::snapshot() const {
return instanceVariableAt(kSnapshotOffset);
}
inline void RawTextIOWrapper::setSnapshot(RawObject snapshot) const {
instanceVariableAtPut(kSnapshotOffset, snapshot);
}
inline RawObject RawTextIOWrapper::seekable() const {
return instanceVariableAt(kSeekableOffset);
}
inline void RawTextIOWrapper::setSeekable(RawObject seekable) const {
instanceVariableAtPut(kSeekableOffset, seekable);
}
inline RawObject RawTextIOWrapper::hasRead1() const {
return instanceVariableAt(kHasRead1Offset);
}
inline void RawTextIOWrapper::setHasRead1(RawObject has_read1) const {
instanceVariableAtPut(kHasRead1Offset, has_read1);
}
inline RawObject RawTextIOWrapper::b2cratio() const {
return instanceVariableAt(kB2cratioOffset);
}
inline void RawTextIOWrapper::setB2cratio(RawObject b2cratio) const {
instanceVariableAtPut(kB2cratioOffset, b2cratio);
}
inline RawObject RawTextIOWrapper::telling() const {
return instanceVariableAt(kTellingOffset);
}
inline void RawTextIOWrapper::setTelling(RawObject telling) const {
instanceVariableAtPut(kTellingOffset, telling);
}
// RawAsyncGenerator
inline RawObject RawAsyncGenerator::finalizer() const {
return instanceVariableAt(kFinalizerOffset);
}
inline void RawAsyncGenerator::setFinalizer(RawObject finalizer) const {
instanceVariableAtPut(kFinalizerOffset, finalizer);
}
inline bool RawAsyncGenerator::hooksInited() const {
return RawBool::cast(instanceVariableAt(kHooksInitedOffset)).value();
}
inline void RawAsyncGenerator::setHooksInited(bool hooks_inited) const {
instanceVariableAtPut(kHooksInitedOffset, RawBool::fromBool(hooks_inited));
}
// RawAsyncGeneratorOpIterBase
inline RawObject RawAsyncGeneratorOpIterBase::generator() const {
return instanceVariableAt(kGeneratorOffset);
}
inline void RawAsyncGeneratorOpIterBase::setGenerator(
RawObject generator) const {
instanceVariableAtPut(kGeneratorOffset, generator);
}
inline RawAsyncGeneratorOpIterBase::State RawAsyncGeneratorOpIterBase::state()
const {
return static_cast<State>(
RawSmallInt::cast(instanceVariableAt(kStateOffset)).value());
}
inline void RawAsyncGeneratorOpIterBase::setState(State state) const {
instanceVariableAtPut(kStateOffset,
RawSmallInt::fromWord(static_cast<word>(state)));
}
// RawAsyncGeneratorAsend
inline RawObject RawAsyncGeneratorAsend::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawAsyncGeneratorAsend::setValue(RawObject value) const {
instanceVariableAtPut(kValueOffset, value);
}
// RawAsyncGeneratorAthrow
inline RawObject RawAsyncGeneratorAthrow::exceptionTraceback() const {
return instanceVariableAt(kExceptionTracebackOffset);
}
inline void RawAsyncGeneratorAthrow::setExceptionTraceback(
RawObject exception_traceback) const {
instanceVariableAtPut(kExceptionTracebackOffset, exception_traceback);
}
inline RawObject RawAsyncGeneratorAthrow::exceptionType() const {
return instanceVariableAt(kExceptionTypeOffset);
}
inline void RawAsyncGeneratorAthrow::setExceptionType(
RawObject exception_type) const {
instanceVariableAtPut(kExceptionTypeOffset, exception_type);
}
inline RawObject RawAsyncGeneratorAthrow::exceptionValue() const {
return instanceVariableAt(kExceptionValueOffset);
}
inline void RawAsyncGeneratorAthrow::setExceptionValue(
RawObject exception_value) const {
instanceVariableAtPut(kExceptionValueOffset, exception_value);
}
// RawAsyncGeneratorWrappedValue
inline RawObject RawAsyncGeneratorWrappedValue::value() const {
return instanceVariableAt(kValueOffset);
}
inline void RawAsyncGeneratorWrappedValue::setValue(RawObject value) const {
instanceVariableAtPut(kValueOffset, value);
}
// RawTraceback
inline RawObject RawTraceback::function() const {
return instanceVariableAt(kFunctionOffset);
}
inline void RawTraceback::setFunction(RawObject function) const {
instanceVariableAtPut(kFunctionOffset, function);
}
inline RawObject RawTraceback::lasti() const {
return instanceVariableAt(kLastiOffset);
}
inline void RawTraceback::setLasti(RawObject lasti) const {
instanceVariableAtPut(kLastiOffset, lasti);
}
inline RawObject RawTraceback::lineno() const {
return instanceVariableAt(kLinenoOffset);
}
inline void RawTraceback::setLineno(RawObject lineno) const {
instanceVariableAtPut(kLinenoOffset, lineno);
}
inline RawObject RawTraceback::next() const {
return instanceVariableAt(kNextOffset);
}
inline void RawTraceback::setNext(RawObject next) const {
instanceVariableAtPut(kNextOffset, next);
}
} // namespace py