ext/Internal/capi-typeslots.cpp (72 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) #include "capi-typeslots.h" #include "cpython-data.h" #include "capi.h" #include "handles.h" #include "runtime.h" #include "thread.h" namespace py { const int kFirstSlot = Py_bf_getbuffer; const int kLastSlot = Py_tp_finalize; static_assert(kSlotFlags < kFirstSlot && kSlotBasicSize < kFirstSlot && kSlotItemSize < kFirstSlot, "slot indexes must not overlap with internal slots"); bool isValidSlotId(int slot_id) { return kFirstSlot <= slot_id && slot_id <= kLastSlot; } bool isObjectSlotId(int slot_id) { switch (slot_id) { case Py_tp_base: case Py_tp_bases: return true; } return false; } static bool isInternalSlotId(int slot_id) { switch (slot_id) { case kSlotFlags: case kSlotBasicSize: case kSlotItemSize: return true; } return false; } void typeSlotsAllocate(Thread* thread, const Type& type) { DCHECK(!typeHasSlots(type), "type must not have slots yet"); HandleScope scope(thread); word length = kNumInternalSlots + kLastSlot + 1; MutableTuple slots(&scope, thread->runtime()->newMutableTuple(length)); type.setSlots(*slots); } bool typeHasSlots(const Type& type) { return !type.slots().isNoneType(); } void* typeSlotAt(const Type& type, int slot_id) { DCHECK(isValidSlotId(slot_id) && !isObjectSlotId(slot_id), "invalid slot id"); return Int::cast(MutableTuple::cast(type.slots()).at(kSlotOffset + slot_id)) .asCPtr(); } void typeSlotAtPut(Thread* thread, const Type& type, int slot_id, void* value) { DCHECK(isValidSlotId(slot_id) && !isObjectSlotId(slot_id), "invalid slot id"); MutableTuple::cast(type.slots()) .atPut(kSlotOffset + slot_id, thread->runtime()->newIntFromCPtr(value)); } RawObject typeSlotObjectAt(const Type& type, int slot_id) { DCHECK(isObjectSlotId(slot_id), "invalid slot id"); return MutableTuple::cast(type.slots()).at(kSlotOffset + slot_id); } void typeSlotObjectAtPut(const Type& type, int slot_id, RawObject value) { DCHECK(isObjectSlotId(slot_id), "invalid slot id"); MutableTuple::cast(type.slots()).atPut(kSlotOffset + slot_id, value); } uword typeSlotUWordAt(const Type& type, int slot_id) { DCHECK(isInternalSlotId(slot_id), "expected internal slot"); return Int::cast(MutableTuple::cast(type.slots()).at(kSlotOffset + slot_id)) .asInt<uword>() .value; } void typeSlotUWordAtPut(Thread* thread, const Type& type, int slot_id, uword value) { DCHECK(isInternalSlotId(slot_id), "expected internal slot"); MutableTuple::cast(type.slots()) .atPut(kSlotOffset + slot_id, thread->runtime()->newIntFromUnsigned(value)); } } // namespace py