this repo has no description
at trunk 2077 lines 84 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2// typeobject.c implementation 3 4#include <cinttypes> 5 6#include "cpython-data.h" 7#include "cpython-func.h" 8#include "cpython-types.h" 9#include "structmember.h" 10 11#include "api-handle.h" 12#include "attributedict.h" 13#include "builtins-module.h" 14#include "capi-typeslots.h" 15#include "capi.h" 16#include "dict-builtins.h" 17#include "extension-object.h" 18#include "function-builtins.h" 19#include "function-utils.h" 20#include "handles.h" 21#include "int-builtins.h" 22#include "mro.h" 23#include "object-utils.h" 24#include "objects.h" 25#include "runtime.h" 26#include "str-builtins.h" 27#include "trampolines.h" 28#include "type-builtins.h" 29#include "type-utils.h" 30#include "utils.h" 31 32namespace py { 33 34PY_EXPORT PyTypeObject* PySuper_Type_Ptr() { 35 Runtime* runtime = Thread::current()->runtime(); 36 return reinterpret_cast<PyTypeObject*>( 37 ApiHandle::borrowedReference(runtime, runtime->typeAt(LayoutId::kSuper))); 38} 39 40PY_EXPORT int PyType_CheckExact_Func(PyObject* obj) { 41 return ApiHandle::asObject(ApiHandle::fromPyObject(obj)).isType(); 42} 43 44PY_EXPORT int PyType_Check_Func(PyObject* obj) { 45 return Thread::current()->runtime()->isInstanceOfType( 46 ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 47} 48 49PY_EXPORT unsigned long PyType_GetFlags(PyTypeObject* type_obj) { 50 ApiHandle* handle = ApiHandle::fromPyTypeObject(type_obj); 51 52 HandleScope scope(Thread::current()); 53 Type type(&scope, ApiHandle::asObjectNoImmediate(handle)); 54 if (type.isBuiltin()) return Py_TPFLAGS_DEFAULT; 55 56 if (!typeHasSlots(type)) { 57 UNIMPLEMENTED("GetFlags from types initialized through Python code"); 58 } 59 60 return typeSlotUWordAt(type, kSlotFlags); 61} 62 63// PyType_FromSpec() operator support 64// 65// The functions and data in this namespace, culminating in addOperators(), are 66// used to add Python-visible wrappers for type slot C functions (e.g., passing 67// a Py_nb_add slot will result in a __add__() method being added to the type). 68// The wrapper functions (wrapUnaryfunc(), wrapBinaryfunc(), etc...) handle 69// translating between incoming/outgoing RawObject/PyObject* values, along with 70// various bits of slot-specific logic. 71// 72// As other builtins the function's Code object has a pointer to the 73// appropriate wrapper function as its code field, and its consts field 74// is a 1-element tuple containing a pointer to the slot function provided by 75// the user. If this multi-step lookup ever becomes a performance problem, we 76// can easily template the trampolines and/or the wrapper functions, but this 77// keeps the code compact for now. 78 79static ALIGN_16 RawObject wrapUnaryfunc(Thread* thread, Arguments args) { 80 unaryfunc func = reinterpret_cast<unaryfunc>(getNativeFunc(thread)); 81 PyObject* o = ApiHandle::newReference(thread->runtime(), args.get(0)); 82 PyObject* result = (*func)(o); 83 Py_DECREF(o); 84 return ApiHandle::checkFunctionResult(thread, result); 85} 86 87// Common work for hashfunc, lenfunc, and inquiry, all of which take a single 88// PyObject* and return an integral value. 89template <typename cfunc, typename RetFunc> 90static RawObject wrapIntegralfunc(Thread* thread, Arguments args, RetFunc ret) { 91 cfunc func = reinterpret_cast<cfunc>(getNativeFunc(thread)); 92 PyObject* o = ApiHandle::newReference(thread->runtime(), args.get(0)); 93 auto result = func(o); 94 Py_DECREF(o); 95 if (result == -1 && thread->hasPendingException()) return Error::exception(); 96 return ret(result); 97} 98 99static ALIGN_16 RawObject wrapHashfunc(Thread* thread, Arguments args) { 100 return wrapIntegralfunc<hashfunc>(thread, args, [thread](Py_hash_t hash) { 101 return thread->runtime()->newInt(hash); 102 }); 103} 104 105static ALIGN_16 RawObject wrapLenfunc(Thread* thread, Arguments args) { 106 return wrapIntegralfunc<lenfunc>(thread, args, [thread](Py_ssize_t len) { 107 return thread->runtime()->newInt(len); 108 }); 109} 110 111static ALIGN_16 RawObject wrapInquirypred(Thread* thread, Arguments args) { 112 return wrapIntegralfunc<inquiry>( 113 thread, args, [](int result) { return Bool::fromBool(result); }); 114} 115 116static ALIGN_16 RawObject wrapBinaryfunc(Thread* thread, Arguments args) { 117 binaryfunc func = reinterpret_cast<binaryfunc>(getNativeFunc(thread)); 118 Runtime* runtime = thread->runtime(); 119 PyObject* o1 = ApiHandle::newReference(runtime, args.get(0)); 120 PyObject* o2 = ApiHandle::newReference(runtime, args.get(1)); 121 PyObject* result = (*func)(o1, o2); 122 Py_DECREF(o2); 123 Py_DECREF(o1); 124 return ApiHandle::checkFunctionResult(thread, result); 125} 126 127static ALIGN_16 RawObject wrapBinaryfuncSwapped(Thread* thread, 128 Arguments args) { 129 binaryfunc func = reinterpret_cast<binaryfunc>(getNativeFunc(thread)); 130 Runtime* runtime = thread->runtime(); 131 PyObject* o1 = ApiHandle::newReference(runtime, args.get(0)); 132 PyObject* o2 = ApiHandle::newReference(runtime, args.get(1)); 133 PyObject* result = (*func)(o2, o1); 134 Py_DECREF(o2); 135 Py_DECREF(o1); 136 return ApiHandle::checkFunctionResult(thread, result); 137} 138 139static RawObject wrapTernaryfuncImpl(Thread* thread, Arguments args, 140 bool swap) { 141 ternaryfunc func = reinterpret_cast<ternaryfunc>(getNativeFunc(thread)); 142 Runtime* runtime = thread->runtime(); 143 PyObject* self = ApiHandle::newReference(runtime, args.get(swap ? 1 : 0)); 144 PyObject* value = ApiHandle::newReference(runtime, args.get(swap ? 0 : 1)); 145 PyObject* mod = ApiHandle::newReference(runtime, args.get(2)); 146 PyObject* result = (*func)(self, value, mod); 147 Py_DECREF(mod); 148 Py_DECREF(value); 149 Py_DECREF(self); 150 return ApiHandle::checkFunctionResult(thread, result); 151} 152 153// wrapTernaryfunc() vs. wrapVarkwTernaryfunc(): 154// - wrapTernaryfunc(Swapped)(): Wraps a C function expecting exactly 3 155// normal arguments, with the 3rd argument defaulting to None. 156// - wrapVarkwTernaryfunc(): Wraps a C function expecting a self argument, a 157// tuple of positional arguments and an optional dict of keyword arguments. 158static ALIGN_16 RawObject wrapTernaryfunc(Thread* thread, Arguments args) { 159 return wrapTernaryfuncImpl(thread, args, false); 160} 161 162static ALIGN_16 RawObject wrapTernaryfuncSwapped(Thread* thread, 163 Arguments args) { 164 return wrapTernaryfuncImpl(thread, args, true); 165} 166 167static ALIGN_16 RawObject wrapTpNew(Thread* thread, Arguments args) { 168 ternaryfunc func = reinterpret_cast<ternaryfunc>(getNativeFunc(thread)); 169 170 HandleScope scope(thread); 171 Runtime* runtime = thread->runtime(); 172 Object self_obj(&scope, args.get(0)); 173 if (!runtime->isInstanceOfType(*self_obj)) { 174 return thread->raiseWithFmt(LayoutId::kTypeError, 175 "'__new__' requires 'type' but got '%T'", 176 &self_obj); 177 } 178 Function function(&scope, thread->currentFrame()->function()); 179 Type expected_type(&scope, slotWrapperFunctionType(function)); 180 if (!typeIsSubclass(*self_obj, *expected_type)) { 181 Str expected_type_name(&scope, strUnderlying(expected_type.name())); 182 return thread->raiseWithFmt(LayoutId::kTypeError, 183 "'__new__' requires '%S' but got '%T'", 184 &expected_type_name, &self_obj); 185 } 186 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 187 PyObject* varargs = ApiHandle::newReference(runtime, args.get(1)); 188 PyObject* kwargs = Dict::cast(args.get(2)).numItems() == 0 189 ? nullptr 190 : ApiHandle::newReference(runtime, args.get(2)); 191 PyObject* result = (*func)(self, varargs, kwargs); 192 Py_XDECREF(kwargs); 193 Py_DECREF(varargs); 194 Py_DECREF(self); 195 return ApiHandle::checkFunctionResult(thread, result); 196} 197 198static bool checkSelfWithSlotType(Thread* thread, const Object& self) { 199 HandleScope scope(thread); 200 Function function(&scope, thread->currentFrame()->function()); 201 Type expected_type(&scope, slotWrapperFunctionType(function)); 202 if (!typeIsSubclass(thread->runtime()->typeOf(*self), *expected_type)) { 203 Str slot_name(&scope, function.name()); 204 Str expected_type_name(&scope, strUnderlying(expected_type.name())); 205 thread->raiseWithFmt(LayoutId::kTypeError, 206 "'%S' requires '%S' but got '%T'", &slot_name, 207 &expected_type_name, &self); 208 return false; 209 } 210 return true; 211} 212 213static ALIGN_16 RawObject wrapVarkwTernaryfunc(Thread* thread, Arguments args) { 214 ternaryfunc func = reinterpret_cast<ternaryfunc>(getNativeFunc(thread)); 215 216 HandleScope scope(thread); 217 Object self_obj(&scope, args.get(0)); 218 if (!checkSelfWithSlotType(thread, self_obj)) { 219 return Error::exception(); 220 } 221 Runtime* runtime = thread->runtime(); 222 PyObject* self = ApiHandle::newReference(runtime, *self_obj); 223 PyObject* varargs = ApiHandle::newReference(runtime, args.get(1)); 224 PyObject* kwargs = Dict::cast(args.get(2)).numItems() == 0 225 ? nullptr 226 : ApiHandle::newReference(runtime, args.get(2)); 227 PyObject* result = (*func)(self, varargs, kwargs); 228 Py_XDECREF(kwargs); 229 Py_DECREF(varargs); 230 Py_DECREF(self); 231 return ApiHandle::checkFunctionResult(thread, result); 232} 233 234static ALIGN_16 RawObject wrapSetattr(Thread* thread, Arguments args) { 235 setattrofunc func = reinterpret_cast<setattrofunc>(getNativeFunc(thread)); 236 237 Runtime* runtime = thread->runtime(); 238 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 239 PyObject* name = ApiHandle::newReference(runtime, args.get(1)); 240 PyObject* value = ApiHandle::newReference(runtime, args.get(2)); 241 int result = func(self, name, value); 242 Py_DECREF(value); 243 Py_DECREF(name); 244 Py_DECREF(self); 245 if (result < 0) return Error::exception(); 246 return NoneType::object(); 247} 248 249static ALIGN_16 RawObject wrapDelattr(Thread* thread, Arguments args) { 250 setattrofunc func = reinterpret_cast<setattrofunc>(getNativeFunc(thread)); 251 Runtime* runtime = thread->runtime(); 252 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 253 PyObject* name = ApiHandle::newReference(runtime, args.get(1)); 254 int result = func(self, name, nullptr); 255 Py_DECREF(name); 256 Py_DECREF(self); 257 if (result < 0) return Error::exception(); 258 return NoneType::object(); 259} 260 261template <CompareOp op> 262static ALIGN_16 RawObject wrapRichcompare(Thread* thread, Arguments args) { 263 richcmpfunc func = reinterpret_cast<richcmpfunc>(getNativeFunc(thread)); 264 Runtime* runtime = thread->runtime(); 265 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 266 PyObject* other = ApiHandle::newReference(runtime, args.get(1)); 267 PyObject* result = (*func)(self, other, op); 268 Py_DECREF(other); 269 Py_DECREF(self); 270 return ApiHandle::checkFunctionResult(thread, result); 271} 272 273static ALIGN_16 RawObject wrapNext(Thread* thread, Arguments args) { 274 unaryfunc func = reinterpret_cast<unaryfunc>(getNativeFunc(thread)); 275 PyObject* self = ApiHandle::newReference(thread->runtime(), args.get(0)); 276 PyObject* result = (*func)(self); 277 Py_DECREF(self); 278 if (result == nullptr && !thread->hasPendingException()) { 279 return thread->raise(LayoutId::kStopIteration, NoneType::object()); 280 } 281 return ApiHandle::checkFunctionResult(thread, result); 282} 283 284static ALIGN_16 RawObject wrapDescrGet(Thread* thread, Arguments args) { 285 descrgetfunc func = reinterpret_cast<descrgetfunc>(getNativeFunc(thread)); 286 Runtime* runtime = thread->runtime(); 287 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 288 PyObject* obj = nullptr; 289 if (!args.get(1).isNoneType()) { 290 obj = ApiHandle::newReference(runtime, args.get(1)); 291 } 292 PyObject* type = nullptr; 293 if (!args.get(2).isNoneType()) { 294 type = ApiHandle::newReference(runtime, args.get(2)); 295 } 296 if (obj == nullptr && type == nullptr) { 297 return thread->raiseWithFmt(LayoutId::kTypeError, 298 "__get__(None, None), is invalid"); 299 } 300 PyObject* result = (*func)(self, obj, type); 301 Py_DECREF(self); 302 Py_XDECREF(obj); 303 Py_XDECREF(type); 304 return ApiHandle::checkFunctionResult(thread, result); 305} 306 307static ALIGN_16 RawObject wrapDescrSet(Thread* thread, Arguments args) { 308 descrsetfunc func = reinterpret_cast<descrsetfunc>(getNativeFunc(thread)); 309 Runtime* runtime = thread->runtime(); 310 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 311 PyObject* obj = ApiHandle::newReference(runtime, args.get(1)); 312 PyObject* value = ApiHandle::newReference(runtime, args.get(2)); 313 int result = func(self, obj, value); 314 Py_DECREF(value); 315 Py_DECREF(obj); 316 Py_DECREF(self); 317 if (result < 0) return Error::exception(); 318 return NoneType::object(); 319} 320 321static ALIGN_16 RawObject wrapDescrDelete(Thread* thread, Arguments args) { 322 descrsetfunc func = reinterpret_cast<descrsetfunc>(getNativeFunc(thread)); 323 Runtime* runtime = thread->runtime(); 324 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 325 PyObject* obj = ApiHandle::newReference(runtime, args.get(1)); 326 int result = func(self, obj, nullptr); 327 Py_DECREF(obj); 328 Py_DECREF(self); 329 if (result < 0) return Error::exception(); 330 return NoneType::object(); 331} 332 333static ALIGN_16 RawObject wrapInit(Thread* thread, Arguments args) { 334 initproc func = reinterpret_cast<initproc>(getNativeFunc(thread)); 335 Runtime* runtime = thread->runtime(); 336 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 337 PyObject* varargs = ApiHandle::newReference(runtime, args.get(1)); 338 PyObject* kwargs = Dict::cast(args.get(2)).numItems() == 0 339 ? nullptr 340 : ApiHandle::newReference(runtime, args.get(2)); 341 int result = func(self, varargs, kwargs); 342 Py_XDECREF(kwargs); 343 Py_DECREF(varargs); 344 Py_DECREF(self); 345 if (result < 0) return Error::exception(); 346 return NoneType::object(); 347} 348 349static ALIGN_16 RawObject wrapDel(Thread* thread, Arguments args) { 350 destructor func = reinterpret_cast<destructor>(getNativeFunc(thread)); 351 PyObject* self = ApiHandle::newReference(thread->runtime(), args.get(0)); 352 func(self); 353 Py_DECREF(self); 354 return NoneType::object(); 355} 356 357static ALIGN_16 RawObject wrapObjobjargproc(Thread* thread, Arguments args) { 358 objobjargproc func = reinterpret_cast<objobjargproc>(getNativeFunc(thread)); 359 Runtime* runtime = thread->runtime(); 360 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 361 PyObject* key = ApiHandle::newReference(runtime, args.get(1)); 362 PyObject* value = ApiHandle::newReference(runtime, args.get(2)); 363 int res = func(self, key, value); 364 Py_DECREF(value); 365 Py_DECREF(key); 366 Py_DECREF(self); 367 if (res == -1 && thread->hasPendingException()) return Error::exception(); 368 return NoneType::object(); 369} 370 371static ALIGN_16 RawObject wrapObjobjproc(Thread* thread, Arguments args) { 372 objobjproc func = reinterpret_cast<objobjproc>(getNativeFunc(thread)); 373 Runtime* runtime = thread->runtime(); 374 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 375 PyObject* value = ApiHandle::newReference(runtime, args.get(1)); 376 int res = func(self, value); 377 Py_DECREF(value); 378 Py_DECREF(self); 379 if (res == -1 && thread->hasPendingException()) return Error::exception(); 380 return Bool::fromBool(res); 381} 382 383static ALIGN_16 RawObject wrapDelitem(Thread* thread, Arguments args) { 384 objobjargproc func = reinterpret_cast<objobjargproc>(getNativeFunc(thread)); 385 Runtime* runtime = thread->runtime(); 386 PyObject* self = ApiHandle::newReference(runtime, args.get(0)); 387 PyObject* key = ApiHandle::newReference(runtime, args.get(1)); 388 int res = func(self, key, nullptr); 389 Py_DECREF(key); 390 Py_DECREF(self); 391 if (res == -1 && thread->hasPendingException()) return Error::exception(); 392 return NoneType::object(); 393} 394 395// Convert obj into a word-sized int or raise an OverflowError, in the style of 396// PyNumber_AsSsize_t(). 397static RawObject makeIndex(Thread* thread, const Object& obj) { 398 HandleScope scope(thread); 399 Object converted(&scope, intFromIndex(thread, obj)); 400 if (converted.isError()) return *converted; 401 Int i(&scope, intUnderlying(*converted)); 402 if (i.numDigits() != 1) { 403 return thread->raiseWithFmt(LayoutId::kOverflowError, 404 "cannot fit '%T' into an index-sized integer", 405 &obj); 406 } 407 return *i; 408} 409 410static ALIGN_16 RawObject wrapIndexargfunc(Thread* thread, Arguments args) { 411 ssizeargfunc func = reinterpret_cast<ssizeargfunc>(getNativeFunc(thread)); 412 413 HandleScope scope(thread); 414 PyObject* self = ApiHandle::newReference(thread->runtime(), args.get(0)); 415 Object arg(&scope, args.get(1)); 416 arg = makeIndex(thread, arg); 417 if (arg.isError()) { 418 Py_DECREF(self); 419 return *arg; 420 } 421 PyObject* result = (*func)(self, Int::cast(*arg).asWord()); 422 Py_DECREF(self); 423 return ApiHandle::checkFunctionResult(thread, result); 424} 425 426// First, convert arg to a word-sized int using makeIndex(). Then, if the result 427// is negative, add len(self) to normalize it. 428static RawObject normalizeIndex(Thread* thread, const Object& self, 429 const Object& arg) { 430 HandleScope scope(thread); 431 Object index(&scope, makeIndex(thread, arg)); 432 if (index.isError()) return *index; 433 word i = Int::cast(*index).asWord(); 434 if (i >= 0) { 435 return *index; 436 } 437 Object len(&scope, thread->invokeFunction1(ID(builtins), ID(len), self)); 438 if (len.isError()) return *len; 439 len = makeIndex(thread, len); 440 if (len.isError()) return *len; 441 i += Int::cast(*len).asWord(); 442 return thread->runtime()->newInt(i); 443} 444 445static ALIGN_16 RawObject wrapSqItem(Thread* thread, Arguments args) { 446 ssizeargfunc func = reinterpret_cast<ssizeargfunc>(getNativeFunc(thread)); 447 448 HandleScope scope(thread); 449 Object self(&scope, args.get(0)); 450 Object arg(&scope, args.get(1)); 451 arg = normalizeIndex(thread, self, arg); 452 if (arg.isError()) return *arg; 453 PyObject* py_self = ApiHandle::newReference(thread->runtime(), *self); 454 PyObject* result = (*func)(py_self, Int::cast(*arg).asWord()); 455 Py_DECREF(py_self); 456 return ApiHandle::checkFunctionResult(thread, result); 457} 458 459static ALIGN_16 RawObject wrapSqSetitem(Thread* thread, Arguments args) { 460 ssizeobjargproc func = 461 reinterpret_cast<ssizeobjargproc>(getNativeFunc(thread)); 462 463 HandleScope scope(thread); 464 Object self(&scope, args.get(0)); 465 Object arg(&scope, args.get(1)); 466 arg = normalizeIndex(thread, self, arg); 467 if (arg.isError()) return *arg; 468 Runtime* runtime = thread->runtime(); 469 PyObject* py_self = ApiHandle::newReference(runtime, *self); 470 PyObject* py_value = ApiHandle::newReference(runtime, args.get(2)); 471 int result = func(py_self, Int::cast(*arg).asWord(), py_value); 472 Py_DECREF(py_value); 473 Py_DECREF(py_self); 474 if (result == -1 && thread->hasPendingException()) return Error::exception(); 475 return NoneType::object(); 476} 477 478static ALIGN_16 RawObject wrapSqDelitem(Thread* thread, Arguments args) { 479 ssizeobjargproc func = 480 reinterpret_cast<ssizeobjargproc>(getNativeFunc(thread)); 481 482 HandleScope scope(thread); 483 Object self(&scope, args.get(0)); 484 Object arg(&scope, args.get(1)); 485 arg = normalizeIndex(thread, self, arg); 486 if (arg.isError()) return *arg; 487 PyObject* py_self = ApiHandle::newReference(thread->runtime(), *self); 488 int result = func(py_self, Int::cast(*arg).asWord(), nullptr); 489 Py_DECREF(py_self); 490 if (result == -1 && thread->hasPendingException()) return Error::exception(); 491 return NoneType::object(); 492} 493 494// Information about a single type slot. 495struct SlotDef { 496 // The name of the method in managed code. 497 SymbolId name; 498 499 // type slot it. 500 int id; 501 502 // List of parameter names/symbols. 503 View<SymbolId> parameters; 504 505 // The wrapper function for this slot. 506 BuiltinFunction wrapper; 507 508 // RawCode::Flags to be set on slot function. 509 word flags; 510 511 // Doc string for the function. 512 const char* doc; 513}; 514 515static const SymbolId kParamsSelfArgsKwargs[] = {ID(self), ID(args), 516 ID(kwargs)}; 517static const SymbolId kParamsSelfInstanceOwner[] = {ID(self), ID(instance), 518 ID(owner)}; 519static const SymbolId kParamsSelfInstanceValue[] = {ID(self), ID(instance), 520 ID(value)}; 521static const SymbolId kParamsSelfInstance[] = {ID(self), ID(instance)}; 522static const SymbolId kParamsSelfKeyValue[] = {ID(self), ID(key), ID(value)}; 523static const SymbolId kParamsSelfKey[] = {ID(self), ID(key)}; 524static const SymbolId kParamsSelfNameValue[] = {ID(self), ID(name), ID(value)}; 525static const SymbolId kParamsSelfName[] = {ID(self), ID(name)}; 526static const SymbolId kParamsSelfValueMod[] = {ID(self), ID(value), ID(mod)}; 527static const SymbolId kParamsSelfValue[] = {ID(self), ID(value)}; 528static const SymbolId kParamsSelf[] = {ID(self)}; 529static const SymbolId kParamsTypeArgsKwargs[] = {ID(type), ID(args), 530 ID(kwargs)}; 531 532// These macros currently ignore the FUNCTION argument, which is still the 533// function name inherited from CPython. This will be cleaned up when we add 534// default slot implementations that delegate to the corresponding Python 535// method, along with logic to update slots as needed when a user assigns to a 536// type dict. 537#define TPSLOT(NAME, SLOT, PARAMETERS, FUNCTION, WRAPPER, DOC) \ 538 { NAME, SLOT, PARAMETERS, WRAPPER, 0, DOC } 539#define KWSLOT(NAME, SLOT, PARAMETERS, FUNCTION, WRAPPER, DOC) \ 540 { \ 541 NAME, SLOT, PARAMETERS, WRAPPER, \ 542 Code::Flags::kVarargs | Code::Flags::kVarkeyargs, DOC, \ 543 } 544#define UNSLOT(NAME, C_NAME, SLOT, FUNCTION, DOC) \ 545 TPSLOT(NAME, SLOT, kParamsSelf, FUNCTION, wrapUnaryfunc, \ 546 C_NAME "($self, /)\n--\n\n" DOC) 547#define IBSLOT(NAME, C_NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 548 TPSLOT(NAME, SLOT, kParamsSelfValue, FUNCTION, WRAPPER, \ 549 C_NAME "($self, value, /)\n--\n\nReturn self" DOC "value.") 550#define BINSLOT(NAME, C_NAME, SLOT, FUNCTION, DOC) \ 551 TPSLOT(NAME, SLOT, kParamsSelfValue, FUNCTION, wrapBinaryfunc, \ 552 C_NAME "($self, value, /)\n--\n\nReturn self" DOC "value.") 553#define RBINSLOT(NAME, C_NAME, SLOT, FUNCTION, DOC) \ 554 TPSLOT(NAME, SLOT, kParamsSelfValue, FUNCTION, wrapBinaryfuncSwapped, \ 555 C_NAME "($self, value, /)\n--\n\nReturn value" DOC "self.") 556#define BINSLOTNOTINFIX(NAME, C_NAME, SLOT, FUNCTION, DOC) \ 557 TPSLOT(NAME, SLOT, kParamsSelfValue, FUNCTION, wrapBinaryfunc, \ 558 C_NAME "($self, value, /)\n--\n\n" DOC) 559#define RBINSLOTNOTINFIX(NAME, C_NAME, SLOT, FUNCTION, DOC) \ 560 TPSLOT(NAME, SLOT, kParamsSelfValue, FUNCTION, wrapBinaryfuncSwapped, \ 561 C_NAME "($self, value, /)\n--\n\n" DOC) 562 563static const SlotDef kSlotdefs[] = { 564 TPSLOT(ID(__getattribute__), Py_tp_getattr, kParamsSelfName, nullptr, 565 nullptr, ""), 566 TPSLOT(ID(__getattr__), Py_tp_getattr, kParamsSelfName, nullptr, nullptr, 567 ""), 568 TPSLOT(ID(__setattr__), Py_tp_setattr, kParamsSelfNameValue, nullptr, 569 nullptr, ""), 570 TPSLOT(ID(__delattr__), Py_tp_setattr, kParamsSelfName, nullptr, nullptr, 571 ""), 572 UNSLOT(ID(__repr__), "__repr__", Py_tp_repr, slot_tp_repr, 573 "Return repr(self)."), 574 TPSLOT(ID(__hash__), Py_tp_hash, kParamsSelf, slot_tp_hash, wrapHashfunc, 575 "__hash__($self, /)\n--\n\nReturn hash(self)."), 576 KWSLOT( 577 ID(__call__), Py_tp_call, kParamsSelfArgsKwargs, slot_tp_call, 578 wrapVarkwTernaryfunc, 579 "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function."), 580 UNSLOT(ID(__str__), "__str__", Py_tp_str, slot_tp_str, "Return str(self)."), 581 TPSLOT(ID(__getattribute__), Py_tp_getattro, kParamsSelfName, 582 slot_tp_getattr_hook, wrapBinaryfunc, 583 "__getattribute__($self, name, /)\n--\n\nReturn getattr(self, " 584 "name)."), 585 TPSLOT(ID(__getattr__), Py_tp_getattro, kParamsSelfName, 586 slot_tp_getattr_hook, nullptr, ""), 587 TPSLOT(ID(__setattr__), Py_tp_setattro, kParamsSelfNameValue, 588 slot_tp_setattro, wrapSetattr, 589 "__setattr__($self, name, value, /)\n--\n\nImplement setattr(self, " 590 "name, value)."), 591 TPSLOT(ID(__delattr__), Py_tp_setattro, kParamsSelfName, slot_tp_setattro, 592 wrapDelattr, 593 "__delattr__($self, name, /)\n--\n\nImplement delattr(self, name)."), 594 TPSLOT(ID(__lt__), Py_tp_richcompare, kParamsSelfValue, slot_tp_richcompare, 595 wrapRichcompare<LT>, 596 "__lt__($self, value, /)\n--\n\nReturn self<value."), 597 TPSLOT(ID(__le__), Py_tp_richcompare, kParamsSelfValue, slot_tp_richcompare, 598 wrapRichcompare<LE>, 599 "__le__($self, value, /)\n--\n\nReturn self<=value."), 600 TPSLOT(ID(__eq__), Py_tp_richcompare, kParamsSelfValue, slot_tp_richcompare, 601 wrapRichcompare<EQ>, 602 "__eq__($self, value, /)\n--\n\nReturn self==value."), 603 TPSLOT(ID(__ne__), Py_tp_richcompare, kParamsSelfValue, slot_tp_richcompare, 604 wrapRichcompare<NE>, 605 "__ne__($self, value, /)\n--\n\nReturn self!=value."), 606 TPSLOT(ID(__gt__), Py_tp_richcompare, kParamsSelfValue, slot_tp_richcompare, 607 wrapRichcompare<GT>, 608 "__gt__($self, value, /)\n--\n\nReturn self>value."), 609 TPSLOT(ID(__ge__), Py_tp_richcompare, kParamsSelfValue, slot_tp_richcompare, 610 wrapRichcompare<GE>, 611 "__ge__($self, value, /)\n--\n\nReturn self>=value."), 612 UNSLOT(ID(__iter__), "__iter__", Py_tp_iter, slot_tp_iter, 613 "Implement iter(self)."), 614 TPSLOT(ID(__next__), Py_tp_iternext, kParamsSelf, slot_tp_iternext, 615 wrapNext, "__next__($self, /)\n--\n\nImplement next(self)."), 616 TPSLOT(ID(__get__), Py_tp_descr_get, kParamsSelfInstanceOwner, 617 slot_tp_descr_get, wrapDescrGet, 618 "__get__($self, instance, owner, /)\n--\n\nReturn an attribute of " 619 "instance, which is of type owner."), 620 TPSLOT(ID(__set__), Py_tp_descr_set, kParamsSelfInstanceValue, 621 slot_tp_descr_set, wrapDescrSet, 622 "__set__($self, instance, value, /)\n--\n\nSet an attribute of " 623 "instance to value."), 624 TPSLOT(ID(__delete__), Py_tp_descr_set, kParamsSelfInstance, 625 slot_tp_descr_set, wrapDescrDelete, 626 "__delete__($self, instance, /)\n--\n\nDelete an attribute of " 627 "instance."), 628 KWSLOT(ID(__init__), Py_tp_init, kParamsSelfArgsKwargs, slot_tp_init, 629 wrapInit, 630 "__init__($self, /, *args, **kwargs)\n--\n\nInitialize self. See " 631 "help(type(self)) for accurate signature."), 632 KWSLOT(ID(__new__), Py_tp_new, kParamsTypeArgsKwargs, slot_tp_new, 633 wrapTpNew, 634 "__new__(type, /, *args, **kwargs)\n--\n\n" 635 "Create and return new object. See help(type) for accurate " 636 "signature."), 637 TPSLOT(ID(__del__), Py_tp_finalize, kParamsSelf, slot_tp_finalize, wrapDel, 638 ""), 639 UNSLOT(ID(__await__), "__await__", Py_am_await, slot_am_await, 640 "Return an iterator to be used in await expression."), 641 UNSLOT(ID(__aiter__), "__aiter__", Py_am_aiter, slot_am_aiter, 642 "Return an awaitable, that resolves in asynchronous iterator."), 643 UNSLOT(ID(__anext__), "__anext__", Py_am_anext, slot_am_anext, 644 "Return a value or raise StopAsyncIteration."), 645 BINSLOT(ID(__add__), "__add__", Py_nb_add, slot_nb_add, "+"), 646 RBINSLOT(ID(__radd__), "__radd__", Py_nb_add, slot_nb_add, "+"), 647 BINSLOT(ID(__sub__), "__sub__", Py_nb_subtract, slot_nb_subtract, "-"), 648 RBINSLOT(ID(__rsub__), "__rsub__", Py_nb_subtract, slot_nb_subtract, "-"), 649 BINSLOT(ID(__mul__), "__mul__", Py_nb_multiply, slot_nb_multiply, "*"), 650 RBINSLOT(ID(__rmul__), "__rmul__", Py_nb_multiply, slot_nb_multiply, "*"), 651 BINSLOT(ID(__mod__), "__mod__", Py_nb_remainder, slot_nb_remainder, "%"), 652 RBINSLOT(ID(__rmod__), "__rmod__", Py_nb_remainder, slot_nb_remainder, "%"), 653 BINSLOTNOTINFIX(ID(__divmod__), "__divmod__", Py_nb_divmod, slot_nb_divmod, 654 "Return divmod(self, value)."), 655 RBINSLOTNOTINFIX(ID(__rdivmod__), "__rdivmod__", Py_nb_divmod, 656 slot_nb_divmod, "Return divmod(value, self)."), 657 TPSLOT(ID(__pow__), Py_nb_power, kParamsSelfValueMod, slot_nb_power, 658 wrapTernaryfunc, 659 "__pow__($self, value, mod=None, /)\n--\n\nReturn pow(self, value, " 660 "mod)."), 661 TPSLOT(ID(__rpow__), Py_nb_power, kParamsSelfValueMod, slot_nb_power, 662 wrapTernaryfuncSwapped, 663 "__rpow__($self, value, mod=None, /)\n--\n\nReturn pow(value, self, " 664 "mod)."), 665 UNSLOT(ID(__neg__), "__neg__", Py_nb_negative, slot_nb_negative, "-self"), 666 UNSLOT(ID(__pos__), "__pos__", Py_nb_positive, slot_nb_positive, "+self"), 667 UNSLOT(ID(__abs__), "__abs__", Py_nb_absolute, slot_nb_absolute, 668 "abs(self)"), 669 TPSLOT(ID(__bool__), Py_nb_bool, kParamsSelf, slot_nb_bool, wrapInquirypred, 670 "__bool__($self, /)\n--\n\nself != 0"), 671 UNSLOT(ID(__invert__), "__invert__", Py_nb_invert, slot_nb_invert, "~self"), 672 BINSLOT(ID(__lshift__), "__lshift__", Py_nb_lshift, slot_nb_lshift, "<<"), 673 RBINSLOT(ID(__rlshift__), "__rlshift__", Py_nb_lshift, slot_nb_lshift, 674 "<<"), 675 BINSLOT(ID(__rshift__), "__rshift__", Py_nb_rshift, slot_nb_rshift, ">>"), 676 RBINSLOT(ID(__rrshift__), "__rrshift__", Py_nb_rshift, slot_nb_rshift, 677 ">>"), 678 BINSLOT(ID(__and__), "__and__", Py_nb_and, slot_nb_and, "&"), 679 RBINSLOT(ID(__rand__), "__rand__", Py_nb_and, slot_nb_and, "&"), 680 BINSLOT(ID(__xor__), "__xor__", Py_nb_xor, slot_nb_xor, "^"), 681 RBINSLOT(ID(__rxor__), "__rxor__", Py_nb_xor, slot_nb_xor, "^"), 682 BINSLOT(ID(__or__), "__or__", Py_nb_or, slot_nb_or, "|"), 683 RBINSLOT(ID(__ror__), "__ror__", Py_nb_or, slot_nb_or, "|"), 684 UNSLOT(ID(__int__), "__int__", Py_nb_int, slot_nb_int, "int(self)"), 685 UNSLOT(ID(__float__), "__float__", Py_nb_float, slot_nb_float, 686 "float(self)"), 687 IBSLOT(ID(__iadd__), "__iadd__", Py_nb_inplace_add, slot_nb_inplace_add, 688 wrapBinaryfunc, "+="), 689 IBSLOT(ID(__isub__), "__isub__", Py_nb_inplace_subtract, 690 slot_nb_inplace_subtract, wrapBinaryfunc, "-="), 691 IBSLOT(ID(__imul__), "__imul__", Py_nb_inplace_multiply, 692 slot_nb_inplace_multiply, wrapBinaryfunc, "*="), 693 IBSLOT(ID(__imod__), "__imod__", Py_nb_inplace_remainder, 694 slot_nb_inplace_remainder, wrapBinaryfunc, "%="), 695 IBSLOT(ID(__ipow__), "__ipow__", Py_nb_inplace_power, slot_nb_inplace_power, 696 wrapBinaryfunc, "**="), 697 IBSLOT(ID(__ilshift__), "__ilshift__", Py_nb_inplace_lshift, 698 slot_nb_inplace_lshift, wrapBinaryfunc, "<<="), 699 IBSLOT(ID(__irshift__), "__irshift__", Py_nb_inplace_rshift, 700 slot_nb_inplace_rshift, wrapBinaryfunc, ">>="), 701 IBSLOT(ID(__iand__), "__iand__", Py_nb_inplace_and, slot_nb_inplace_and, 702 wrapBinaryfunc, "&="), 703 IBSLOT(ID(__ixor__), "__ixor__", Py_nb_inplace_xor, slot_nb_inplace_xor, 704 wrapBinaryfunc, "^="), 705 IBSLOT(ID(__ior__), "__ior__", Py_nb_inplace_or, slot_nb_inplace_or, 706 wrapBinaryfunc, "|="), 707 BINSLOT(ID(__floordiv__), "__floordiv__", Py_nb_floor_divide, 708 slot_nb_floor_divide, "//"), 709 RBINSLOT(ID(__rfloordiv__), "__rfloordiv__", Py_nb_floor_divide, 710 slot_nb_floor_divide, "//"), 711 BINSLOT(ID(__truediv__), "__truediv__", Py_nb_true_divide, 712 slot_nb_true_divide, "/"), 713 RBINSLOT(ID(__rtruediv__), "__rtruediv__", Py_nb_true_divide, 714 slot_nb_true_divide, "/"), 715 IBSLOT(ID(__ifloordiv__), "__ifloordiv__", Py_nb_inplace_floor_divide, 716 slot_nb_inplace_floor_divide, wrapBinaryfunc, "//="), 717 IBSLOT(ID(__itruediv__), "__itruediv__", Py_nb_inplace_true_divide, 718 slot_nb_inplace_true_divide, wrapBinaryfunc, "/="), 719 UNSLOT(ID(__index__), "__index__", Py_nb_index, slot_nb_index, 720 "Return self converted to an integer, if self is suitable " 721 "for use as an index into a list."), 722 BINSLOT(ID(__matmul__), "__matmul__", Py_nb_matrix_multiply, 723 slot_nb_matrix_multiply, "@"), 724 RBINSLOT(ID(__rmatmul__), "__rmatmul__", Py_nb_matrix_multiply, 725 slot_nb_matrix_multiply, "@"), 726 IBSLOT(ID(__imatmul__), "__imatmul__", Py_nb_inplace_matrix_multiply, 727 slot_nb_inplace_matrix_multiply, wrapBinaryfunc, "@="), 728 TPSLOT(ID(__len__), Py_mp_length, kParamsSelf, slot_mp_length, wrapLenfunc, 729 "__len__($self, /)\n--\n\nReturn len(self)."), 730 TPSLOT(ID(__getitem__), Py_mp_subscript, kParamsSelfKey, slot_mp_subscript, 731 wrapBinaryfunc, 732 "__getitem__($self, key, /)\n--\n\nReturn self[key]."), 733 TPSLOT(ID(__setitem__), Py_mp_ass_subscript, kParamsSelfKeyValue, 734 slot_mp_ass_subscript, wrapObjobjargproc, 735 "__setitem__($self, key, value, /)\n--\n\nSet self[key] to value."), 736 TPSLOT(ID(__delitem__), Py_mp_ass_subscript, kParamsSelfKey, 737 slot_mp_ass_subscript, wrapDelitem, 738 "__delitem__($self, key, /)\n--\n\nDelete self[key]."), 739 TPSLOT(ID(__len__), Py_sq_length, kParamsSelf, slot_sq_length, wrapLenfunc, 740 "__len__($self, /)\n--\n\nReturn len(self)."), 741 TPSLOT(ID(__add__), Py_sq_concat, kParamsSelfValue, nullptr, wrapBinaryfunc, 742 "__add__($self, value, /)\n--\n\nReturn self+value."), 743 TPSLOT(ID(__mul__), Py_sq_repeat, kParamsSelfValue, nullptr, 744 wrapIndexargfunc, 745 "__mul__($self, value, /)\n--\n\nReturn self*value."), 746 TPSLOT(ID(__rmul__), Py_sq_repeat, kParamsSelfValue, nullptr, 747 wrapIndexargfunc, 748 "__rmul__($self, value, /)\n--\n\nReturn value*self."), 749 TPSLOT(ID(__getitem__), Py_sq_item, kParamsSelfKey, slot_sq_item, 750 wrapSqItem, "__getitem__($self, key, /)\n--\n\nReturn self[key]."), 751 TPSLOT(ID(__setitem__), Py_sq_ass_item, kParamsSelfKeyValue, 752 slot_sq_ass_item, wrapSqSetitem, 753 "__setitem__($self, key, value, /)\n--\n\nSet self[key] to value."), 754 TPSLOT(ID(__delitem__), Py_sq_ass_item, kParamsSelfKey, slot_sq_ass_item, 755 wrapSqDelitem, 756 "__delitem__($self, key, /)\n--\n\nDelete self[key]."), 757 TPSLOT(ID(__contains__), Py_sq_contains, kParamsSelfKey, slot_sq_contains, 758 wrapObjobjproc, 759 "__contains__($self, key, /)\n--\n\nReturn key in self."), 760 TPSLOT(ID(__iadd__), Py_sq_inplace_concat, kParamsSelfValue, nullptr, 761 wrapBinaryfunc, 762 "__iadd__($self, value, /)\n--\n\nImplement self+=value."), 763 TPSLOT(ID(__imul__), Py_sq_inplace_repeat, kParamsSelfValue, nullptr, 764 wrapIndexargfunc, 765 "__imul__($self, value, /)\n--\n\nImplement self*=value."), 766}; 767 768// For every entry in kSlotdefs with a non-null wrapper function, a slot id 769// that was provided by the user, and no preexisting entry in the type dict, add 770// a wrapper function to call the slot from Python. 771// 772// Returns Error if an exception was raised at any point, None otherwise. 773static RawObject addOperators(Thread* thread, const Type& type) { 774 Runtime* runtime = thread->runtime(); 775 HandleScope scope(thread); 776 Str type_name(&scope, type.name()); 777 778 for (const SlotDef& slot : kSlotdefs) { 779 if (slot.wrapper == nullptr) continue; 780 void* slot_value = typeSlotAt(type, slot.id); 781 if (slot_value == nullptr) continue; 782 783 // Unlike most slots, we always allow __new__ to be overwritten by a subtype 784 if (slot.id != Py_tp_new && 785 !typeAtById(thread, type, slot.name).isErrorNotFound()) { 786 continue; 787 } 788 789 // When given PyObject_HashNotImplemented, put None in the type dict 790 // rather than a wrapper. CPython does this regardless of which slot it 791 // was given for, so we do too. 792 if (slot_value == reinterpret_cast<void*>(&PyObject_HashNotImplemented)) { 793 Object none(&scope, NoneType::object()); 794 typeAtPutById(thread, type, slot.name, none); 795 return NoneType::object(); 796 } 797 798 Object func_obj(&scope, NoneType::object()); 799 if (slot_value == reinterpret_cast<void*>(&PyObject_GenericGetAttr)) { 800 func_obj = runtime->objectDunderGetattribute(); 801 } else if (slot_value == 802 reinterpret_cast<void*>(&PyObject_GenericSetAttr)) { 803 func_obj = runtime->objectDunderSetattr(); 804 } else { 805 // Create the wrapper function. 806 Str slot_name(&scope, runtime->symbols()->at(slot.name)); 807 Str qualname(&scope, 808 runtime->newStrFromFmt("%S.%S", &type_name, &slot_name)); 809 Code code(&scope, newExtCode(thread, slot_name, slot.parameters, 810 slot.flags, slot.wrapper, slot_value)); 811 Object globals(&scope, NoneType::object()); 812 Function func(&scope, runtime->newFunctionWithCode(thread, qualname, code, 813 globals)); 814 slotWrapperFunctionSetType(func, type); 815 if (slot.id == Py_nb_power) { 816 Object none(&scope, NoneType::object()); 817 func.setDefaults(runtime->newTupleWith1(none)); 818 } 819 820 // __new__ is the one special-case static method, so wrap it 821 // appropriately. 822 func_obj = *func; 823 if (slot.id == Py_tp_new) { 824 func_obj = 825 thread->invokeFunction1(ID(builtins), ID(staticmethod), func); 826 if (func_obj.isError()) return *func_obj; 827 } 828 } 829 830 // Finally, put the wrapper in the type dict. 831 typeAtPutById(thread, type, slot.name, func_obj); 832 } 833 834 return NoneType::object(); 835} 836 837static PyObject* allocatePyObject(const Type& type, Py_ssize_t nitems) { 838 uword basic_size = typeSlotUWordAt(type, kSlotBasicSize); 839 uword item_size = typeSlotUWordAt(type, kSlotItemSize); 840 Py_ssize_t size = Utils::roundUp(nitems * item_size + basic_size, kWordSize); 841 842 PyObject* result = nullptr; 843 if (type.hasFlag(Type::Flag::kHasCycleGC)) { 844 result = static_cast<PyObject*>(_PyObject_GC_Calloc(size)); 845 } else { 846 result = static_cast<PyObject*>(PyObject_Calloc(1, size)); 847 } 848 // Track object in native GC queue 849 if (type.hasFlag(Type::Flag::kHasCycleGC)) { 850 PyObject_GC_Track(result); 851 } 852 return result; 853} 854 855static PyObject* superclassTpNew(PyTypeObject* typeobj, PyObject* args, 856 PyObject* kwargs) { 857 Thread* thread = Thread::current(); 858 HandleScope scope(thread); 859 Runtime* runtime = thread->runtime(); 860 861 Type type(&scope, ApiHandle::asObject(ApiHandle::fromPyTypeObject(typeobj))); 862 Object args_obj(&scope, args == nullptr 863 ? runtime->emptyTuple() 864 : ApiHandle::asObject(ApiHandle::fromPyObject(args))); 865 DCHECK(runtime->isInstanceOfTuple(*args_obj), 866 "Slot __new__ expected tuple args"); 867 Object kwargs_obj(&scope, kwargs == nullptr 868 ? NoneType::object() 869 : ApiHandle::asObject(ApiHandle::fromPyObject(kwargs))); 870 DCHECK(kwargs == nullptr || runtime->isInstanceOfDict(*kwargs_obj), 871 "Slot __new__ expected nullptr or dict kwargs"); 872 873 Tuple type_mro(&scope, type.mro()); 874 word i = 0; 875 Type superclass(&scope, type_mro.at(i++)); 876 while (typeHasSlots(superclass)) { 877 superclass = type_mro.at(i++); 878 } 879 Object dunder_new(&scope, 880 typeLookupInMroById(thread, *superclass, ID(__new__))); 881 Object none(&scope, NoneType::object()); 882 dunder_new = resolveDescriptorGet(thread, dunder_new, none, type); 883 dunder_new = runtime->newBoundMethod(dunder_new, type); 884 thread->stackPush(*dunder_new); 885 thread->stackPush(*args_obj); 886 word flags = 0; 887 if (kwargs != nullptr) { 888 thread->stackPush(*kwargs_obj); 889 flags = CallFunctionExFlag::VAR_KEYWORDS; 890 } 891 Object instance(&scope, Interpreter::callEx(thread, flags)); 892 if (instance.isErrorException()) return nullptr; 893 894 // If the type doesn't require NativeData, we don't need to allocate or 895 // create a NativeProxy for the instance 896 if (!type.hasNativeData()) { 897 return ApiHandle::newReference(runtime, *instance); 898 } 899 900 PyObject* result = allocatePyObject(type, 0); 901 if (result == nullptr) { 902 thread->raiseMemoryError(); 903 return nullptr; 904 } 905 return initializeExtensionObject(thread, result, typeobj, instance); 906} 907 908// tp_new slot implementation that delegates to a Type's __new__ attribute. 909static PyObject* slotTpNew(PyObject* type, PyObject* args, PyObject* kwargs) { 910 Thread* thread = Thread::current(); 911 Runtime* runtime = thread->runtime(); 912 HandleScope scope(thread); 913 914 Object type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(type))); 915 Object args_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(args))); 916 DCHECK(runtime->isInstanceOfTuple(*args_obj), 917 "Slot __new__ expected tuple args"); 918 Object kwargs_obj(&scope, kwargs ? ApiHandle::asObject(ApiHandle::fromPyObject(kwargs)) 919 : NoneType::object()); 920 DCHECK(kwargs == nullptr || runtime->isInstanceOfDict(*kwargs_obj), 921 "Slot __new__ expected nullptr or dict kwargs"); 922 923 // Construct a new args tuple with type at the front. 924 Tuple args_tuple(&scope, tupleUnderlying(*args_obj)); 925 MutableTuple new_args(&scope, 926 runtime->newMutableTuple(args_tuple.length() + 1)); 927 new_args.atPut(0, *type_obj); 928 new_args.replaceFromWith(1, *args_tuple, args_tuple.length()); 929 930 // Call type.__new__(type, *args, **kwargs) 931 Object dunder_new(&scope, 932 runtime->attributeAtById(thread, type_obj, ID(__new__))); 933 if (dunder_new.isError()) return nullptr; 934 thread->stackPush(*dunder_new); 935 thread->stackPush(new_args.becomeImmutable()); 936 word flags = 0; 937 if (kwargs != nullptr) { 938 thread->stackPush(*kwargs_obj); 939 flags = CallFunctionExFlag::VAR_KEYWORDS; 940 } 941 Object result(&scope, Interpreter::callEx(thread, flags)); 942 if (result.isError()) return nullptr; 943 return ApiHandle::newReference(runtime, *result); 944} 945 946// Return a default slot wrapper for the given slot, or abort if it's not yet 947// supported. 948// 949// This performs similar duties to update_one_slot() in CPython, but it's 950// drastically simpler. This is intentional, and will only change if a real C 951// extension exercises slots in a way that exposes the differences. 952static void* defaultSlot(int slot_id) { 953 switch (slot_id) { 954 case Py_tp_new: 955 return reinterpret_cast<void*>(&slotTpNew); 956 default: 957 UNIMPLEMENTED("Unsupported default slot %d", slot_id); 958 } 959} 960 961static int emptyClear(PyObject*) { return 0; } 962 963static int emptyTraverse(PyObject*, visitproc, void*) { return 0; } 964 965static void builtinDealloc(PyObject* self) { 966 // This function is called for instances of non-heaptypes (most builtin types) 967 // or subclasses of them. There is nothing to deallocate/free for 968 // instances of builtin types. However subclasses may have extra data 969 // allocated that needs to be freed with `PyObject_Del`. 970 Thread* thread = Thread::current(); 971 Runtime* runtime = thread->runtime(); 972 HandleScope scope(thread); 973 Object self_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(self))); 974 Type type(&scope, runtime->typeOf(*self_obj)); 975 if (type.hasNativeData()) { 976 PyObject_Del(self); 977 } 978} 979 980PY_EXPORT void* PyType_GetSlot(PyTypeObject* type_obj, int slot_id) { 981 Thread* thread = Thread::current(); 982 if (slot_id < 0) { 983 thread->raiseBadInternalCall(); 984 return nullptr; 985 } 986 987 HandleScope scope(thread); 988 ApiHandle* handle = ApiHandle::fromPyTypeObject(type_obj); 989 Type type(&scope, ApiHandle::asObjectNoImmediate(handle)); 990 if (!type.isCPythonHeaptype()) { 991 if (slot_id == Py_tp_new) { 992 return reinterpret_cast<void*>(&superclassTpNew); 993 } 994 if (slot_id == Py_tp_clear) { 995 return reinterpret_cast<void*>(&emptyClear); 996 } 997 if (slot_id == Py_tp_traverse) { 998 return reinterpret_cast<void*>(&emptyTraverse); 999 } 1000 if (slot_id == Py_tp_dealloc) { 1001 return reinterpret_cast<void*>(&builtinDealloc); 1002 } 1003 thread->raiseBadInternalCall(); 1004 return nullptr; 1005 } 1006 1007 // Extension module requesting slot from a future version 1008 if (!isValidSlotId(slot_id)) { 1009 return nullptr; 1010 } 1011 1012 if (!typeHasSlots(type)) { 1013 // The Type was not created by PyType_FromSpec(), so return a default slot 1014 // implementation that delegates to managed methods. 1015 return defaultSlot(slot_id); 1016 } 1017 if (isObjectSlotId(slot_id)) { 1018 return ApiHandle::borrowedReference(thread->runtime(), 1019 typeSlotObjectAt(type, slot_id)); 1020 } 1021 1022 return typeSlotAt(type, slot_id); 1023} 1024 1025PY_EXPORT int PyType_Ready(PyTypeObject*) { 1026 UNIMPLEMENTED("This function will never be implemented"); 1027} 1028 1029PY_EXPORT PyObject* PyType_FromSpec(PyType_Spec* spec) { 1030 return PyType_FromSpecWithBases(spec, nullptr); 1031} 1032 1033static RawObject memberGetter(Thread* thread, PyMemberDef* member) { 1034 HandleScope scope(thread); 1035 Runtime* runtime = thread->runtime(); 1036 Object name(&scope, runtime->newStrFromCStr(member->name)); 1037 Int offset(&scope, runtime->newInt(member->offset)); 1038 switch (member->type) { 1039 case T_BOOL: 1040 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_bool), 1041 offset); 1042 case T_BYTE: 1043 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_byte), 1044 offset); 1045 case T_UBYTE: 1046 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_ubyte), 1047 offset); 1048 case T_SHORT: 1049 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_short), 1050 offset); 1051 case T_USHORT: 1052 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_ushort), 1053 offset); 1054 case T_INT: 1055 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_int), 1056 offset); 1057 case T_UINT: 1058 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_uint), 1059 offset); 1060 case T_LONG: 1061 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_long), 1062 offset); 1063 case T_ULONG: 1064 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_ulong), 1065 offset); 1066 case T_PYSSIZET: 1067 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_ulong), 1068 offset); 1069 case T_FLOAT: 1070 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_float), 1071 offset); 1072 case T_DOUBLE: 1073 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_double), 1074 offset); 1075 case T_LONGLONG: 1076 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_long), 1077 offset); 1078 case T_ULONGLONG: 1079 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_ulong), 1080 offset); 1081 case T_STRING: 1082 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_string), 1083 offset); 1084 case T_STRING_INPLACE: 1085 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_string), 1086 offset); 1087 case T_CHAR: 1088 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_char), 1089 offset); 1090 case T_OBJECT: 1091 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_pyobject), 1092 offset); 1093 case T_OBJECT_EX: 1094 return thread->invokeFunction2(ID(builtins), ID(_new_member_get_pyobject), 1095 offset, name); 1096 case T_NONE: 1097 return thread->invokeFunction1(ID(builtins), ID(_new_member_get_pyobject), 1098 offset); 1099 default: 1100 return thread->raiseWithFmt(LayoutId::kSystemError, 1101 "bad member name type"); 1102 } 1103} 1104 1105static RawObject memberSetter(Thread* thread, PyMemberDef* member) { 1106 HandleScope scope(thread); 1107 Runtime* runtime = thread->runtime(); 1108 if (member->flags & READONLY) { 1109 Object name(&scope, runtime->newStrFromCStr(member->name)); 1110 Function setter( 1111 &scope, thread->invokeFunction1(ID(builtins), 1112 ID(_new_member_set_readonly), name)); 1113 return *setter; 1114 } 1115 1116 Int offset(&scope, runtime->newInt(member->offset)); 1117 switch (member->type) { 1118 case T_BOOL: 1119 return thread->invokeFunction1(ID(builtins), ID(_new_member_set_bool), 1120 offset); 1121 case T_BYTE: { 1122 Int num_bytes(&scope, runtime->newInt(sizeof(char))); 1123 Int min_value(&scope, runtime->newInt(std::numeric_limits<char>::min())); 1124 Int max_value(&scope, runtime->newInt(std::numeric_limits<char>::max())); 1125 Str primitive_type(&scope, runtime->newStrFromCStr("char")); 1126 Function setter(&scope, 1127 thread->invokeFunction5( 1128 ID(builtins), ID(_new_member_set_integral), offset, 1129 num_bytes, min_value, max_value, primitive_type)); 1130 return *setter; 1131 } 1132 case T_UBYTE: { 1133 Int num_bytes(&scope, runtime->newInt(sizeof(unsigned char))); 1134 Int max_value(&scope, runtime->newIntFromUnsigned( 1135 std::numeric_limits<unsigned char>::max())); 1136 Str primitive_type(&scope, runtime->newStrFromCStr("unsigned char")); 1137 Function setter(&scope, 1138 thread->invokeFunction4( 1139 ID(builtins), ID(_new_member_set_integral_unsigned), 1140 offset, num_bytes, max_value, primitive_type)); 1141 return *setter; 1142 } 1143 case T_SHORT: { 1144 Int num_bytes(&scope, runtime->newInt(sizeof(short))); 1145 Int min_value(&scope, runtime->newInt(std::numeric_limits<short>::min())); 1146 Int max_value(&scope, runtime->newInt(std::numeric_limits<short>::max())); 1147 Str primitive_type(&scope, runtime->newStrFromCStr("short")); 1148 Function setter(&scope, 1149 thread->invokeFunction5( 1150 ID(builtins), ID(_new_member_set_integral), offset, 1151 num_bytes, min_value, max_value, primitive_type)); 1152 return *setter; 1153 } 1154 case T_USHORT: { 1155 Int num_bytes(&scope, runtime->newInt(sizeof(unsigned short))); 1156 Int max_value(&scope, runtime->newIntFromUnsigned( 1157 std::numeric_limits<unsigned short>::max())); 1158 Str primitive_type(&scope, runtime->newStrFromCStr("unsigned short")); 1159 Function setter(&scope, 1160 thread->invokeFunction4( 1161 ID(builtins), ID(_new_member_set_integral_unsigned), 1162 offset, num_bytes, max_value, primitive_type)); 1163 return *setter; 1164 } 1165 case T_INT: { 1166 Int num_bytes(&scope, runtime->newInt(sizeof(int))); 1167 Int min_value(&scope, runtime->newInt(std::numeric_limits<int>::min())); 1168 Int max_value(&scope, runtime->newInt(std::numeric_limits<int>::max())); 1169 Str primitive_type(&scope, runtime->newStrFromCStr("int")); 1170 Function setter(&scope, 1171 thread->invokeFunction5( 1172 ID(builtins), ID(_new_member_set_integral), offset, 1173 num_bytes, min_value, max_value, primitive_type)); 1174 return *setter; 1175 } 1176 case T_UINT: { 1177 Int num_bytes(&scope, runtime->newInt(sizeof(unsigned int))); 1178 Int max_value(&scope, runtime->newIntFromUnsigned( 1179 std::numeric_limits<unsigned int>::max())); 1180 Str primitive_type(&scope, runtime->newStrFromCStr("unsigned int")); 1181 Function setter(&scope, 1182 thread->invokeFunction4( 1183 ID(builtins), ID(_new_member_set_integral_unsigned), 1184 offset, num_bytes, max_value, primitive_type)); 1185 return *setter; 1186 } 1187 case T_LONG: { 1188 Int num_bytes(&scope, runtime->newInt(sizeof(long))); 1189 Int min_value(&scope, runtime->newInt(std::numeric_limits<long>::min())); 1190 Int max_value(&scope, runtime->newInt(std::numeric_limits<long>::max())); 1191 Str primitive_type(&scope, runtime->newStrFromCStr("long")); 1192 Function setter(&scope, 1193 thread->invokeFunction5( 1194 ID(builtins), ID(_new_member_set_integral), offset, 1195 num_bytes, min_value, max_value, primitive_type)); 1196 return *setter; 1197 } 1198 case T_ULONG: { 1199 Int num_bytes(&scope, runtime->newInt(sizeof(unsigned long))); 1200 Int max_value(&scope, runtime->newIntFromUnsigned( 1201 std::numeric_limits<unsigned long>::max())); 1202 Str primitive_type(&scope, runtime->newStrFromCStr("unsigned long")); 1203 Function setter(&scope, 1204 thread->invokeFunction4( 1205 ID(builtins), ID(_new_member_set_integral_unsigned), 1206 offset, num_bytes, max_value, primitive_type)); 1207 return *setter; 1208 } 1209 case T_PYSSIZET: { 1210 Int num_bytes(&scope, runtime->newInt(sizeof(Py_ssize_t))); 1211 Int min_value(&scope, SmallInt::fromWord(0)); 1212 Int max_value(&scope, 1213 runtime->newInt(std::numeric_limits<Py_ssize_t>::max())); 1214 Str primitive_type(&scope, runtime->newStrFromCStr("Py_ssize_t")); 1215 Function setter(&scope, 1216 thread->invokeFunction5( 1217 ID(builtins), ID(_new_member_set_integral), offset, 1218 num_bytes, min_value, max_value, primitive_type)); 1219 return *setter; 1220 } 1221 case T_FLOAT: { 1222 return thread->invokeFunction1(ID(builtins), ID(_new_member_set_float), 1223 offset); 1224 } 1225 case T_DOUBLE: { 1226 return thread->invokeFunction1(ID(builtins), ID(_new_member_set_double), 1227 offset); 1228 } 1229 case T_STRING: { 1230 Object name(&scope, runtime->newStrFromCStr(member->name)); 1231 Function setter(&scope, thread->invokeFunction1( 1232 ID(builtins), 1233 ID(_new_member_set_readonly_strings), name)); 1234 return *setter; 1235 } 1236 case T_STRING_INPLACE: { 1237 Object name(&scope, runtime->newStrFromCStr(member->name)); 1238 Function setter(&scope, thread->invokeFunction1( 1239 ID(builtins), 1240 ID(_new_member_set_readonly_strings), name)); 1241 return *setter; 1242 } 1243 case T_CHAR: { 1244 Function setter( 1245 &scope, thread->invokeFunction1(ID(builtins), 1246 ID(_new_member_set_char), offset)); 1247 return *setter; 1248 } 1249 case T_OBJECT: { 1250 Function setter(&scope, 1251 thread->invokeFunction1( 1252 ID(builtins), ID(_new_member_set_pyobject), offset)); 1253 return *setter; 1254 } 1255 case T_OBJECT_EX: { 1256 Function setter(&scope, 1257 thread->invokeFunction1( 1258 ID(builtins), ID(_new_member_set_pyobject), offset)); 1259 return *setter; 1260 } 1261 case T_LONGLONG: { 1262 Int num_bytes(&scope, runtime->newInt(sizeof(long long))); 1263 Int min_value(&scope, 1264 runtime->newInt(std::numeric_limits<long long>::min())); 1265 Int max_value(&scope, 1266 runtime->newInt(std::numeric_limits<long long>::max())); 1267 Str primitive_type(&scope, runtime->newStrFromCStr("long long")); 1268 Function setter(&scope, 1269 thread->invokeFunction5( 1270 ID(builtins), ID(_new_member_set_integral), offset, 1271 num_bytes, min_value, max_value, primitive_type)); 1272 return *setter; 1273 } 1274 case T_ULONGLONG: { 1275 Int num_bytes(&scope, runtime->newInt(sizeof(unsigned long long))); 1276 Int max_value(&scope, 1277 runtime->newIntFromUnsigned( 1278 std::numeric_limits<unsigned long long>::max())); 1279 Str primitive_type(&scope, runtime->newStrFromCStr("unsigned long long")); 1280 Function setter(&scope, 1281 thread->invokeFunction4( 1282 ID(builtins), ID(_new_member_set_integral_unsigned), 1283 offset, num_bytes, max_value, primitive_type)); 1284 return *setter; 1285 } 1286 default: 1287 return thread->raiseWithFmt(LayoutId::kSystemError, 1288 "bad member name type"); 1289 } 1290} 1291 1292static RawObject addMethods(Thread* thread, const Type& type) { 1293 HandleScope scope(thread); 1294 PyMethodDef* methods = 1295 static_cast<PyMethodDef*>(typeSlotAt(type, Py_tp_methods)); 1296 if (methods == nullptr) return NoneType::object(); 1297 Object none(&scope, NoneType::object()); 1298 Object unbound(&scope, Unbound::object()); 1299 Object name(&scope, NoneType::object()); 1300 Object member(&scope, NoneType::object()); 1301 for (PyMethodDef* method = methods; method->ml_name != nullptr; method++) { 1302 name = Runtime::internStrFromCStr(thread, method->ml_name); 1303 int flags = method->ml_flags; 1304 if (!(flags & METH_COEXIST) && !typeAt(type, name).isErrorNotFound()) { 1305 continue; 1306 } 1307 if (flags & METH_CLASS) { 1308 if (flags & METH_STATIC) { 1309 return thread->raiseWithFmt(LayoutId::kValueError, 1310 "method cannot be both class and static"); 1311 } 1312 member = newClassMethod(thread, method, name, type); 1313 } else if (flags & METH_STATIC) { 1314 member = newCFunction(thread, method, name, unbound, none); 1315 } else { 1316 member = newMethod(thread, method, name, type); 1317 } 1318 typeAtPut(thread, type, name, member); 1319 } 1320 return NoneType::object(); 1321} 1322 1323static RawObject addMembers(Thread* thread, const Type& type, 1324 PyMemberDef* members) { 1325 if (members == nullptr) return NoneType::object(); 1326 HandleScope scope(thread); 1327 Object none(&scope, NoneType::object()); 1328 Runtime* runtime = thread->runtime(); 1329 Object getter(&scope, NoneType::object()); 1330 Object setter(&scope, NoneType::object()); 1331 Object property(&scope, NoneType::object()); 1332 Object name_obj(&scope, NoneType::object()); 1333 for (PyMemberDef* member = members; member->name != nullptr; member++) { 1334 const char* name = member->name; 1335 if (std::strcmp(name, "__dictoffset__") == 0 || 1336 std::strcmp(name, "__weaklistoffset__") == 0) { 1337 continue; 1338 } 1339 getter = memberGetter(thread, member); 1340 if (getter.isErrorException()) return *getter; 1341 setter = memberSetter(thread, member); 1342 if (setter.isErrorException()) return *setter; 1343 property = runtime->newProperty(getter, setter, none); 1344 name_obj = Runtime::internStrFromCStr(thread, name); 1345 typeAtPut(thread, type, name_obj, property); 1346 } 1347 return NoneType::object(); 1348} 1349 1350static RawObject addGetSet(Thread* thread, const Type& type) { 1351 HandleScope scope(thread); 1352 PyGetSetDef* getsets = 1353 static_cast<PyGetSetDef*>(typeSlotAt(type, Py_tp_getset)); 1354 if (getsets == nullptr) return NoneType::object(); 1355 for (word i = 0; getsets[i].name != nullptr; i++) { 1356 Object name(&scope, Runtime::internStrFromCStr(thread, getsets[i].name)); 1357 Object property(&scope, newGetSet(thread, name, &getsets[i])); 1358 typeAtPut(thread, type, name, property); 1359 } 1360 return NoneType::object(); 1361} 1362 1363// The default tp_dealloc slot for all C Types. This loosely follows CPython's 1364// subtype_dealloc. 1365static void subtypeDealloc(PyObject* self) { 1366 Thread* thread = Thread::current(); 1367 Runtime* runtime = thread->runtime(); 1368 HandleScope scope(thread); 1369 Object self_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(self))); 1370 Type type(&scope, runtime->typeOf(*self_obj)); 1371 1372 DCHECK(type.isCPythonHeaptype(), "must be called with heaptype"); 1373 1374 void* finalize_func = typeSlotAt(type, Py_tp_finalize); 1375 if (finalize_func != nullptr) { 1376 if (PyObject_CallFinalizerFromDealloc(self) < 0) { 1377 // Resurrected 1378 return; 1379 } 1380 } 1381 1382 destructor del_func = 1383 reinterpret_cast<destructor>(typeSlotAt(type, Py_tp_del)); 1384 if (del_func != nullptr) { 1385 (*del_func)(self); 1386 if (Py_REFCNT(self) > 1) { 1387 // Resurrected 1388 return; 1389 } 1390 } 1391 destructor base_dealloc = subtypeDealloc; 1392 Type base_type(&scope, *type); 1393 while (base_dealloc == subtypeDealloc) { 1394 base_type = typeSlotObjectAt(base_type, Py_tp_base); 1395 if (typeHasSlots(base_type)) { 1396 base_dealloc = 1397 reinterpret_cast<destructor>(typeSlotAt(base_type, Py_tp_dealloc)); 1398 } else { 1399 base_dealloc = reinterpret_cast<destructor>(PyObject_Del); 1400 } 1401 } 1402 type = runtime->typeOf(*self_obj); 1403 (*base_dealloc)(self); 1404 if (type.isCPythonHeaptype() && !base_type.isCPythonHeaptype()) { 1405 ApiHandle::decref(ApiHandle::borrowedReference(runtime, *type)); 1406 } 1407} 1408 1409// Copy the slot from the base type if it defined. 1410static void copySlot(Thread* thread, const Type& type, const Type& base, 1411 int slot_id) { 1412 if (typeSlotAt(type, slot_id) != nullptr) return; 1413 void* base_slot = typeSlotAt(base, slot_id); 1414 typeSlotAtPut(thread, type, slot_id, base_slot); 1415} 1416 1417static void* baseBaseSlot(Thread* thread, const Type& base, int slot_id) { 1418 if (typeSlotObjectAt(base, Py_tp_base) != SmallInt::fromWord(0)) { 1419 return nullptr; 1420 } 1421 HandleScope scope(thread); 1422 Type basebase(&scope, typeSlotObjectAt(base, Py_tp_base)); 1423 if (!typeHasSlots(basebase)) return nullptr; 1424 return typeSlotAt(basebase, slot_id); 1425} 1426 1427// Copy the slot from the base type if defined and it is the first type that 1428// defines it. If base's base type defines the same slot, then base inherited 1429// it. Thus, it is not the first type to define it. 1430static void copySlotIfImplementedInBase(Thread* thread, const Type& type, 1431 const Type& base, int slot_id) { 1432 if (typeSlotAt(type, slot_id) != nullptr) return; 1433 void* base_slot = typeSlotAt(base, slot_id); 1434 if (base_slot != nullptr) { 1435 void* basebase_slot = baseBaseSlot(thread, base, slot_id); 1436 if (basebase_slot == nullptr || base_slot != basebase_slot) { 1437 typeSlotAtPut(thread, type, slot_id, base_slot); 1438 } 1439 } 1440} 1441 1442static void inheritFree(Thread* thread, const Type& type, 1443 unsigned long type_flags, const Type& base, 1444 unsigned long base_flags) { 1445 // Both child and base are GC or non GC 1446 if ((type_flags & Py_TPFLAGS_HAVE_GC) == (base_flags & Py_TPFLAGS_HAVE_GC)) { 1447 copySlotIfImplementedInBase(thread, type, base, Py_tp_free); 1448 return; 1449 } 1450 1451 DCHECK(!(base_flags & Py_TPFLAGS_HAVE_GC), "The child should not remove GC"); 1452 1453 // Only the child is GC 1454 // Set the free function if the base has a default free 1455 if ((type_flags & Py_TPFLAGS_HAVE_GC) && 1456 typeSlotAt(type, Py_tp_free) == nullptr) { 1457 if (typeSlotAt(base, Py_tp_free) == 1458 reinterpret_cast<void*>(&PyObject_Free)) { 1459 typeSlotAtPut(thread, type, Py_tp_free, 1460 reinterpret_cast<void*>(&PyObject_GC_Del)); 1461 } 1462 } 1463} 1464 1465static void inheritGCFlagsAndSlots(Thread* thread, const Type& type, 1466 const Type& base) { 1467 unsigned long type_flags = typeSlotUWordAt(type, kSlotFlags); 1468 unsigned long base_flags = typeSlotUWordAt(base, kSlotFlags); 1469 if (!(type_flags & Py_TPFLAGS_HAVE_GC) && (base_flags & Py_TPFLAGS_HAVE_GC) && 1470 typeSlotAt(type, Py_tp_traverse) == nullptr && 1471 typeSlotAt(type, Py_tp_clear) == nullptr) { 1472 typeSlotUWordAtPut(thread, type, kSlotFlags, 1473 type_flags | Py_TPFLAGS_HAVE_GC); 1474 copySlot(thread, type, base, Py_tp_traverse); 1475 copySlot(thread, type, base, Py_tp_clear); 1476 } 1477} 1478 1479static void inheritNonFunctionSlots(Thread* thread, const Type& type, 1480 const Type& base) { 1481 if (typeSlotUWordAt(type, kSlotBasicSize) == 0) { 1482 typeSlotUWordAtPut(thread, type, kSlotBasicSize, 1483 typeSlotUWordAt(base, kSlotBasicSize)); 1484 } 1485 typeSlotUWordAtPut(thread, type, kSlotItemSize, 1486 typeSlotUWordAt(base, kSlotItemSize)); 1487} 1488 1489// clang-format off 1490static const int kInheritableSlots[] = { 1491 // Number slots 1492 Py_nb_add, 1493 Py_nb_subtract, 1494 Py_nb_multiply, 1495 Py_nb_remainder, 1496 Py_nb_divmod, 1497 Py_nb_power, 1498 Py_nb_negative, 1499 Py_nb_positive, 1500 Py_nb_absolute, 1501 Py_nb_bool, 1502 Py_nb_invert, 1503 Py_nb_lshift, 1504 Py_nb_rshift, 1505 Py_nb_and, 1506 Py_nb_xor, 1507 Py_nb_or, 1508 Py_nb_int, 1509 Py_nb_float, 1510 Py_nb_inplace_add, 1511 Py_nb_inplace_subtract, 1512 Py_nb_inplace_multiply, 1513 Py_nb_inplace_remainder, 1514 Py_nb_inplace_power, 1515 Py_nb_inplace_lshift, 1516 Py_nb_inplace_rshift, 1517 Py_nb_inplace_and, 1518 Py_nb_inplace_xor, 1519 Py_nb_inplace_or, 1520 Py_nb_true_divide, 1521 Py_nb_floor_divide, 1522 Py_nb_inplace_true_divide, 1523 Py_nb_inplace_floor_divide, 1524 Py_nb_index, 1525 Py_nb_matrix_multiply, 1526 Py_nb_inplace_matrix_multiply, 1527 1528 // Await slots 1529 Py_am_await, 1530 Py_am_aiter, 1531 Py_am_anext, 1532 1533 // Sequence slots 1534 Py_sq_length, 1535 Py_sq_concat, 1536 Py_sq_repeat, 1537 Py_sq_item, 1538 Py_sq_ass_item, 1539 Py_sq_contains, 1540 Py_sq_inplace_concat, 1541 Py_sq_inplace_repeat, 1542 1543 // Mapping slots 1544 Py_mp_length, 1545 Py_mp_subscript, 1546 Py_mp_ass_subscript, 1547 1548 // Buffer protocol is not part of PEP-384 1549 1550 // Type slots 1551 Py_tp_dealloc, 1552 Py_tp_repr, 1553 Py_tp_call, 1554 Py_tp_str, 1555 Py_tp_iter, 1556 Py_tp_iternext, 1557 Py_tp_descr_get, 1558 Py_tp_descr_set, 1559 Py_tp_init, 1560 Py_tp_alloc, 1561 Py_tp_is_gc, 1562 Py_tp_finalize, 1563 1564 // Instance dictionary is not part of PEP-384 1565 1566 // Weak reference support is not part of PEP-384 1567}; 1568// clang-format on 1569 1570static int typeSetattro(PyTypeObject* type, PyObject* name, PyObject* value) { 1571 DCHECK(PyType_GetFlags(type) & Py_TPFLAGS_HEAPTYPE, 1572 "typeSetattro requires an instance from a heap allocated C " 1573 "extension type"); 1574 Thread* thread = Thread::current(); 1575 HandleScope scope(thread); 1576 Type type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyTypeObject(type))); 1577 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name))); 1578 Object value_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(value))); 1579 if (thread 1580 ->invokeMethodStatic3(LayoutId::kType, ID(__setattr__), type_obj, 1581 name_obj, value_obj) 1582 .isError()) { 1583 return -1; 1584 } 1585 return 0; 1586} 1587 1588static void inheritSlots(Thread* thread, const Type& type, const Type& base) { 1589 // Heap allocated types are guaranteed to have slot space, no check is needed 1590 // i.e. CPython does: `if (type->tp_as_number != NULL)` 1591 // Only static types need to do this type of check. 1592 for (int slot_id : kInheritableSlots) { 1593 copySlotIfImplementedInBase(thread, type, base, slot_id); 1594 } 1595 1596 // Inherit conditional type slots 1597 if (typeSlotAt(type, Py_tp_getattr) == nullptr && 1598 typeSlotAt(type, Py_tp_getattro) == nullptr) { 1599 copySlot(thread, type, base, Py_tp_getattr); 1600 copySlot(thread, type, base, Py_tp_getattro); 1601 } 1602 if (typeSlotAt(type, Py_tp_setattr) == nullptr && 1603 typeSlotAt(type, Py_tp_setattro) == nullptr) { 1604 copySlot(thread, type, base, Py_tp_setattr); 1605 copySlot(thread, type, base, Py_tp_setattro); 1606 } 1607 if (typeSlotAt(type, Py_tp_richcompare) == nullptr && 1608 typeSlotAt(type, Py_tp_hash) == nullptr) { 1609 copySlot(thread, type, base, Py_tp_richcompare); 1610 copySlot(thread, type, base, Py_tp_hash); 1611 } 1612 1613 unsigned long type_flags = typeSlotUWordAt(type, kSlotFlags); 1614 unsigned long base_flags = typeSlotUWordAt(base, kSlotFlags); 1615 inheritFree(thread, type, type_flags, base, base_flags); 1616} 1617 1618static int objectInit(PyObject*, PyObject*, PyObject*) { 1619 UNIMPLEMENTED("should not directly call tp_init"); 1620} 1621 1622static RawObject addDefaultsForRequiredSlots(Thread* thread, const Type& type, 1623 const Type& base) { 1624 Runtime* runtime = thread->runtime(); 1625 HandleScope scope(thread); 1626 Str type_name(&scope, type.name()); 1627 1628 // tp_basicsize -> sizeof(PyObject) 1629 uword basic_size = typeSlotUWordAt(type, kSlotBasicSize); 1630 if (basic_size == 0) { 1631 basic_size = sizeof(PyObject); 1632 typeSlotUWordAtPut(thread, type, kSlotBasicSize, basic_size); 1633 } 1634 DCHECK(basic_size >= sizeof(PyObject), 1635 "sizeof(PyObject) is the minimum size required for an extension " 1636 "instance"); 1637 1638 // tp_repr -> PyObject_Repr 1639 if (typeSlotAt(type, Py_tp_repr) == nullptr) { 1640 typeSlotAtPut(thread, type, Py_tp_repr, 1641 reinterpret_cast<void*>(&PyObject_Repr)); 1642 // PyObject_Repr delegates its job to type.__repr__(). 1643 DCHECK(!typeLookupInMroById(thread, *type, ID(__repr__)).isErrorNotFound(), 1644 "__repr__ is expected"); 1645 } 1646 1647 // tp_str -> object_str 1648 if (typeSlotAt(type, Py_tp_str) == nullptr) { 1649 typeSlotAtPut(thread, type, Py_tp_str, 1650 reinterpret_cast<void*>(&PyObject_Str)); 1651 // PyObject_Str delegates its job to type.__str__(). 1652 DCHECK(!typeLookupInMroById(thread, *type, ID(__str__)).isErrorNotFound(), 1653 "__str__ is expected"); 1654 } 1655 1656 // tp_init -> object_init 1657 if (typeSlotAt(type, Py_tp_init) == nullptr) { 1658 typeSlotAtPut(thread, type, Py_tp_init, 1659 reinterpret_cast<void*>(&objectInit)); 1660 } 1661 1662 // tp_alloc -> PyType_GenericAlloc 1663 if (typeSlotAt(type, Py_tp_alloc) == nullptr) { 1664 typeSlotAtPut(thread, type, Py_tp_alloc, 1665 reinterpret_cast<void*>(&PyType_GenericAlloc)); 1666 } 1667 1668 // tp_new -> PyType_GenericNew 1669 if (typeSlotAt(type, Py_tp_new) == nullptr) { 1670 void* new_func = reinterpret_cast<void*>(&superclassTpNew); 1671 typeSlotAtPut(thread, type, Py_tp_new, new_func); 1672 1673 Str dunder_new_name(&scope, runtime->symbols()->at(ID(__new__))); 1674 Str qualname(&scope, 1675 runtime->newStrFromFmt("%S.%S", &type_name, &dunder_new_name)); 1676 Code code(&scope, 1677 newExtCode(thread, dunder_new_name, kParamsTypeArgsKwargs, 1678 Code::Flags::kVarargs | Code::Flags::kVarkeyargs, 1679 wrapTpNew, new_func)); 1680 Object globals(&scope, NoneType::object()); 1681 Function func( 1682 &scope, runtime->newFunctionWithCode(thread, qualname, code, globals)); 1683 slotWrapperFunctionSetType(func, type); 1684 Object func_obj( 1685 &scope, thread->invokeFunction1(ID(builtins), ID(staticmethod), func)); 1686 if (func_obj.isError()) return *func; 1687 typeAtPutById(thread, type, ID(__new__), func_obj); 1688 } 1689 1690 // tp_free. 1691 if (typeSlotAt(type, Py_tp_free) == nullptr) { 1692 unsigned long type_flags = typeSlotUWordAt(type, kSlotFlags); 1693 freefunc func = 1694 (type_flags & Py_TPFLAGS_HAVE_GC) ? &PyObject_GC_Del : &PyObject_Del; 1695 typeSlotAtPut(thread, type, Py_tp_free, reinterpret_cast<void*>(func)); 1696 } 1697 1698 // tp_setattro 1699 if (typeSlotAt(type, Py_tp_setattr) == nullptr && 1700 typeSlotAt(type, Py_tp_setattro) == nullptr) { 1701 if (typeIsSubclass(*base, runtime->typeAt(LayoutId::kType))) { 1702 typeSlotAtPut(thread, type, Py_tp_setattro, 1703 reinterpret_cast<void*>(typeSetattro)); 1704 } 1705 } 1706 1707 return NoneType::object(); 1708} 1709 1710RawObject typeInheritSlots(Thread* thread, const Type& type, const Type& base) { 1711 HandleScope scope(thread); 1712 1713 if (!typeHasSlots(type)) { 1714 typeSlotsAllocate(thread, type); 1715 unsigned long flags = typeGetFlags(base); 1716 if (type.hasFlag(Type::Flag::kHasCycleGC)) flags |= Py_TPFLAGS_HAVE_GC; 1717 if (type.hasFlag(Type::Flag::kIsBasetype)) flags |= Py_TPFLAGS_BASETYPE; 1718 if (type.hasFlag(Type::Flag::kIsCPythonHeaptype)) { 1719 flags |= Py_TPFLAGS_HEAPTYPE; 1720 } 1721 typeSlotUWordAtPut(thread, type, kSlotFlags, flags); 1722 uword basicsize = typeGetBasicSize(base); 1723 typeSlotUWordAtPut(thread, type, kSlotBasicSize, basicsize); 1724 typeSlotUWordAtPut(thread, type, kSlotItemSize, 0); 1725 typeSlotObjectAtPut(type, Py_tp_base, *base); 1726 } 1727 1728 // Inherit special slots from dominant base 1729 if (typeHasSlots(base)) { 1730 inheritGCFlagsAndSlots(thread, type, base); 1731 if (typeSlotAt(type, Py_tp_new) == nullptr) { 1732 copySlot(thread, type, base, Py_tp_new); 1733 } 1734 inheritNonFunctionSlots(thread, type, base); 1735 } 1736 1737 // Inherit slots from the MRO 1738 Tuple mro(&scope, type.mro()); 1739 for (word i = 1; i < mro.length(); i++) { 1740 Type mro_entry(&scope, mro.at(i)); 1741 // Skip inheritance if mro_entry does not define slots 1742 if (!typeHasSlots(mro_entry)) continue; 1743 inheritSlots(thread, type, mro_entry); 1744 } 1745 1746 // Inherit all the default slots that would have been inherited 1747 // through the base object type in CPython 1748 Object result(&scope, addDefaultsForRequiredSlots(thread, type, base)); 1749 if (result.isError()) return *result; 1750 1751 return NoneType::object(); 1752} 1753 1754PY_EXPORT PyObject* PyType_FromSpecWithBases(PyType_Spec* spec, 1755 PyObject* bases) { 1756 Thread* thread = Thread::current(); 1757 Runtime* runtime = thread->runtime(); 1758 HandleScope scope(thread); 1759 1760 // Define the type name 1761 Object module_name(&scope, NoneType::object()); 1762 const char* class_name = strrchr(spec->name, '.'); 1763 if (class_name == nullptr) { 1764 class_name = spec->name; 1765 } else { 1766 module_name = Runtime::internStrFromAll( 1767 thread, View<byte>(reinterpret_cast<const byte*>(spec->name), 1768 class_name - spec->name)); 1769 class_name++; 1770 } 1771 Str type_name(&scope, Runtime::internStrFromCStr(thread, class_name)); 1772 1773 // Create a new type for the PyTypeObject with an instance layout 1774 // matching the layout of RawNativeProxy 1775 // TODO(T54277314): Fill the dictionary before creating the type 1776 Tuple bases_obj(&scope, runtime->implicitBases()); 1777 if (bases != nullptr) bases_obj = ApiHandle::asObject(ApiHandle::fromPyObject(bases)); 1778 Dict dict(&scope, runtime->newDict()); 1779 if (!module_name.isNoneType()) { 1780 dictAtPutById(thread, dict, ID(__module__), module_name); 1781 } 1782 dictAtPutById(thread, dict, ID(__qualname__), type_name); 1783 1784 bool has_default_dealloc = true; 1785 for (PyType_Slot* slot = spec->slots; slot->slot; slot++) { 1786 int slot_id = slot->slot; 1787 if (!isValidSlotId(slot_id)) { 1788 thread->raiseWithFmt(LayoutId::kRuntimeError, "invalid slot offset"); 1789 return nullptr; 1790 } 1791 switch (slot_id) { 1792 case Py_tp_dealloc: 1793 case Py_tp_del: 1794 case Py_tp_finalize: 1795 has_default_dealloc = false; 1796 break; 1797 case Py_tp_setattr: 1798 UNIMPLEMENTED("Py_tp_setattr not supported"); 1799 } 1800 } 1801 1802 word flags = Type::Flag::kIsCPythonHeaptype; 1803 // We allocate a heap object in the C heap space only when 1) we need to 1804 // execute a custom finalizer with it or 2) the type explicitly uses non-zero 1805 // sizes to store a user-specified structure. 1806 if (!has_default_dealloc || 1807 static_cast<size_t>(spec->basicsize) > sizeof(PyObject) || 1808 spec->itemsize > 0) { 1809 flags |= Type::Flag::kHasNativeData; 1810 } 1811 if (spec->flags & Py_TPFLAGS_HAVE_GC) { 1812 flags |= Type::Flag::kHasCycleGC; 1813 } 1814 if (spec->flags & Py_TPFLAGS_BASETYPE) { 1815 flags |= Type::Flag::kIsBasetype; 1816 } 1817 1818 Object fixed_attr_base_obj(&scope, 1819 computeFixedAttributeBase(thread, bases_obj)); 1820 if (fixed_attr_base_obj.isErrorException()) return nullptr; 1821 Type fixed_attr_base(&scope, *fixed_attr_base_obj); 1822 1823 word base_size = typeGetBasicSize(fixed_attr_base); 1824 if (spec->basicsize > base_size) { 1825 flags |= Type::Flag::kIsFixedAttributeBase; 1826 } 1827 1828 PyMemberDef* members = nullptr; 1829 word dictoffset = 0; 1830 for (PyType_Slot* slot = spec->slots; slot->slot != 0; slot++) { 1831 if (slot->slot != Py_tp_members) continue; 1832 members = static_cast<PyMemberDef*>(slot->pfunc); 1833 for (PyMemberDef* member = members; member->name != nullptr; member++) { 1834 const char* name = member->name; 1835 if (std::strcmp(name, "__weaklistoffset__") == 0) { 1836 DCHECK(member->type == T_PYSSIZET, "must be T_PYSSIZET"); 1837 DCHECK(member->flags == READONLY, "must be readonly"); 1838 // weaklistoffset not used yet. 1839 } else if (std::strcmp(name, "__dictoffset__") == 0) { 1840 DCHECK(member->type == T_PYSSIZET, "must be T_PYSSIZET"); 1841 DCHECK(member->flags == READONLY, "must be readonly"); 1842 dictoffset = member->offset; 1843 } 1844 } 1845 } 1846 1847 bool add_instance_dict = (dictoffset != 0); 1848 Type metaclass(&scope, runtime->typeAt(LayoutId::kType)); 1849 Object type_obj(&scope, typeNew(thread, metaclass, type_name, bases_obj, dict, 1850 static_cast<Type::Flag>(flags), 1851 /*inherit_slots=*/false, 1852 /*add_instance_dict=*/add_instance_dict)); 1853 if (type_obj.isError()) return nullptr; 1854 Type type(&scope, *type_obj); 1855 1856 // Initialize the extension slots tuple 1857 typeSlotsAllocate(thread, type); 1858 1859 typeSlotObjectAtPut(type, Py_tp_bases, *bases_obj); 1860 typeSlotObjectAtPut(type, Py_tp_base, *fixed_attr_base); 1861 unsigned long extension_flags = 1862 spec->flags | Py_TPFLAGS_READY | Py_TPFLAGS_HEAPTYPE; 1863 typeSlotUWordAtPut(thread, type, kSlotFlags, extension_flags); 1864 typeSlotUWordAtPut(thread, type, kSlotBasicSize, spec->basicsize); 1865 typeSlotUWordAtPut(thread, type, kSlotItemSize, spec->itemsize); 1866 1867 // Set the type slots 1868 for (PyType_Slot* slot = spec->slots; slot->slot; slot++) { 1869 typeSlotAtPut(thread, type, slot->slot, slot->pfunc); 1870 } 1871 if (has_default_dealloc) { 1872 type.setFlags( 1873 static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDefaultDealloc)); 1874 } 1875 1876 // If no custom tp_dealloc is defined set subtypeDealloc 1877 if (typeSlotAt(type, Py_tp_dealloc) == nullptr) { 1878 typeSlotAtPut(thread, type, Py_tp_dealloc, 1879 reinterpret_cast<void*>(&subtypeDealloc)); 1880 } 1881 1882 if (addOperators(thread, type).isError()) return nullptr; 1883 1884 if (addMethods(thread, type).isError()) return nullptr; 1885 1886 if (addMembers(thread, type, members).isErrorException()) return nullptr; 1887 1888 if (addGetSet(thread, type).isError()) return nullptr; 1889 1890 if (typeInheritSlots(thread, type, fixed_attr_base).isError()) return nullptr; 1891 1892 return ApiHandle::newReferenceWithManaged(runtime, *type); 1893} 1894 1895PY_EXPORT PyObject* PyType_GenericAlloc(PyTypeObject* type_obj, 1896 Py_ssize_t nitems) { 1897 Thread* thread = Thread::current(); 1898 HandleScope scope(thread); 1899 Type type(&scope, 1900 ApiHandle::asObjectNoImmediate(ApiHandle::fromPyTypeObject(type_obj))); 1901 DCHECK(!type.isBuiltin(), 1902 "Type is unmanaged. Please initialize using PyType_FromSpec"); 1903 DCHECK(typeHasSlots(type), 1904 "GenericAlloc from types initialized through Python code"); 1905 1906 if (!type.hasNativeData()) { 1907 // Since the type will be pointed to by the layout as long as there are any 1908 // objects of its type, we don't need to INCREF the type object if it 1909 // doesn't have NativeData. 1910 Layout layout(&scope, type.instanceLayout()); 1911 Runtime* runtime = thread->runtime(); 1912 return ApiHandle::newReference(runtime, runtime->newInstance(layout)); 1913 } 1914 PyObject* result = allocatePyObject(type, nitems); 1915 if (result == nullptr) { 1916 thread->raiseMemoryError(); 1917 return nullptr; 1918 } 1919 1920 // Initialize the newly-allocated instance 1921 if (typeSlotUWordAt(type, kSlotItemSize) == 0) { 1922 PyObject_Init(result, type_obj); 1923 } else { 1924 PyObject_InitVar(reinterpret_cast<PyVarObject*>(result), type_obj, nitems); 1925 } 1926 1927 return result; 1928} 1929 1930PY_EXPORT Py_ssize_t _PyObject_SIZE_Func(PyObject* obj) { 1931 HandleScope scope(Thread::current()); 1932 Type type(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 1933 return typeSlotUWordAt(type, kSlotBasicSize); 1934} 1935 1936PY_EXPORT Py_ssize_t _PyObject_VAR_SIZE_Func(PyObject* obj, Py_ssize_t nitems) { 1937 HandleScope scope(Thread::current()); 1938 Type type(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 1939 uword basic_size = typeSlotUWordAt(type, kSlotBasicSize); 1940 uword item_size = typeSlotUWordAt(type, kSlotItemSize); 1941 return Utils::roundUp(nitems * item_size + basic_size, kWordSize); 1942} 1943 1944PY_EXPORT unsigned int PyType_ClearCache() { 1945 UNIMPLEMENTED("PyType_ClearCache"); 1946} 1947 1948PY_EXPORT PyObject* PyType_GenericNew(PyTypeObject* type, PyObject*, 1949 PyObject*) { 1950 auto alloc_func = 1951 reinterpret_cast<allocfunc>(PyType_GetSlot(type, Py_tp_alloc)); 1952 return alloc_func(type, 0); 1953} 1954 1955PY_EXPORT int PyObject_TypeCheck_Func(PyObject* obj, PyTypeObject* type) { 1956 PyTypeObject* obj_type = reinterpret_cast<PyTypeObject*>(PyObject_Type(obj)); 1957 int res = PyType_IsSubtype(obj_type, type); 1958 Py_DECREF(obj_type); 1959 return res; 1960} 1961 1962PY_EXPORT int PyType_IsSubtype(PyTypeObject* a, PyTypeObject* b) { 1963 return a == b || typeIsSubclass(ApiHandle::asObject(ApiHandle::fromPyTypeObject(a)), 1964 ApiHandle::asObject(ApiHandle::fromPyTypeObject(b))) 1965 ? 1 1966 : 0; 1967} 1968 1969PY_EXPORT void PyType_Modified(PyTypeObject* /* e */) { 1970 // We invalidate caches incrementally, so do nothing. 1971} 1972 1973PY_EXPORT PyTypeObject* PyType_Type_Ptr() { 1974 Runtime* runtime = Thread::current()->runtime(); 1975 return reinterpret_cast<PyTypeObject*>( 1976 ApiHandle::borrowedReference(runtime, runtime->typeAt(LayoutId::kType))); 1977} 1978 1979PY_EXPORT PyObject* _PyObject_LookupSpecial(PyObject* /* f */, 1980 _Py_Identifier* /* d */) { 1981 UNIMPLEMENTED("_Py_Identifiers are not supported"); 1982} 1983 1984PY_EXPORT const char* _PyType_Name(PyTypeObject* type) { 1985 Thread* thread = Thread::current(); 1986 if (type == nullptr) { 1987 thread->raiseBadInternalCall(); 1988 return nullptr; 1989 } 1990 HandleScope scope(thread); 1991 Runtime* runtime = thread->runtime(); 1992 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyTypeObject(type))); 1993 if (!runtime->isInstanceOfType(*obj)) { 1994 thread->raiseBadInternalCall(); 1995 return nullptr; 1996 } 1997 Type type_obj(&scope, *obj); 1998 return PyUnicode_AsUTF8( 1999 ApiHandle::borrowedReference(runtime, type_obj.name())); 2000} 2001 2002PY_EXPORT PyObject* _PyType_Lookup(PyTypeObject* type, PyObject* name) { 2003 Thread* thread = Thread::current(); 2004 HandleScope scope(thread); 2005 Type type_obj( 2006 &scope, 2007 ApiHandle::asObject(ApiHandle::fromPyObject(reinterpret_cast<PyObject*>(type)))); 2008 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name))); 2009 name_obj = attributeNameNoException(thread, name_obj); 2010 if (name_obj.isErrorError()) return nullptr; 2011 Object res(&scope, typeLookupInMro(thread, *type_obj, *name_obj)); 2012 if (res.isErrorNotFound()) { 2013 return nullptr; 2014 } 2015 return ApiHandle::borrowedReference(thread->runtime(), *res); 2016} 2017 2018uword typeGetBasicSize(const Type& type) { 2019 if (typeHasSlots(type)) { 2020 return typeSlotUWordAt(type, kSlotBasicSize); 2021 } 2022 DCHECK(!type.hasNativeData(), "Types with native data should have slots"); 2023 // Return just the size needed for a pure `PyObject`/`PyObject_HEAD`. 2024 return sizeof(PyObject); 2025} 2026 2027uword typeGetFlags(const Type& type) { 2028 if (typeHasSlots(type)) { 2029 return typeSlotUWordAt(type, kSlotFlags); 2030 } 2031 uword result = Py_TPFLAGS_READY | Py_TPFLAGS_DEFAULT; 2032 Type::Flag internal_flags = type.flags(); 2033 if (internal_flags & Type::Flag::kHasCycleGC) { 2034 result |= Py_TPFLAGS_HAVE_GC; 2035 } 2036 if (internal_flags & Type::Flag::kIsAbstract) { 2037 result |= Py_TPFLAGS_IS_ABSTRACT; 2038 } 2039 if (internal_flags & Type::Flag::kIsCPythonHeaptype) { 2040 result |= Py_TPFLAGS_HEAPTYPE; 2041 } 2042 if (internal_flags & Type::Flag::kIsBasetype) { 2043 result |= Py_TPFLAGS_BASETYPE; 2044 } 2045 switch (type.builtinBase()) { 2046 case LayoutId::kInt: 2047 result |= Py_TPFLAGS_LONG_SUBCLASS; 2048 break; 2049 case LayoutId::kList: 2050 result |= Py_TPFLAGS_LIST_SUBCLASS; 2051 break; 2052 case LayoutId::kTuple: 2053 result |= Py_TPFLAGS_TUPLE_SUBCLASS; 2054 break; 2055 case LayoutId::kBytes: 2056 result |= Py_TPFLAGS_BYTES_SUBCLASS; 2057 break; 2058 case LayoutId::kStr: 2059 result |= Py_TPFLAGS_UNICODE_SUBCLASS; 2060 break; 2061 case LayoutId::kDict: 2062 result |= Py_TPFLAGS_DICT_SUBCLASS; 2063 break; 2064 // BaseException is handled separately down below 2065 case LayoutId::kType: 2066 result |= Py_TPFLAGS_TYPE_SUBCLASS; 2067 break; 2068 default: 2069 if (type.isBaseExceptionSubclass()) { 2070 result |= Py_TPFLAGS_BASE_EXC_SUBCLASS; 2071 } 2072 break; 2073 } 2074 return result; 2075} 2076 2077} // namespace py