this repo has no description
at trunk 694 lines 24 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2// object.c implementation 3 4#include "cpython-data.h" 5#include "cpython-func.h" 6 7#include "api-handle.h" 8#include "attributedict.h" 9#include "builtins-module.h" 10#include "bytes-builtins.h" 11#include "capi-typeslots.h" 12#include "capi.h" 13#include "dict-builtins.h" 14#include "extension-object.h" 15#include "frame.h" 16#include "list-builtins.h" 17#include "module-builtins.h" 18#include "object-builtins.h" 19#include "object-utils.h" 20#include "runtime.h" 21#include "str-builtins.h" 22#include "type-builtins.h" 23 24namespace py { 25 26PY_EXPORT PyTypeObject* PyBaseObject_Type_Ptr() { 27 Runtime* runtime = Thread::current()->runtime(); 28 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 29 runtime, runtime->typeAt(LayoutId::kObject))); 30} 31 32PY_EXPORT PyObject* PyEllipsis_Ptr() { 33 Runtime* runtime = Thread::current()->runtime(); 34 return ApiHandle::borrowedReference(runtime, runtime->ellipsis()); 35} 36 37PY_EXPORT PyTypeObject* PyEllipsis_Type_Ptr() { 38 Runtime* runtime = Thread::current()->runtime(); 39 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 40 runtime, runtime->typeAt(LayoutId::kEllipsis))); 41} 42 43PY_EXPORT PyTypeObject* PyEnum_Type_Ptr() { 44 Runtime* runtime = Thread::current()->runtime(); 45 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 46 runtime, runtime->typeAt(LayoutId::kEnumerate))); 47} 48 49PY_EXPORT PyObject* PyNone_Ptr() { 50 return ApiHandle::handleFromImmediate(NoneType::object()); 51} 52 53PY_EXPORT PyObject* PyNotImplemented_Ptr() { 54 return ApiHandle::handleFromImmediate(NotImplementedType::object()); 55} 56 57PY_EXPORT void _Py_Dealloc(PyObject* pyobj) { 58 Thread* thread = Thread::current(); 59 Runtime* runtime = thread->runtime(); 60 HandleScope scope(thread); 61 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 62 if (!runtime->isInstanceOfNativeProxy(*obj)) return; 63 Type obj_type(&scope, runtime->typeOf(*obj)); 64 // Do nothing for builtin types since we have our own GC to deallocate objects 65 if (typeHasSlots(obj_type)) { 66 destructor dealloc = 67 reinterpret_cast<destructor>(typeSlotAt(obj_type, Py_tp_dealloc)); 68 (dealloc)(pyobj); 69 } 70} 71 72PY_EXPORT void _Py_NewReference(PyObject*) { 73 UNIMPLEMENTED("_Py_NewReference"); 74} 75 76PY_EXPORT void Py_INCREF_Func(PyObject* obj) { 77 ApiHandle* handle = ApiHandle::fromPyObject(obj); 78 ApiHandle::incref(handle); 79} 80 81PY_EXPORT Py_ssize_t Py_REFCNT_Func(PyObject* obj) { 82 ApiHandle* handle = ApiHandle::fromPyObject(obj); 83 return ApiHandle::refcnt(handle); 84} 85 86PY_EXPORT void Py_SET_REFCNT_Func(PyObject* obj, Py_ssize_t refcnt) { 87 ApiHandle* handle = ApiHandle::fromPyObject(obj); 88 ApiHandle::setRefcnt(handle, refcnt); 89} 90 91PY_EXPORT void Py_DECREF_Func(PyObject* obj) { 92 ApiHandle* handle = ApiHandle::fromPyObject(obj); 93 if (ApiHandle::isImmediate(handle)) return; 94 ApiHandle::decrefNoImmediate(handle); 95 DCHECK(ApiHandle::refcnt(handle) > 0 || 96 !Thread::current()->runtime()->isInstanceOfNativeProxy( 97 ApiHandle::asObjectNoImmediate(ApiHandle::fromPyObject(obj))), 98 "native proxies should not reach refcount 0 without GC"); 99} 100 101PY_EXPORT Py_ssize_t* Py_SIZE_Func(PyVarObject* obj) { 102 // Cannot call this on builtin types like `int`. 103 DCHECK(Thread::current()->runtime()->isInstanceOfNativeProxy( 104 ApiHandle::asObject(ApiHandle::fromPyObject(reinterpret_cast<PyObject*>(obj))) 105), 106 "must only be called on extension object"); 107 return &(obj->ob_size); 108} 109 110PY_EXPORT int PyCallable_Check(PyObject* obj) { 111 if (obj == nullptr) return 0; 112 Thread* thread = Thread::current(); 113 HandleScope scope(thread); 114 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 115 return thread->runtime()->isCallable(thread, object); 116} 117 118PY_EXPORT PyObject* PyObject_ASCII(PyObject* pyobj) { 119 Thread* thread = Thread::current(); 120 Runtime* runtime = thread->runtime(); 121 if (pyobj == nullptr) { 122 return ApiHandle::newReference(runtime, SmallStr::fromCStr("<NULL>")); 123 } 124 HandleScope scope(thread); 125 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 126 Object result(&scope, thread->invokeFunction1(ID(builtins), ID(ascii), obj)); 127 if (result.isError()) { 128 return nullptr; 129 } 130 return ApiHandle::newReference(runtime, *result); 131} 132 133PY_EXPORT PyObject* PyObject_Bytes(PyObject* pyobj) { 134 Thread* thread = Thread::current(); 135 HandleScope scope(thread); 136 Runtime* runtime = thread->runtime(); 137 if (pyobj == nullptr) { 138 static const byte value[] = "<NULL>"; 139 return ApiHandle::newReference(runtime, SmallBytes::fromBytes(value)); 140 } 141 142 ApiHandle* handle = ApiHandle::fromPyObject(pyobj); 143 Object obj(&scope, ApiHandle::asObject(handle)); 144 if (obj.isBytes()) { 145 ApiHandle::incref(handle); 146 return pyobj; 147 } 148 149 Object result(&scope, thread->invokeMethod1(obj, ID(__bytes__))); 150 if (result.isError()) { 151 if (result.isErrorException()) return nullptr; 152 // Attribute lookup failed 153 result = thread->invokeFunction1(ID(builtins), ID(_bytes_new), obj); 154 if (result.isErrorException()) return nullptr; 155 DCHECK(!result.isError(), "Couldn't call builtins._bytes_new"); 156 } else if (!runtime->isInstanceOfBytes(*result)) { 157 thread->raiseWithFmt(LayoutId::kTypeError, 158 "__bytes__ returned non-bytes (type %T)", &result); 159 return nullptr; 160 } 161 return ApiHandle::newReference(runtime, *result); 162} 163 164PY_EXPORT void PyObject_CallFinalizer(PyObject* self) { 165 PyTypeObject* type = Py_TYPE(self); 166 auto finalizer = 167 reinterpret_cast<destructor>(PyType_GetSlot(type, Py_tp_finalize)); 168 if (finalizer == nullptr) { 169 // Nothing to finalize. 170 return; 171 } 172 bool is_gc = (PyType_GetFlags(type) & Py_TPFLAGS_HAVE_GC) != 0; 173 if (is_gc) { 174 // TODO(T55208267): Support GC types 175 UNIMPLEMENTED( 176 "PyObject_CallFinalizer with finalizer and gc type is not " 177 "yet supported"); 178 } 179 // TODO(T55208267): Check if the type has GC flags and the object is already 180 // finalized and return early. tp_finalize should only be called once. 181 (*finalizer)(self); 182 // TODO(T55208267): Check if the type has GC flags set a bit on the object to 183 // indicate that it has been finalized already. 184} 185 186PY_EXPORT int PyObject_CallFinalizerFromDealloc(PyObject* self) { 187 DCHECK(self != nullptr, "self cannot be null"); 188 if (Py_REFCNT(self) != 0) { 189 Py_FatalError( 190 "PyObject_CallFinalizerFromDealloc called on " 191 "object with a non-zero refcount"); 192 } 193 // Temporarily resurrect the object. 194 self->ob_refcnt = 1; 195 // Finalize the object. 196 PyObject_CallFinalizer(self); 197 if (self->ob_refcnt == 1) { 198 // tp_finalize did not resurrect the object, so undo the temporary 199 // resurrection and put it to rest. 200 self->ob_refcnt--; 201 return 0; 202 } 203 DCHECK(Py_REFCNT(self) > 0, "refcnt must be positive"); 204 // If we get here, tp_finalize resurrected the object. 205 return -1; 206} 207 208PY_EXPORT int PyObject_DelAttr(PyObject* obj, PyObject* attr_name) { 209 Thread* thread = Thread::current(); 210 HandleScope scope(thread); 211 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 212 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(attr_name))); 213 Object result(&scope, delAttribute(thread, object, name_obj)); 214 return result.isErrorException() ? -1 : 0; 215} 216 217PY_EXPORT int PyObject_DelAttrString(PyObject* obj, const char* attr_name) { 218 PyObject* str = PyUnicode_FromString(attr_name); 219 if (str == nullptr) return -1; 220 int result = PyObject_DelAttr(obj, str); 221 Py_DECREF(str); 222 return result; 223} 224 225PY_EXPORT PyObject* PyObject_Dir(PyObject* obj) { 226 Thread* thread = Thread::current(); 227 Frame* frame = thread->currentFrame(); 228 if (obj == nullptr && frame->isSentinel()) { 229 return nullptr; 230 } 231 HandleScope scope(thread); 232 Runtime* runtime = thread->runtime(); 233 if (obj == nullptr) { 234 Object locals(&scope, frameLocals(thread, frame)); 235 Object list_obj(&scope, NoneType::object()); 236 if (locals.isDict()) { 237 Dict locals_dict(&scope, *locals); 238 list_obj = dictKeys(thread, locals_dict); 239 } else if (locals.isModuleProxy()) { 240 ModuleProxy module_proxy(&scope, *locals); 241 Module module(&scope, module_proxy.module()); 242 list_obj = moduleKeys(thread, module); 243 } else { 244 return nullptr; 245 } 246 List list(&scope, *list_obj); 247 listSort(thread, list); 248 return ApiHandle::newReference(runtime, *list); 249 } 250 251 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 252 Type type(&scope, runtime->typeOf(*object)); 253 Object func(&scope, typeLookupInMroById(thread, *type, ID(__dir__))); 254 if (func.isError() || !func.isFunction()) { 255 return nullptr; 256 } 257 Object sequence(&scope, Interpreter::call1(thread, func, object)); 258 if (sequence.isError()) { 259 return nullptr; 260 } 261 if (sequence.isList()) { 262 List list(&scope, *sequence); 263 listSort(thread, list); 264 return ApiHandle::newReference(runtime, *list); 265 } 266 List list(&scope, runtime->newList()); 267 Object result(&scope, thread->invokeMethodStatic2(LayoutId::kList, ID(extend), 268 list, sequence)); 269 if (result.isError()) { 270 return nullptr; 271 } 272 listSort(thread, list); 273 return ApiHandle::newReference(runtime, *list); 274} 275 276PY_EXPORT PyObject* PyObject_GenericGetAttr(PyObject* obj, PyObject* name) { 277 Thread* thread = Thread::current(); 278 HandleScope scope(thread); 279 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 280 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name))); 281 name_obj = attributeName(thread, name_obj); 282 if (name_obj.isErrorException()) return nullptr; 283 Object result(&scope, objectGetAttribute(thread, object, name_obj)); 284 if (result.isError()) { 285 if (result.isErrorNotFound()) { 286 objectRaiseAttributeError(thread, object, name_obj); 287 } 288 return nullptr; 289 } 290 return ApiHandle::newReference(thread->runtime(), *result); 291} 292 293PY_EXPORT int _PyObject_LookupAttr(PyObject* obj, PyObject* name, 294 PyObject** result) { 295 // Replacements of PyObject_GetAttr() and _PyObject_GetAttrId() which don't 296 // raise AttributeError. 297 // Return 1 and set *result != NULL if an attribute is found. 298 // Return 0 and set *result == NULL if an attribute is not found; an 299 // AttributeError is silenced. 300 // Return -1 and set *result == NULL if an error other than AttributeError is 301 // raised. 302 Thread* thread = Thread::current(); 303 HandleScope scope(thread); 304 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 305 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name))); 306 Object name_str(&scope, attributeName(thread, name_obj)); 307 if (name_str.isErrorException()) { 308 // name was not a str instance 309 *result = nullptr; 310 return -1; 311 } 312 Runtime* runtime = thread->runtime(); 313 Object result_obj(&scope, runtime->attributeAt(thread, object, name_obj)); 314 if (!result_obj.isError()) { 315 *result = ApiHandle::newReference(runtime, *result_obj); 316 return 1; 317 } 318 DCHECK(result_obj.isErrorException(), "result should only be an exception"); 319 if (thread->pendingExceptionMatches(LayoutId::kAttributeError)) { 320 *result = nullptr; 321 thread->clearPendingException(); 322 return 0; 323 } 324 *result = nullptr; 325 return -1; 326} 327 328PY_EXPORT int PyObject_GenericSetAttr(PyObject* obj, PyObject* name, 329 PyObject* value) { 330 Thread* thread = Thread::current(); 331 HandleScope scope(thread); 332 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 333 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name))); 334 name_obj = attributeName(thread, name_obj); 335 if (name_obj.isErrorException()) return -1; 336 Object value_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(value))); 337 Object result(&scope, objectSetAttr(thread, object, name_obj, value_obj)); 338 if (result.isErrorException()) { 339 return -1; 340 } 341 return 0; 342} 343 344PY_EXPORT int PyObject_GenericSetDict(PyObject* /* j */, PyObject* /* e */, 345 void* /* t */) { 346 UNIMPLEMENTED("PyObject_GenericSetDict"); 347} 348 349PY_EXPORT PyObject* PyObject_GetAttr(PyObject* obj, PyObject* name) { 350 Thread* thread = Thread::current(); 351 HandleScope scope(thread); 352 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 353 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name))); 354 Object result(&scope, getAttribute(thread, object, name_obj)); 355 return result.isError() ? nullptr 356 : ApiHandle::newReference(thread->runtime(), *result); 357} 358 359PY_EXPORT PyObject* PyObject_GetAttrString(PyObject* pyobj, const char* name) { 360 DCHECK(pyobj != nullptr, "pyobj must not be nullptr"); 361 DCHECK(name != nullptr, "name must not be nullptr"); 362 Thread* thread = Thread::current(); 363 HandleScope scope(thread); 364 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 365 Runtime* runtime = thread->runtime(); 366 Object result(&scope, runtime->attributeAtByCStr(thread, object, name)); 367 if (result.isError()) return nullptr; 368 return ApiHandle::newReference(runtime, *result); 369} 370 371PY_EXPORT int PyObject_HasAttr(PyObject* pyobj, PyObject* pyname) { 372 Thread* thread = Thread::current(); 373 HandleScope scope(thread); 374 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 375 Object name(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyname))); 376 Object result(&scope, hasAttribute(thread, obj, name)); 377 if (result.isBool()) return Bool::cast(*result).value(); 378 thread->clearPendingException(); 379 return false; 380} 381 382PY_EXPORT int PyObject_HasAttrString(PyObject* pyobj, const char* name) { 383 Thread* thread = Thread::current(); 384 HandleScope scope(thread); 385 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))); 386 Object name_str(&scope, Runtime::internStrFromCStr(thread, name)); 387 Object result(&scope, thread->runtime()->attributeAt(thread, obj, name_str)); 388 if (!result.isErrorException()) return true; 389 thread->clearPendingException(); 390 return false; 391} 392 393PY_EXPORT Py_hash_t PyObject_Hash(PyObject* obj) { 394 DCHECK(obj != nullptr, "obj should not be nullptr"); 395 Thread* thread = Thread::current(); 396 HandleScope scope(thread); 397 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 398 Object result(&scope, Interpreter::hash(thread, object)); 399 if (result.isErrorException()) return -1; 400 return SmallInt::cast(*result).value(); 401} 402 403PY_EXPORT Py_hash_t PyObject_HashNotImplemented(PyObject* /* v */) { 404 Thread* thread = Thread::current(); 405 thread->raiseWithFmt(LayoutId::kTypeError, "unhashable type"); 406 return -1; 407} 408 409PY_EXPORT PyObject* PyObject_Init(PyObject* obj, PyTypeObject* typeobj) { 410 if (obj == nullptr) return PyErr_NoMemory(); 411 412 // Create a managed proxy for the native instance 413 Thread* thread = Thread::current(); 414 Runtime* runtime = thread->runtime(); 415 HandleScope scope(thread); 416 Type type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyTypeObject(typeobj))); 417 Layout layout(&scope, type_obj.instanceLayout()); 418 Object instance(&scope, runtime->newInstance(layout)); 419 return initializeExtensionObject(thread, obj, typeobj, instance); 420} 421 422PY_EXPORT PyVarObject* PyObject_InitVar(PyVarObject* obj, PyTypeObject* type, 423 Py_ssize_t size) { 424 if (obj == nullptr) return reinterpret_cast<PyVarObject*>(PyErr_NoMemory()); 425 obj->ob_size = size; 426 PyObject_Init(reinterpret_cast<PyObject*>(obj), type); 427 return obj; 428} 429 430PY_EXPORT int PyObject_IsTrue(PyObject* obj) { 431 DCHECK(obj != nullptr, "nullptr passed into PyObject_IsTrue"); 432 Thread* thread = Thread::current(); 433 HandleScope scope(thread); 434 Object obj_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 435 Object result(&scope, Interpreter::isTrue(thread, *obj_obj)); 436 if (result.isError()) { 437 return -1; 438 } 439 return Bool::cast(*result).value(); 440} 441 442PY_EXPORT int PyObject_Not(PyObject* obj) { 443 int res = PyObject_IsTrue(obj); 444 if (res < 0) { 445 return res; 446 } 447 return res == 0; 448} 449 450PY_EXPORT int PyObject_Print(PyObject* obj, FILE* fp, int flags) { 451 if (PyErr_CheckSignals()) return -1; 452 std::clearerr(fp); // Clear any previous error condition 453 if (obj == nullptr) { 454 std::fprintf(fp, "<nil>"); 455 } else { 456 PyObject* str = 457 flags & Py_PRINT_RAW ? PyObject_Str(obj) : PyObject_Repr(obj); 458 if (str == nullptr) return -1; 459 if (!PyUnicode_Check(str)) { 460 Thread::current()->raiseWithFmt(LayoutId::kTypeError, 461 "str() or repr() returned '%s'", 462 _PyType_Name(Py_TYPE(str))); 463 Py_DECREF(str); 464 return -1; 465 } 466 PyObject* bytes = 467 PyUnicode_AsEncodedString(str, "utf-8", "backslashreplace"); 468 Py_DECREF(str); 469 if (bytes == nullptr) { 470 return -1; 471 } 472 char* c_str = PyBytes_AsString(bytes); 473 std::fputs(c_str, fp); 474 Py_DECREF(bytes); 475 } 476 if (std::ferror(fp)) { 477 PyErr_SetFromErrno(PyExc_IOError); 478 std::clearerr(fp); 479 return -1; 480 } 481 return 0; 482} 483 484// TODO(T38571506): Handle recursive objects safely. 485PY_EXPORT PyObject* PyObject_Repr(PyObject* obj) { 486 Thread* thread = Thread::current(); 487 Runtime* runtime = thread->runtime(); 488 if (obj == nullptr) { 489 return ApiHandle::newReference(runtime, SmallStr::fromCStr("<NULL>")); 490 } 491 HandleScope scope(thread); 492 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 493 Object result(&scope, thread->invokeMethod1(object, ID(__repr__))); 494 if (result.isError()) { 495 return nullptr; 496 } 497 if (!runtime->isInstanceOfStr(*result)) { 498 thread->raiseWithFmt(LayoutId::kTypeError, 499 "__repr__ returned non-str instance"); 500 return nullptr; 501 } 502 return ApiHandle::newReference(runtime, *result); 503} 504 505PY_EXPORT PyObject* PyObject_RichCompare(PyObject* v, PyObject* w, int op) { 506 DCHECK(CompareOp::LT <= op && op <= CompareOp::GE, "Bad op"); 507 Thread* thread = Thread::current(); 508 if (v == nullptr || w == nullptr) { 509 if (!thread->hasPendingException()) { 510 thread->raiseBadInternalCall(); 511 } 512 return nullptr; 513 } 514 // TODO(emacs): Recursive call check 515 HandleScope scope(thread); 516 Object left(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(v))); 517 Object right(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(w))); 518 Object result(&scope, Interpreter::compareOperation( 519 thread, static_cast<CompareOp>(op), left, right)); 520 if (result.isError()) { 521 return nullptr; 522 } 523 return ApiHandle::newReference(thread->runtime(), *result); 524} 525 526PY_EXPORT int PyObject_RichCompareBool(PyObject* left, PyObject* right, 527 int op) { 528 // Quick result when objects are the same. Guarantees that identity implies 529 // equality. 530 if (left == right) { 531 if (op == Py_EQ) { 532 return 1; 533 } 534 if (op == Py_NE) { 535 return 0; 536 } 537 } 538 PyObject* res = PyObject_RichCompare(left, right, op); 539 if (res == nullptr) { 540 return -1; 541 } 542 int ok; 543 if (PyBool_Check(res)) { 544 ok = (res == Py_True); 545 } else { 546 ok = PyObject_IsTrue(res); 547 } 548 Py_DECREF(res); 549 return ok; 550} 551 552PY_EXPORT PyObject* PyObject_SelfIter(PyObject* obj) { 553 Py_INCREF(obj); 554 return obj; 555} 556 557PY_EXPORT int PyObject_SetAttr(PyObject* obj, PyObject* name, PyObject* value) { 558 if (value == nullptr) { 559 return PyObject_DelAttr(obj, name); 560 } 561 Thread* thread = Thread::current(); 562 HandleScope scope(thread); 563 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 564 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name))); 565 Object value_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(value))); 566 Object result(&scope, setAttribute(thread, object, name_obj, value_obj)); 567 return result.isErrorException() ? -1 : 0; 568} 569 570PY_EXPORT int PyObject_SetAttrString(PyObject* v, const char* name, 571 PyObject* w) { 572 PyObject* str = PyUnicode_FromString(name); 573 if (str == nullptr) return -1; 574 int result = PyObject_SetAttr(v, str, w); 575 Py_DECREF(str); 576 return result; 577} 578 579// TODO(T38571506): Handle recursive objects safely. 580PY_EXPORT PyObject* PyObject_Str(PyObject* obj) { 581 Thread* thread = Thread::current(); 582 Runtime* runtime = thread->runtime(); 583 if (obj == nullptr) { 584 return ApiHandle::newReference(runtime, SmallStr::fromCStr("<NULL>")); 585 } 586 HandleScope scope(thread); 587 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 588 Object result(&scope, thread->invokeMethod1(object, ID(__str__))); 589 if (result.isError()) { 590 return nullptr; 591 } 592 if (!runtime->isInstanceOfStr(*result)) { 593 thread->raiseWithFmt(LayoutId::kTypeError, 594 "__str__ returned non-str instance"); 595 return nullptr; 596 } 597 return ApiHandle::newReference(runtime, *result); 598} 599 600PY_EXPORT void Py_DecRef(PyObject* obj) { 601 if (obj == nullptr) return; 602 Py_DECREF_Func(obj); 603} 604 605PY_EXPORT void Py_IncRef(PyObject* obj) { 606 if (obj == nullptr) return; 607 Py_INCREF_Func(obj); 608} 609 610PY_EXPORT int Py_ReprEnter(PyObject* obj) { 611 Thread* thread = Thread::current(); 612 HandleScope scope(thread); 613 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 614 Object result(&scope, thread->reprEnter(object)); 615 if (result.isError()) { 616 return -1; 617 } 618 return Bool::cast(*result).value(); 619} 620 621PY_EXPORT void Py_ReprLeave(PyObject* obj) { 622 Thread* thread = Thread::current(); 623 HandleScope scope(thread); 624 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 625 thread->reprLeave(object); 626} 627 628PY_EXPORT PyObject* _PyObject_GetAttrId(PyObject* /* v */, 629 _Py_Identifier* /* e */) { 630 UNIMPLEMENTED("_PyObject_GetAttrId"); 631} 632 633PY_EXPORT int _PyObject_HasAttrId(PyObject* /* v */, _Py_Identifier* /* e */) { 634 UNIMPLEMENTED("_PyObject_HasAttrId"); 635} 636 637PY_EXPORT PyObject* _PyObject_New(PyTypeObject* type) { 638 Thread* thread = Thread::current(); 639 HandleScope scope(thread); 640 Type type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyTypeObject(type))); 641 if (!type_obj.hasNativeData()) { 642 // Since the type will be pointed to by the layout as long as there are any 643 // objects of its type, we don't need to INCREF the type object if it 644 // doesn't have NativeData. 645 Layout layout(&scope, type_obj.instanceLayout()); 646 Runtime* runtime = thread->runtime(); 647 return ApiHandle::newReference(runtime, runtime->newInstance(layout)); 648 } 649 PyObject* obj = static_cast<PyObject*>(PyObject_MALLOC(_PyObject_SIZE(type))); 650 if (obj == nullptr) return PyErr_NoMemory(); 651 return PyObject_INIT(obj, type); 652} 653 654PY_EXPORT PyVarObject* _PyObject_NewVar(PyTypeObject* type, Py_ssize_t nitems) { 655 PyObject* obj = 656 static_cast<PyObject*>(PyObject_MALLOC(_PyObject_VAR_SIZE(type, nitems))); 657 if (obj == nullptr) return reinterpret_cast<PyVarObject*>(PyErr_NoMemory()); 658 return PyObject_INIT_VAR(obj, type, nitems); 659} 660 661PY_EXPORT PyTypeObject* _PyNone_Type_Ptr() { 662 Runtime* runtime = Thread::current()->runtime(); 663 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 664 runtime, runtime->typeAt(LayoutId::kNoneType))); 665} 666 667PY_EXPORT PyTypeObject* _PyNotImplemented_Type_Ptr() { 668 Runtime* runtime = Thread::current()->runtime(); 669 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 670 runtime, runtime->typeAt(LayoutId::kNotImplementedType))); 671} 672 673PY_EXPORT int _PyObject_SetAttrId(PyObject* /* v */, _Py_Identifier* /* e */, 674 PyObject* /* w */) { 675 UNIMPLEMENTED("_PyObject_SetAttrId"); 676} 677 678PY_EXPORT void _PyTrash_deposit_object(PyObject* /* p */) { 679 UNIMPLEMENTED("_PyTrash_deposit_object"); 680} 681 682PY_EXPORT void _PyTrash_destroy_chain() { 683 UNIMPLEMENTED("_PyTrash_destroy_chain"); 684} 685 686PY_EXPORT void _PyTrash_thread_deposit_object(PyObject* /* p */) { 687 UNIMPLEMENTED("_PyTrash_thread_deposit_object"); 688} 689 690PY_EXPORT void _PyTrash_thread_destroy_chain() { 691 UNIMPLEMENTED("_PyTrash_thread_destroy_chain"); 692} 693 694} // namespace py