this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <cstdarg>
3
4#include "../Python/modsupport-internal.h"
5#include "cpython-data.h"
6#include "cpython-func.h"
7
8#include "api-handle.h"
9#include "array-module.h"
10#include "attributedict.h"
11#include "bytearrayobject-utils.h"
12#include "bytesobject-utils.h"
13#include "capi-typeslots.h"
14#include "capi.h"
15#include "exception-builtins.h"
16#include "formatter.h"
17#include "frame.h"
18#include "int-builtins.h"
19#include "list-builtins.h"
20#include "object-builtins.h"
21#include "runtime.h"
22#include "type-builtins.h"
23
24namespace py {
25
26static PyObject* nullError(Thread* thread) {
27 if (!thread->hasPendingException()) {
28 thread->raiseWithFmt(LayoutId::kSystemError,
29 "null argument to internal routine");
30 }
31 return nullptr;
32}
33
34static PyObject* doUnaryOp(SymbolId op, PyObject* obj) {
35 Thread* thread = Thread::current();
36 if (obj == nullptr) {
37 return nullError(thread);
38 }
39
40 HandleScope scope(thread);
41 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
42 Object result(&scope, thread->invokeFunction1(ID(operator), op, object));
43 return result.isError() ? nullptr
44 : ApiHandle::newReference(thread->runtime(), *result);
45}
46
47static PyObject* doBinaryOp(SymbolId op, PyObject* left, PyObject* right) {
48 Thread* thread = Thread::current();
49 DCHECK(left != nullptr && right != nullptr, "null argument to binary op %s",
50 Symbols::predefinedSymbolAt(op));
51 HandleScope scope(thread);
52 Object left_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(left)));
53 Object right_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(right)));
54 Object result(&scope,
55 thread->invokeFunction2(ID(operator), op, left_obj, right_obj));
56 return result.isError() ? nullptr
57 : ApiHandle::newReference(thread->runtime(), *result);
58}
59
60static Py_ssize_t objectLength(PyObject* pyobj) {
61 Thread* thread = Thread::current();
62 if (pyobj == nullptr) {
63 nullError(thread);
64 return -1;
65 }
66
67 HandleScope scope(thread);
68 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
69 Object len_index(&scope, thread->invokeMethod1(obj, ID(__len__)));
70 if (len_index.isError()) {
71 if (len_index.isErrorNotFound()) {
72 thread->raiseWithFmt(LayoutId::kTypeError, "object has no len()");
73 }
74 return -1;
75 }
76 Object len(&scope, intFromIndex(thread, len_index));
77 if (len.isError()) {
78 return -1;
79 }
80 Int index(&scope, intUnderlying(*len));
81 if (index.isNegative()) {
82 thread->raiseWithFmt(LayoutId::kValueError, "__len__() should return >= 0");
83 return -1;
84 }
85 if (index.numDigits() > 1) {
86 thread->raiseWithFmt(LayoutId::kOverflowError,
87 "cannot fit '%T' into an index-sized integer",
88 &len_index);
89 return -1;
90 }
91 return index.asWord();
92}
93
94// Buffer Protocol
95
96static RawObject raiseBufferError(Thread* thread, const Object& obj) {
97 return thread->raiseWithFmt(
98 LayoutId::kTypeError, "a bytes-like object is required, not '%T'", &obj);
99}
100
101RawObject newBytesFromBuffer(Thread* thread, const Object& obj) {
102 HandleScope scope(thread);
103 Runtime* runtime = thread->runtime();
104 Type type(&scope, runtime->typeOf(*obj));
105 if (!typeHasSlots(type)) {
106 return raiseBufferError(thread, obj);
107 }
108 void* get_slot = typeSlotAt(type, Py_bf_getbuffer);
109 if (get_slot == nullptr) {
110 return raiseBufferError(thread, obj);
111 }
112 Py_buffer view;
113 int flags = PyBUF_SIMPLE;
114 ApiHandle* handle = ApiHandle::borrowedReference(runtime, *obj);
115 int get_result =
116 reinterpret_cast<getbufferproc>(get_slot)(handle, &view, flags);
117 if (get_result != 0) {
118 return Error::exception();
119 }
120 DCHECK(view.readonly, "writable buffers not supported");
121 DCHECK(view.ndim == 1, "multi-dimensional buffers not supported");
122 Bytes result(&scope, runtime->newBytesWithAll(
123 {reinterpret_cast<byte*>(view.buf), view.len}));
124 void* release_slot = typeSlotAt(type, Py_bf_releasebuffer);
125 // The release slot may not be defined. That's allowed.
126 if (release_slot != nullptr) {
127 reinterpret_cast<releasebufferproc>(release_slot)(handle, &view);
128 }
129 return *result;
130}
131
132PY_EXPORT int PyBuffer_FillInfo(Py_buffer* view, PyObject* exporter, void* buf,
133 Py_ssize_t len, int readonly, int flags) {
134 if (view == nullptr) {
135 Thread::current()->raiseWithFmt(
136 LayoutId::kBufferError,
137 "PyBuffer_FillInfo: view==NULL argument is obsolete");
138 return -1;
139 }
140 if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && readonly == 1) {
141 Thread::current()->raiseWithFmt(LayoutId::kBufferError,
142 "Object is not writable.");
143 return -1;
144 }
145
146 if (exporter != nullptr) {
147 Py_INCREF(exporter);
148 }
149 view->obj = exporter;
150 view->buf = buf;
151 view->len = len;
152 view->readonly = readonly;
153 view->itemsize = 1;
154 view->format = nullptr;
155 if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
156 view->format = const_cast<char*>("B");
157 }
158 view->ndim = 1;
159 view->shape = nullptr;
160 if ((flags & PyBUF_ND) == PyBUF_ND) {
161 view->shape = &(view->len);
162 }
163 view->strides = nullptr;
164 if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
165 view->strides = &(view->itemsize);
166 }
167 view->suboffsets = nullptr;
168 view->internal = nullptr;
169 return 0;
170}
171
172static bool isContiguousWithRowMajorOrder(const Py_buffer* view) {
173 if (view->suboffsets != nullptr) return false;
174 if (view->strides == nullptr) return true;
175 if (view->len == 0) return true;
176
177 Py_ssize_t dim_stride = view->itemsize;
178 for (int d = view->ndim - 1; d >= 0; d--) {
179 Py_ssize_t dim_size = view->shape[d];
180 if (dim_size > 1 && view->strides[d] != dim_stride) {
181 return false;
182 }
183 dim_stride *= dim_size;
184 }
185 return true;
186}
187
188static bool isContiguousWithColumnMajorOrder(const Py_buffer* view) {
189 if (view->suboffsets != nullptr) return false;
190 if (view->len == 0) return true;
191 if (view->strides == nullptr) {
192 if (view->ndim <= 1) return true;
193 // Non-contiguous if there is more than 1 dimension with size > 0.
194 bool had_nonempty_dim = false;
195 for (int d = 0; d < view->ndim; d++) {
196 if (view->shape[d] > 1) {
197 if (had_nonempty_dim) return false;
198 had_nonempty_dim = true;
199 }
200 }
201 return true;
202 }
203
204 Py_ssize_t dim_stride = view->itemsize;
205 for (int d = 0; d < view->ndim; d++) {
206 Py_ssize_t dim_size = view->shape[d];
207 if (dim_size > 1 && view->strides[d] != dim_stride) {
208 return false;
209 }
210 dim_stride *= dim_size;
211 }
212 return true;
213}
214
215PY_EXPORT int PyBuffer_IsContiguous(const Py_buffer* view, char order) {
216 if (order == 'C') {
217 return isContiguousWithRowMajorOrder(view);
218 }
219 if (order == 'F') {
220 return isContiguousWithColumnMajorOrder(view);
221 }
222 if (order == 'A') {
223 return isContiguousWithRowMajorOrder(view) ||
224 isContiguousWithColumnMajorOrder(view);
225 }
226 return false;
227}
228
229PY_EXPORT void PyBuffer_Release(Py_buffer* view) {
230 DCHECK(view != nullptr, "view must not be nullptr");
231 PyObject* pyobj = view->obj;
232 if (pyobj == nullptr) return;
233
234 Thread* thread = Thread::current();
235 HandleScope scope(thread);
236 Runtime* runtime = thread->runtime();
237 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
238 Type type(&scope, runtime->typeOf(*object));
239 if (typeHasSlots(type)) {
240 // Call Py_bf_releasebuffer slot if defined
241 void* releasebuffer_fn =
242 PyType_GetSlot(Py_TYPE(pyobj), Py_bf_releasebuffer);
243 if (releasebuffer_fn != nullptr) {
244 reinterpret_cast<releasebufferproc>(releasebuffer_fn)(pyobj, view);
245 }
246 }
247 view->obj = nullptr;
248 Py_DECREF(pyobj);
249}
250
251// PyIndex_Check
252
253PY_EXPORT int PyIndex_Check_Func(PyObject* obj) {
254 DCHECK(obj != nullptr, "Got null argument");
255 Thread* thread = Thread::current();
256 HandleScope scope(thread);
257 Object num(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
258 Type type(&scope, thread->runtime()->typeOf(*num));
259 return !typeLookupInMroById(thread, *type, ID(__index__)).isErrorNotFound();
260}
261
262// PyIter_Next
263
264PY_EXPORT PyObject* PyIter_Next(PyObject* iter) {
265 Thread* thread = Thread::current();
266 HandleScope scope(thread);
267 Object iter_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(iter)));
268 Object next(&scope, thread->invokeMethod1(iter_obj, ID(__next__)));
269 if (thread->clearPendingStopIteration()) {
270 // End of iterable
271 return nullptr;
272 }
273 if (next.isError()) {
274 // Method lookup or call failed
275 if (next.isErrorNotFound()) {
276 thread->raiseWithFmt(LayoutId::kTypeError,
277 "failed to call __next__ on iterable");
278 }
279 return nullptr;
280 }
281 return ApiHandle::newReference(thread->runtime(), *next);
282}
283
284// Mapping Protocol
285
286PY_EXPORT int PyMapping_Check(PyObject* py_obj) {
287 Thread* thread = Thread::current();
288 HandleScope scope(thread);
289 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(py_obj)));
290 return thread->runtime()->isMapping(thread, obj);
291}
292
293PY_EXPORT int PyMapping_DelItemString(PyObject* obj, const char* attr_name) {
294 return PyObject_DelItemString(obj, attr_name);
295}
296
297PY_EXPORT int PyMapping_DelItem(PyObject* obj, PyObject* attr_name) {
298 return PyObject_DelItem(obj, attr_name);
299}
300
301PY_EXPORT PyObject* PyMapping_GetItemString(PyObject* obj, const char* key) {
302 Thread* thread = Thread::current();
303 if (obj == nullptr || key == nullptr) {
304 return nullError(thread);
305 }
306 HandleScope scope(thread);
307 Runtime* runtime = thread->runtime();
308 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
309 Object key_obj(&scope, runtime->newStrFromCStr(key));
310 Object result(&scope, objectGetItem(thread, object, key_obj));
311 if (result.isErrorException()) return nullptr;
312 return ApiHandle::newReference(runtime, *result);
313}
314
315PY_EXPORT int PyMapping_HasKey(PyObject* obj, PyObject* key) {
316 PyObject* v = PyObject_GetItem(obj, key);
317 if (v != nullptr) {
318 Py_DECREF(v);
319 return 1;
320 }
321 PyErr_Clear();
322 return 0;
323}
324
325PY_EXPORT int PyMapping_HasKeyString(PyObject* obj, const char* key) {
326 PyObject* v = PyMapping_GetItemString(obj, key);
327 if (v != nullptr) {
328 Py_DECREF(v);
329 return 1;
330 }
331 PyErr_Clear();
332 return 0;
333}
334
335PY_EXPORT PyObject* PyMapping_Items(PyObject* mapping) {
336 if (PyDict_CheckExact(mapping)) {
337 return PyDict_Items(mapping);
338 }
339 PyObject* items = PyObject_CallMethod(mapping, "items", nullptr);
340 if (items == nullptr) {
341 return nullptr;
342 }
343 PyObject* fast = PySequence_Fast(items, "mapping.items() are not iterable");
344 Py_DECREF(items);
345 return fast;
346}
347
348PY_EXPORT PyObject* PyMapping_Keys(PyObject* mapping) {
349 DCHECK(mapping != nullptr, "mapping was null");
350 if (PyDict_CheckExact(mapping)) {
351 return PyDict_Keys(mapping);
352 }
353 PyObject* keys = PyObject_CallMethod(mapping, "keys", nullptr);
354 if (keys == nullptr) {
355 return nullptr;
356 }
357 PyObject* fast = PySequence_Fast(keys, "mapping.keys() are not iterable");
358 Py_DECREF(keys);
359 return fast;
360}
361
362PY_EXPORT Py_ssize_t PyMapping_Length(PyObject* pyobj) {
363 return objectLength(pyobj);
364}
365
366PY_EXPORT int PyMapping_SetItemString(PyObject* obj, const char* key,
367 PyObject* value) {
368 if (key == nullptr) {
369 nullError(Thread::current());
370 return -1;
371 }
372 PyObject* key_obj = PyUnicode_FromString(key);
373 if (key_obj == nullptr) {
374 return -1;
375 }
376 int r = PyObject_SetItem(obj, key_obj, value);
377 Py_DECREF(key_obj);
378 return r;
379}
380
381PY_EXPORT Py_ssize_t PyMapping_Size(PyObject* pyobj) {
382 return objectLength(pyobj);
383}
384
385PY_EXPORT PyObject* PyMapping_Values(PyObject* mapping) {
386 if (PyDict_CheckExact(mapping)) {
387 return PyDict_Values(mapping);
388 }
389 PyObject* values = PyObject_CallMethod(mapping, "values", nullptr);
390 if (values == nullptr) {
391 return nullptr;
392 }
393 PyObject* fast = PySequence_Fast(values, "mapping.values() are not iterable");
394 Py_DECREF(values);
395 return fast;
396}
397
398// Number Protocol
399
400PY_EXPORT PyObject* PyNumber_Absolute(PyObject* obj) {
401 return doUnaryOp(ID(abs), obj);
402}
403
404static PyObject* smallIntAdd(PyObject* left, PyObject* right) {
405 RawObject left_obj = ApiHandle::asObject(ApiHandle::fromPyObject(left));
406 RawObject right_obj = ApiHandle::asObject(ApiHandle::fromPyObject(right));
407 if (left_obj.isSmallInt() && right_obj.isSmallInt()) {
408 Runtime* runtime = Thread::current()->runtime();
409 return ApiHandle::newReference(
410 runtime, runtime->newInt(SmallInt::cast(left_obj).value() +
411 SmallInt::cast(right_obj).value()));
412 }
413 return nullptr;
414}
415
416PY_EXPORT PyObject* PyNumber_Add(PyObject* left, PyObject* right) {
417 PyObject* result = smallIntAdd(left, right);
418 if (result != nullptr) {
419 // Fast path: smallint + smallint.
420 return result;
421 }
422 return doBinaryOp(ID(add), left, right);
423}
424
425PY_EXPORT PyObject* PyNumber_And(PyObject* left, PyObject* right) {
426 return doBinaryOp(ID(and_), left, right);
427}
428
429PY_EXPORT Py_ssize_t PyNumber_AsSsize_t(PyObject* obj, PyObject* overflow_err) {
430 Thread* thread = Thread::current();
431 if (obj == nullptr) {
432 nullError(thread);
433 return -1;
434 }
435 HandleScope scope(thread);
436 Object index(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
437 Object num(&scope, intFromIndex(thread, index));
438 if (num.isError()) return -1;
439 Int number(&scope, intUnderlying(*num));
440 if (overflow_err == nullptr || number.numDigits() == 1) {
441 // Overflows should be clipped, or value is already in range.
442 return number.asWordSaturated();
443 }
444 // Value overflows, raise an exception.
445 thread->setPendingExceptionType(
446 ApiHandle::asObject(ApiHandle::fromPyObject(overflow_err)));
447 thread->setPendingExceptionValue(thread->runtime()->newStrFromFmt(
448 "cannot fit '%T' into an index-sized integer", &index));
449 return -1;
450}
451
452PY_EXPORT int PyNumber_Check(PyObject* obj) {
453 if (obj == nullptr) {
454 return false;
455 }
456
457 Thread* thread = Thread::current();
458 HandleScope scope(thread);
459 Object num(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
460 Type type(&scope, thread->runtime()->typeOf(*num));
461 if (!typeLookupInMroById(thread, *type, ID(__int__)).isErrorNotFound()) {
462 return true;
463 }
464 if (!typeLookupInMroById(thread, *type, ID(__float__)).isErrorNotFound()) {
465 return true;
466 }
467 return false;
468}
469
470PY_EXPORT PyObject* PyNumber_Divmod(PyObject* left, PyObject* right) {
471 return doBinaryOp(ID(divmod), left, right);
472}
473
474PY_EXPORT PyObject* PyNumber_Float(PyObject* obj) {
475 Thread* thread = Thread::current();
476 if (obj == nullptr) {
477 return nullError(thread);
478 }
479 HandleScope scope(thread);
480 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
481 Object flt(&scope, thread->invokeFunction1(ID(builtins), ID(float), object));
482 return flt.isError() ? nullptr
483 : ApiHandle::newReference(thread->runtime(), *flt);
484}
485
486PY_EXPORT PyObject* PyNumber_FloorDivide(PyObject* left, PyObject* right) {
487 return doBinaryOp(ID(floordiv), left, right);
488}
489
490PY_EXPORT PyObject* PyNumber_Index(PyObject* item) {
491 Thread* thread = Thread::current();
492 if (item == nullptr) {
493 return nullError(thread);
494 }
495
496 HandleScope scope(thread);
497 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(item)));
498 Object index(&scope, intFromIndex(thread, obj));
499 return index.isError() ? nullptr
500 : ApiHandle::newReference(thread->runtime(), *index);
501}
502
503PY_EXPORT PyObject* PyNumber_InPlaceAdd(PyObject* left, PyObject* right) {
504 PyObject* result = smallIntAdd(left, right);
505 if (result != nullptr) {
506 // Fast path: smallint + smallint.
507 // In case operands are SmallInts, InPlaceAdd doesn't mutate them.
508 return result;
509 }
510 return doBinaryOp(ID(iadd), left, right);
511}
512
513PY_EXPORT PyObject* PyNumber_InPlaceAnd(PyObject* left, PyObject* right) {
514 return doBinaryOp(ID(iand), left, right);
515}
516
517PY_EXPORT PyObject* PyNumber_InPlaceFloorDivide(PyObject* left,
518 PyObject* right) {
519 return doBinaryOp(ID(ifloordiv), left, right);
520}
521
522PY_EXPORT PyObject* PyNumber_InPlaceLshift(PyObject* left, PyObject* right) {
523 return doBinaryOp(ID(ilshift), left, right);
524}
525
526PY_EXPORT PyObject* PyNumber_InPlaceMatrixMultiply(PyObject* left,
527 PyObject* right) {
528 return doBinaryOp(ID(imatmul), left, right);
529}
530
531PY_EXPORT PyObject* PyNumber_InPlaceMultiply(PyObject* left, PyObject* right) {
532 return doBinaryOp(ID(imul), left, right);
533}
534
535PY_EXPORT PyObject* PyNumber_InPlaceOr(PyObject* left, PyObject* right) {
536 return doBinaryOp(ID(ior), left, right);
537}
538
539PY_EXPORT PyObject* PyNumber_InPlacePower(PyObject* base, PyObject* exponent,
540 PyObject* divisor) {
541 if (divisor == Py_None) {
542 return doBinaryOp(ID(ipow), base, exponent);
543 }
544 UNIMPLEMENTED("ipow(base, exponent, divisor)");
545}
546
547PY_EXPORT PyObject* PyNumber_InPlaceRemainder(PyObject* left, PyObject* right) {
548 return doBinaryOp(ID(imod), left, right);
549}
550
551PY_EXPORT PyObject* PyNumber_InPlaceRshift(PyObject* left, PyObject* right) {
552 return doBinaryOp(ID(irshift), left, right);
553}
554
555PY_EXPORT PyObject* PyNumber_InPlaceSubtract(PyObject* left, PyObject* right) {
556 return doBinaryOp(ID(isub), left, right);
557}
558
559PY_EXPORT PyObject* PyNumber_InPlaceTrueDivide(PyObject* left,
560 PyObject* right) {
561 return doBinaryOp(ID(itruediv), left, right);
562}
563
564PY_EXPORT PyObject* PyNumber_InPlaceXor(PyObject* left, PyObject* right) {
565 return doBinaryOp(ID(ixor), left, right);
566}
567
568PY_EXPORT PyObject* PyNumber_Invert(PyObject* pyobj) {
569 return doUnaryOp(ID(invert), pyobj);
570}
571
572PY_EXPORT PyObject* PyNumber_Long(PyObject* obj) {
573 Thread* thread = Thread::current();
574 if (obj == nullptr) {
575 return nullError(thread);
576 }
577 HandleScope scope(thread);
578 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
579 Object result(&scope, thread->invokeFunction1(ID(builtins), ID(int), object));
580 if (result.isError()) {
581 return nullptr;
582 }
583 return ApiHandle::newReference(thread->runtime(), *result);
584}
585
586PY_EXPORT PyObject* PyNumber_Lshift(PyObject* left, PyObject* right) {
587 return doBinaryOp(ID(lshift), left, right);
588}
589
590PY_EXPORT PyObject* PyNumber_MatrixMultiply(PyObject* left, PyObject* right) {
591 return doBinaryOp(ID(matmul), left, right);
592}
593
594PY_EXPORT PyObject* PyNumber_Multiply(PyObject* left, PyObject* right) {
595 return doBinaryOp(ID(mul), left, right);
596}
597
598PY_EXPORT PyObject* PyNumber_Negative(PyObject* pyobj) {
599 return doUnaryOp(ID(neg), pyobj);
600}
601
602PY_EXPORT PyObject* PyNumber_Or(PyObject* left, PyObject* right) {
603 return doBinaryOp(ID(or_), left, right);
604}
605
606PY_EXPORT PyObject* PyNumber_Positive(PyObject* pyobj) {
607 return doUnaryOp(ID(pos), pyobj);
608}
609
610PY_EXPORT PyObject* PyNumber_Power(PyObject* base, PyObject* exponent,
611 PyObject* divisor) {
612 if (divisor == Py_None) {
613 return doBinaryOp(ID(pow), base, exponent);
614 }
615 UNIMPLEMENTED("pow(base, exponent, divisor)");
616}
617
618PY_EXPORT PyObject* PyNumber_Remainder(PyObject* left, PyObject* right) {
619 return doBinaryOp(ID(mod), left, right);
620}
621
622PY_EXPORT PyObject* PyNumber_Rshift(PyObject* left, PyObject* right) {
623 return doBinaryOp(ID(rshift), left, right);
624}
625
626PY_EXPORT PyObject* PyNumber_Subtract(PyObject* left, PyObject* right) {
627 return doBinaryOp(ID(sub), left, right);
628}
629
630PY_EXPORT PyObject* PyNumber_ToBase(PyObject* n, int base) {
631 Thread* thread = Thread::current();
632 HandleScope scope(thread);
633 Object n_object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(n)));
634 n_object = intFromIndex(thread, n_object);
635 if (n_object.isError()) {
636 return nullptr;
637 }
638 Int number(&scope, intUnderlying(*n_object));
639 Object formatted(&scope, NoneType::object());
640 switch (base) {
641 case 2:
642 formatted = formatIntBinarySimple(thread, number);
643 break;
644 case 8:
645 formatted = formatIntOctalSimple(thread, number);
646 break;
647 case 10:
648 formatted = formatIntDecimalSimple(thread, number);
649 break;
650 case 16:
651 formatted = formatIntHexadecimalSimple(thread, number);
652 break;
653 default:
654 thread->raiseWithFmt(LayoutId::kSystemError,
655 "PyNumber_ToBase: base must be 2, 8, 10 or 16");
656 return nullptr;
657 }
658 return ApiHandle::newReference(thread->runtime(), *formatted);
659}
660
661PY_EXPORT PyObject* PyNumber_TrueDivide(PyObject* left, PyObject* right) {
662 return doBinaryOp(ID(truediv), left, right);
663}
664
665PY_EXPORT PyObject* PyNumber_Xor(PyObject* left, PyObject* right) {
666 return doBinaryOp(ID(xor), left, right);
667}
668
669// Object Protocol
670
671PY_EXPORT int PyObject_AsCharBuffer(PyObject* /* j */,
672 const char** /* buffer */,
673 Py_ssize_t* /* n */) {
674 UNIMPLEMENTED("PyObject_AsCharBuffer");
675}
676
677PY_EXPORT int PyObject_AsReadBuffer(PyObject* /* j */,
678 const void** /* buffer */,
679 Py_ssize_t* /* n */) {
680 UNIMPLEMENTED("PyObject_AsReadBuffer");
681}
682
683PY_EXPORT int PyObject_AsWriteBuffer(PyObject* /* j */, void** /* buffer */,
684 Py_ssize_t* /* n */) {
685 UNIMPLEMENTED("PyObject_AsWriteBuffer");
686}
687
688PY_EXPORT PyObject* PyObject_Call(PyObject* callable, PyObject* args,
689 PyObject* kwargs) {
690 Thread* thread = Thread::current();
691 if (callable == nullptr) {
692 return nullError(thread);
693 }
694
695 DCHECK(!thread->hasPendingException(),
696 "may accidentally clear pending exception");
697
698 HandleScope scope(thread);
699 Runtime* runtime = thread->runtime();
700 Object callable_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(callable)));
701 Type callable_type(&scope, runtime->typeOf(*callable_obj));
702 if (typeHasSlots(callable_type)) {
703 // Attempt to call tp_call directly for native types to avoid
704 // recursive interpreter calls.
705 void* tp_call_value = typeSlotAt(callable_type, Py_tp_call);
706 if (tp_call_value != nullptr) {
707 ternaryfunc call = reinterpret_cast<ternaryfunc>(tp_call_value);
708 return call(callable, args, kwargs);
709 }
710 }
711 thread->stackPush(*callable_obj);
712
713 Object args_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(args)));
714 DCHECK(runtime->isInstanceOfTuple(*args_obj), "args mut be a tuple");
715 thread->stackPush(*args_obj);
716
717 word flags = 0;
718 if (kwargs != nullptr) {
719 Object kwargs_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(kwargs)));
720 DCHECK(thread->runtime()->isInstanceOfDict(*kwargs_obj),
721 "kwargs must be a dict");
722 thread->stackPush(*kwargs_obj);
723 flags |= CallFunctionExFlag::VAR_KEYWORDS;
724 }
725
726 // TODO(T30925218): Protect against native stack overflow.
727
728 Object result(&scope, Interpreter::callEx(thread, flags));
729 if (result.isError()) return nullptr;
730 return ApiHandle::newReference(runtime, *result);
731}
732
733static PyObject* makeInterpreterCall(Thread* thread, word nargs) {
734 HandleScope scope(thread);
735 Object result(&scope, Interpreter::call(thread, nargs));
736 if (result.isError()) return nullptr;
737 return ApiHandle::newReference(thread->runtime(), *result);
738}
739
740static PyObject* callWithVarArgs(Thread* thread, const Object& callable,
741 const char* format, std::va_list* va,
742 int build_value_flags) {
743 thread->stackPush(*callable);
744
745 if (format == nullptr) {
746 return makeInterpreterCall(thread, /*nargs=*/0);
747 }
748
749 word nargs = countFormat(format, '\0');
750 if (nargs == 1) {
751 PyObject* value = makeValueFromFormat(&format, va, build_value_flags);
752 if (!PyTuple_Check(value)) {
753 thread->stackPush(ApiHandle::stealReference(value));
754 return makeInterpreterCall(thread, nargs);
755 }
756 // If the only argument passed is a tuple, splat the tuple as positional
757 // arguments
758 nargs = PyTuple_Size(value);
759 for (word i = 0; i < nargs; i++) {
760 PyObject* arg = PyTuple_GetItem(value, i);
761 thread->stackPush(ApiHandle::asObject(ApiHandle::fromPyObject(arg)));
762 }
763 return makeInterpreterCall(thread, nargs);
764 }
765 for (const char* f = format; *f != '\0';) {
766 PyObject* value = makeValueFromFormat(&f, va, build_value_flags);
767 if (value == nullptr) break;
768 thread->stackPush(ApiHandle::stealReference(value));
769 }
770
771 return makeInterpreterCall(thread, nargs);
772}
773
774static PyObject* callFunction(PyObject* callable, const char* format,
775 std::va_list* va) {
776 Thread* thread = Thread::current();
777 if (callable == nullptr) {
778 return nullError(thread);
779 }
780
781 HandleScope scope(thread);
782 Object callable_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(callable)));
783 PyObject* result = callWithVarArgs(thread, callable_obj, format, va, 0);
784 return result;
785}
786
787PY_EXPORT PyObject* PyObject_CallFunction(PyObject* callable,
788 const char* format, ...) {
789 va_list va;
790 va_start(va, format);
791 PyObject* result = callFunction(callable, format, &va);
792 va_end(va);
793 return result;
794}
795
796PY_EXPORT PyObject* PyEval_CallFunction(PyObject* callable, const char* format,
797 ...) {
798 va_list va;
799 va_start(va, format);
800 PyObject* result = callFunction(callable, format, &va);
801 va_end(va);
802 return result;
803}
804
805static PyObject* callWithObjArgs(Thread* thread, const Object& callable,
806 std::va_list va) {
807 DCHECK(!thread->hasPendingException(),
808 "may accidentally clear pending exception");
809
810 thread->stackPush(*callable);
811 word nargs = 0;
812 for (PyObject* arg; (arg = va_arg(va, PyObject*)) != nullptr; nargs++) {
813 thread->stackPush(ApiHandle::asObject(ApiHandle::fromPyObject(arg)));
814 }
815
816 // TODO(T30925218): CPython tracks recursive calls before calling the function
817 // through Py_EnterRecursiveCall, and we should probably do the same
818 HandleScope scope(thread);
819 Object result(&scope, Interpreter::call(thread, nargs));
820 if (result.isError()) return nullptr;
821 return ApiHandle::newReference(thread->runtime(), *result);
822}
823
824PY_EXPORT PyObject* PyObject_CallFunctionObjArgs(PyObject* callable, ...) {
825 Thread* thread = Thread::current();
826 if (callable == nullptr) {
827 return nullError(thread);
828 }
829 HandleScope scope(thread);
830 Object callable_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(callable)));
831 va_list va;
832 va_start(va, callable);
833 PyObject* result = callWithObjArgs(thread, callable_obj, va);
834 va_end(va);
835 return result;
836}
837
838PY_EXPORT PyObject* _PyObject_CallFunction_SizeT(PyObject* callable,
839 const char* format, ...) {
840 Thread* thread = Thread::current();
841 if (callable == nullptr) {
842 return nullError(thread);
843 }
844
845 HandleScope scope(thread);
846 Object callable_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(callable)));
847 va_list va;
848 va_start(va, format);
849 PyObject* result =
850 callWithVarArgs(thread, callable_obj, format, &va, kFlagSizeT);
851 va_end(va);
852 return result;
853}
854
855static PyObject* callMethod(PyObject* pyobj, const char* name,
856 const char* format, std::va_list* va) {
857 Thread* thread = Thread::current();
858 if (pyobj == nullptr) {
859 return nullError(thread);
860 }
861
862 HandleScope scope(thread);
863 Runtime* runtime = thread->runtime();
864 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
865 Object callable(&scope, runtime->attributeAtByCStr(thread, obj, name));
866 if (callable.isError()) return nullptr;
867
868 PyObject* result = callWithVarArgs(thread, callable, format, va, 0);
869 return result;
870}
871
872PY_EXPORT PyObject* PyObject_CallMethod(PyObject* pyobj, const char* name,
873 const char* format, ...) {
874 va_list va;
875 va_start(va, format);
876 PyObject* result = callMethod(pyobj, name, format, &va);
877 va_end(va);
878 return result;
879}
880
881PY_EXPORT PyObject* PyEval_CallMethod(PyObject* pyobj, const char* name,
882 const char* format, ...) {
883 va_list va;
884 va_start(va, format);
885 PyObject* result = callMethod(pyobj, name, format, &va);
886 va_end(va);
887 return result;
888}
889
890PY_EXPORT PyObject* PyObject_CallMethodObjArgs(PyObject* pyobj,
891 PyObject* py_method_name, ...) {
892 Thread* thread = Thread::current();
893 if (pyobj == nullptr || py_method_name == nullptr) {
894 return nullError(thread);
895 }
896 HandleScope scope(thread);
897 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
898 Object name(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(py_method_name)));
899 name = attributeName(thread, name);
900 if (name.isErrorException()) return nullptr;
901 Object callable(&scope, thread->runtime()->attributeAt(thread, obj, name));
902 if (callable.isError()) return nullptr;
903
904 va_list va;
905 va_start(va, py_method_name);
906 PyObject* result = callWithObjArgs(thread, callable, va);
907 va_end(va);
908 return result;
909}
910
911PY_EXPORT PyObject* _PyObject_CallMethod_SizeT(PyObject* pyobj,
912 const char* name,
913 const char* format, ...) {
914 Thread* thread = Thread::current();
915 if (pyobj == nullptr) {
916 return nullError(thread);
917 }
918
919 HandleScope scope(thread);
920 Runtime* runtime = thread->runtime();
921 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
922 Object callable(&scope, runtime->attributeAtByCStr(thread, obj, name));
923 if (callable.isError()) return nullptr;
924
925 va_list va;
926 va_start(va, format);
927 PyObject* result = callWithVarArgs(thread, callable, format, &va, kFlagSizeT);
928 va_end(va);
929 return result;
930}
931
932PY_EXPORT PyObject* PyObject_CallObject(PyObject* callable, PyObject* args) {
933 Thread* thread = Thread::current();
934 if (callable == nullptr) {
935 return nullError(thread);
936 }
937 DCHECK(!thread->hasPendingException(),
938 "may accidentally clear pending exception");
939 HandleScope scope(thread);
940 thread->stackPush(ApiHandle::asObject(ApiHandle::fromPyObject(callable)));
941 Object result(&scope, NoneType::object());
942 Runtime* runtime = thread->runtime();
943 if (args != nullptr) {
944 Object args_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(args)));
945 if (!runtime->isInstanceOfTuple(*args_obj)) {
946 thread->raiseWithFmt(LayoutId::kTypeError,
947 "argument list must be a tuple");
948 return nullptr;
949 }
950 thread->stackPush(*args_obj);
951 // TODO(T30925218): Protect against native stack overflow.
952 result = Interpreter::callEx(thread, 0);
953 } else {
954 result = Interpreter::call(thread, 0);
955 }
956 if (result.isError()) return nullptr;
957 return ApiHandle::newReference(runtime, *result);
958}
959
960PY_EXPORT int PyObject_CheckBuffer_Func(PyObject* pyobj) {
961 // TODO(T38246066): Collapse all the cases into Runtime::isByteslike and make
962 // this function a small wrapper around that
963 Thread* thread = Thread::current();
964 HandleScope scope(thread);
965 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
966 Runtime* runtime = thread->runtime();
967 if (runtime->isInstanceOfBytes(*obj) ||
968 runtime->isInstanceOfBytearray(*obj)) {
969 return true;
970 }
971 if (runtime->isByteslike(*obj)) {
972 UNIMPLEMENTED("PyObject_CheckBuffer with builtin byteslike");
973 }
974 Type type(&scope, runtime->typeOf(*obj));
975 if (type.isBuiltin()) return false;
976 if (!typeHasSlots(type)) return false;
977 return typeSlotAt(type, Py_bf_getbuffer) != nullptr;
978}
979
980PY_EXPORT int PyObject_CheckReadBuffer(PyObject* /* j */) {
981 UNIMPLEMENTED("PyObject_CheckReadBuffer");
982}
983
984PY_EXPORT int PyObject_DelItem(PyObject* obj, PyObject* key) {
985 Thread* thread = Thread::current();
986 if (obj == nullptr || key == nullptr) {
987 nullError(thread);
988 return -1;
989 }
990 HandleScope scope(thread);
991 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
992 Object key_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(key)));
993 Object result(&scope, objectDelItem(thread, object, key_obj));
994 if (result.isErrorException()) {
995 return -1;
996 }
997 return 0;
998}
999
1000PY_EXPORT int PyObject_DelItemString(PyObject* obj, const char* key) {
1001 Thread* thread = Thread::current();
1002 if (obj == nullptr || key == nullptr) {
1003 nullError(thread);
1004 return -1;
1005 }
1006 HandleScope scope(thread);
1007 Runtime* runtime = thread->runtime();
1008 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1009 Object key_obj(&scope, runtime->newStrFromCStr(key));
1010 Object result(&scope, objectDelItem(thread, object, key_obj));
1011 if (result.isErrorException()) {
1012 return -1;
1013 }
1014 return 0;
1015}
1016
1017PY_EXPORT PyObject* _PyObject_CallNoArg(PyObject* callable) {
1018 return _PyObject_FastCall(callable, nullptr, 0);
1019}
1020
1021PY_EXPORT PyObject* _PyObject_FastCall(PyObject* callable, PyObject** pyargs,
1022 Py_ssize_t n_args) {
1023 return _PyObject_FastCallDict(callable, pyargs, n_args, nullptr);
1024}
1025
1026PY_EXPORT PyObject* _PyObject_FastCallDict(PyObject* callable,
1027 PyObject** pyargs, Py_ssize_t n_args,
1028 PyObject* kwargs) {
1029 DCHECK(callable != nullptr, "callable must not be nullptr");
1030 Thread* thread = Thread::current();
1031 DCHECK(!thread->hasPendingException(),
1032 "may accidentally clear pending exception");
1033 DCHECK(n_args >= 0, "n_args must not be negative");
1034
1035 HandleScope scope(thread);
1036 thread->stackPush(ApiHandle::asObject(ApiHandle::fromPyObject(callable)));
1037 DCHECK(n_args == 0 || pyargs != nullptr, "Args array must not be nullptr");
1038 Object result(&scope, NoneType::object());
1039 Runtime* runtime = thread->runtime();
1040 if (kwargs != nullptr) {
1041 Object args_obj(&scope, NoneType::object());
1042 if (n_args > 0) {
1043 MutableTuple args(&scope, runtime->newMutableTuple(n_args));
1044 for (Py_ssize_t i = 0; i < n_args; i++) {
1045 args.atPut(i, ApiHandle::asObject(ApiHandle::fromPyObject(pyargs[i])));
1046 }
1047 args_obj = args.becomeImmutable();
1048 } else {
1049 args_obj = runtime->emptyTuple();
1050 }
1051 thread->stackPush(*args_obj);
1052 Object kwargs_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(kwargs)));
1053 DCHECK(runtime->isInstanceOfDict(*kwargs_obj), "kwargs must be a dict");
1054 thread->stackPush(*kwargs_obj);
1055 // TODO(T30925218): Protect against native stack overflow.
1056 result = Interpreter::callEx(thread, CallFunctionExFlag::VAR_KEYWORDS);
1057 } else {
1058 for (Py_ssize_t i = 0; i < n_args; i++) {
1059 thread->stackPush(ApiHandle::asObject(ApiHandle::fromPyObject(pyargs[i])));
1060 }
1061 // TODO(T30925218): Protect against native stack overflow.
1062 result = Interpreter::call(thread, n_args);
1063 }
1064 if (result.isError()) return nullptr;
1065 return ApiHandle::newReference(runtime, *result);
1066}
1067
1068PY_EXPORT PyObject* _PyObject_FastCallKeywords(PyObject* /* e */,
1069 PyObject** /* k */,
1070 Py_ssize_t /* s */,
1071 PyObject* /* s */) {
1072 UNIMPLEMENTED("_PyObject_FastCallKeywords");
1073}
1074
1075PY_EXPORT PyObject* PyObject_Format(PyObject* obj, PyObject* format_spec) {
1076 DCHECK(obj != nullptr, "obj should not be null");
1077 Thread* thread = Thread::current();
1078 HandleScope scope(thread);
1079 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1080 Object format_spec_obj(
1081 &scope, format_spec == nullptr
1082 ? Str::empty()
1083 : ApiHandle::asObject(ApiHandle::fromPyObject(format_spec)));
1084 Object result(&scope, thread->invokeFunction2(ID(builtins), ID(format),
1085 object, format_spec_obj));
1086 if (result.isError()) {
1087 return nullptr;
1088 }
1089 return ApiHandle::newReference(thread->runtime(), *result);
1090}
1091
1092PY_EXPORT int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) {
1093 DCHECK(obj != nullptr, "obj must not be nullptr");
1094
1095 Thread* thread = Thread::current();
1096 ApiHandle* handle = ApiHandle::fromPyObject(obj);
1097 HandleScope scope(thread);
1098 Object obj_obj(&scope, ApiHandle::asObject(handle));
1099 Runtime* runtime = thread->runtime();
1100 if (runtime->isInstanceOfBytes(*obj_obj)) {
1101 Bytes bytes(&scope, bytesUnderlying(*obj_obj));
1102 char* buffer = bytesAsString(runtime, handle, bytes);
1103 if (buffer == nullptr) {
1104 return -1;
1105 }
1106 return PyBuffer_FillInfo(view, handle, buffer, bytes.length(),
1107 /*readonly=*/1, flags);
1108 }
1109 if (runtime->isInstanceOfBytearray(*obj_obj)) {
1110 // TODO(T54579154): This creates a copy of the object which does not stay
1111 // in sync. We should have a way to pin the memory to allow direct access.
1112 Bytearray array(&scope, *obj_obj);
1113 char* buffer = bytearrayAsString(runtime, handle, array);
1114 if (buffer == nullptr) {
1115 return -1;
1116 }
1117 return PyBuffer_FillInfo(view, handle, buffer, array.numItems(),
1118 /*readonly=*/1, flags);
1119 }
1120 if (obj_obj.isMemoryView()) {
1121 MemoryView memoryview(&scope, *obj_obj);
1122 Object buffer(&scope, memoryview.buffer());
1123 // A MemoryView's underlying buffer is either a bytes object or a raw
1124 // pointer.
1125 if (runtime->isInstanceOfBytes(*buffer)) {
1126 Bytes bytes(&scope, bytesUnderlying(*obj_obj));
1127 // We use the memoryview handle's cache directly to store the buffer.
1128 char* underlying_buffer = bytesAsString(runtime, handle, bytes);
1129 if (underlying_buffer == nullptr) {
1130 return -1;
1131 }
1132 return PyBuffer_FillInfo(view, handle, underlying_buffer,
1133 memoryview.length(),
1134 /*readonly=*/1, flags);
1135 }
1136
1137 Pointer underlying_pointer(&scope, *buffer);
1138 char* underlying_buffer =
1139 reinterpret_cast<char*>(underlying_pointer.cptr());
1140 return PyBuffer_FillInfo(view, handle, underlying_buffer,
1141 memoryview.length(),
1142 /*readonly=*/1, flags);
1143 }
1144 if (runtime->isInstanceOfArray(*obj_obj)) {
1145 Array array(&scope, *obj_obj);
1146 word length = arrayByteLength(*array);
1147 // We create a copy of the array's buffer and place it in the API handle's
1148 // cache to ensure it gets reaped.
1149 if (void* cache = ApiHandle::cache(runtime, handle)) {
1150 std::free(cache);
1151 }
1152 byte* buffer = static_cast<byte*>(std::malloc(length + 1));
1153 if (buffer == nullptr) {
1154 return -1;
1155 }
1156 MutableBytes::cast(array.buffer()).copyTo(buffer, length);
1157 ApiHandle::setCache(runtime, handle, buffer);
1158
1159 return PyBuffer_FillInfo(view, handle, reinterpret_cast<char*>(buffer),
1160 length,
1161 /*readonly=*/1, flags);
1162 }
1163 // We must be dealing with a buffer protocol or an incompatible type.
1164 Type type(&scope, runtime->typeOf(*obj_obj));
1165 if (type.isBuiltin()) {
1166 raiseBufferError(thread, obj_obj);
1167 return -1;
1168 }
1169 if (!typeHasSlots(type)) {
1170 raiseBufferError(thread, obj_obj);
1171 return -1;
1172 }
1173 void* slot = typeSlotAt(type, Py_bf_getbuffer);
1174 if (slot == nullptr) {
1175 raiseBufferError(thread, obj_obj);
1176 return -1;
1177 }
1178 return reinterpret_cast<getbufferproc>(slot)(handle, view, flags);
1179}
1180
1181PY_EXPORT PyObject* PyObject_GetItem(PyObject* obj, PyObject* key) {
1182 Thread* thread = Thread::current();
1183 if (obj == nullptr || key == nullptr) {
1184 return nullError(thread);
1185 }
1186 HandleScope scope(thread);
1187 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1188 Object key_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(key)));
1189 Object result(&scope, objectGetItem(thread, object, key_obj));
1190 if (result.isErrorException()) return nullptr;
1191 return ApiHandle::newReference(thread->runtime(), *result);
1192}
1193
1194PY_EXPORT PyObject* PyObject_GetIter(PyObject* pyobj) {
1195 Thread* thread = Thread::current();
1196 HandleScope scope(thread);
1197 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
1198 Object result(&scope, Interpreter::createIterator(thread, obj));
1199 if (result.isError()) {
1200 return nullptr;
1201 }
1202 return ApiHandle::newReference(thread->runtime(), *result);
1203}
1204
1205PY_EXPORT int PyObject_IsInstance(PyObject* instance, PyObject* cls) {
1206 Thread* thread = Thread::current();
1207 HandleScope scope(thread);
1208 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(instance)));
1209 Object classinfo(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(cls)));
1210 Object result(&scope, thread->invokeFunction2(ID(builtins), ID(isinstance),
1211 object, classinfo));
1212 return result.isError() ? -1 : Bool::cast(*result).value();
1213}
1214
1215PY_EXPORT int PyObject_IsSubclass(PyObject* derived, PyObject* cls) {
1216 Thread* thread = Thread::current();
1217 HandleScope scope(thread);
1218 Object subclass(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(derived)));
1219 Object classinfo(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(cls)));
1220 Object result(&scope, thread->invokeFunction2(ID(builtins), ID(issubclass),
1221 subclass, classinfo));
1222 return result.isError() ? -1 : Bool::cast(*result).value();
1223}
1224
1225PY_EXPORT Py_ssize_t PyObject_Length(PyObject* pyobj) {
1226 return objectLength(pyobj);
1227}
1228
1229PY_EXPORT Py_ssize_t PyObject_LengthHint(PyObject* obj,
1230 Py_ssize_t default_value) {
1231 Py_ssize_t res = objectLength(obj);
1232 Thread* thread = Thread::current();
1233 Runtime* runtime = thread->runtime();
1234 HandleScope scope(thread);
1235 if (res < 0 && thread->hasPendingException()) {
1236 Object given_obj(&scope, thread->pendingExceptionType());
1237 Object exc_obj(&scope, runtime->typeAt(LayoutId::kTypeError));
1238 if (!givenExceptionMatches(thread, given_obj, exc_obj)) {
1239 return -1;
1240 }
1241 // Catch TypeError when obj does not have __len__.
1242 thread->clearPendingException();
1243 } else {
1244 return res;
1245 }
1246
1247 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1248 Object length_hint(&scope,
1249 thread->invokeMethod1(object, ID(__length_hint__)));
1250 if (length_hint.isErrorNotFound() || length_hint.isNotImplementedType()) {
1251 return default_value;
1252 }
1253 if (length_hint.isError()) {
1254 return -1;
1255 }
1256 if (!thread->runtime()->isInstanceOfInt(*length_hint)) {
1257 thread->raiseWithFmt(LayoutId::kTypeError,
1258 "__length_hint__ must be an integer, not %T",
1259 &length_hint);
1260 return -1;
1261 }
1262 Int index(&scope, intUnderlying(*length_hint));
1263 if (!index.isSmallInt()) {
1264 thread->raiseWithFmt(LayoutId::kOverflowError,
1265 "cannot fit '%T' into an index-sized integer",
1266 &length_hint);
1267 return -1;
1268 }
1269 if (index.isNegative()) {
1270 thread->raiseWithFmt(LayoutId::kValueError, "__len__() should return >= 0");
1271 return -1;
1272 }
1273 return index.asWord();
1274}
1275
1276PY_EXPORT int PyObject_SetItem(PyObject* obj, PyObject* key, PyObject* value) {
1277 Thread* thread = Thread::current();
1278 if (obj == nullptr || key == nullptr || value == nullptr) {
1279 nullError(thread);
1280 return -1;
1281 }
1282 HandleScope scope(thread);
1283 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1284 Object key_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(key)));
1285 Object value_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(value)));
1286 Object result(&scope, objectSetItem(thread, object, key_obj, value_obj));
1287 return result.isErrorException() ? -1 : 0;
1288}
1289
1290PY_EXPORT Py_ssize_t PyObject_Size(PyObject* pyobj) {
1291 return objectLength(pyobj);
1292}
1293
1294PY_EXPORT PyTypeObject* Py_TYPE_Func(PyObject* pyobj) {
1295 Thread* thread = Thread::current();
1296 if (pyobj == nullptr) {
1297 nullError(thread);
1298 return nullptr;
1299 }
1300
1301 Runtime* runtime = thread->runtime();
1302 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference(
1303 runtime, runtime->typeOf(ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)))));
1304}
1305
1306PY_EXPORT void Py_SET_TYPE_Func(PyObject* obj, PyTypeObject* type) {
1307 DCHECK(obj != nullptr, "obj must be non-null");
1308 DCHECK(type != nullptr, "type must be non-null");
1309 Thread* thread = Thread::current();
1310 HandleScope scope(thread);
1311 Object self(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1312 Type new_type(&scope, ApiHandle::asObject(ApiHandle::fromPyTypeObject(type)));
1313 Object result(&scope, typeSetDunderClass(thread, self, new_type));
1314 if (result.isError()) {
1315 UNIMPLEMENTED("unhandled case in __class__ setter");
1316 }
1317}
1318
1319PY_EXPORT PyObject* PyObject_Type(PyObject* pyobj) {
1320 Thread* thread = Thread::current();
1321 if (pyobj == nullptr) {
1322 return nullError(thread);
1323 }
1324
1325 Runtime* runtime = thread->runtime();
1326 return ApiHandle::newReference(
1327 runtime, runtime->typeOf(ApiHandle::asObject(ApiHandle::fromPyObject(pyobj))));
1328}
1329
1330PY_EXPORT const char* PyObject_TypeName(PyObject* /* obj */) {
1331 UNIMPLEMENTED("PyObject_TypeName");
1332}
1333
1334// Sequence Protocol
1335
1336PY_EXPORT void _Py_FreeCharPArray(char* const array[]) {
1337 for (Py_ssize_t i = 0; array[i] != nullptr; ++i) {
1338 PyMem_Free(array[i]);
1339 }
1340 PyMem_Free(const_cast<char**>(array));
1341}
1342
1343PY_EXPORT char* const* _PySequence_BytesToCharpArray(PyObject* self) {
1344 Py_ssize_t argc = PySequence_Size(self);
1345 if (argc < 0) {
1346 DCHECK(argc == -1, "size cannot be negative (-1 denotes an error)");
1347 return nullptr;
1348 }
1349
1350 if (argc > (kMaxWord / kPointerSize) - 1) {
1351 PyErr_NoMemory();
1352 return nullptr;
1353 }
1354
1355 char** result = static_cast<char**>(PyMem_Malloc((argc + 1) * kPointerSize));
1356 if (result == nullptr) {
1357 PyErr_NoMemory();
1358 return nullptr;
1359 }
1360
1361 for (Py_ssize_t i = 0; i < argc; ++i) {
1362 PyObject* item = PySequence_GetItem(self, i);
1363 if (item == nullptr) {
1364 // NULL terminate before freeing.
1365 result[i] = nullptr;
1366 _Py_FreeCharPArray(result);
1367 return nullptr;
1368 }
1369 char* data;
1370 if (PyBytes_AsStringAndSize(item, &data, nullptr) < 0) {
1371 // NULL terminate before freeing.
1372 result[i] = nullptr;
1373 Py_DECREF(item);
1374 _Py_FreeCharPArray(result);
1375 return nullptr;
1376 }
1377 Py_ssize_t size = PyBytes_GET_SIZE(item) + 1;
1378 result[i] = static_cast<char*>(PyMem_Malloc(size));
1379 if (result[i] == nullptr) {
1380 PyErr_NoMemory();
1381 Py_DECREF(item);
1382 _Py_FreeCharPArray(result);
1383 return nullptr;
1384 }
1385 std::memcpy(result[i], data, size);
1386 Py_DECREF(item);
1387 }
1388
1389 result[argc] = nullptr;
1390 return result;
1391}
1392
1393PY_EXPORT int PySequence_Check(PyObject* py_obj) {
1394 Thread* thread = Thread::current();
1395 HandleScope scope(thread);
1396 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(py_obj)));
1397 return thread->runtime()->isSequence(thread, obj);
1398}
1399
1400PY_EXPORT PyObject* PySequence_Concat(PyObject* left, PyObject* right) {
1401 Thread* thread = Thread::current();
1402 if (left == nullptr || right == nullptr) {
1403 return nullError(thread);
1404 }
1405 if (!PySequence_Check(left) || !PySequence_Check(right)) {
1406 thread->raiseWithFmt(LayoutId::kTypeError,
1407 "objects cannot be concatenated");
1408 return nullptr;
1409 }
1410 return PyNumber_Add(left, right);
1411}
1412
1413PY_EXPORT int PySequence_Contains(PyObject* seq, PyObject* obj) {
1414 Thread* thread = Thread::current();
1415 if (seq == nullptr || obj == nullptr) {
1416 nullError(thread);
1417 return -1;
1418 }
1419 HandleScope scope(thread);
1420 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1421 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1422 Object result(&scope, thread->invokeFunction2(ID(operator), ID(contains),
1423 seq_obj, object));
1424 if (result.isError()) {
1425 return -1;
1426 }
1427 return Bool::cast(*result).value() ? 1 : 0;
1428}
1429
1430PY_EXPORT Py_ssize_t PySequence_Count(PyObject* seq, PyObject* obj) {
1431 Thread* thread = Thread::current();
1432 if (seq == nullptr || obj == nullptr) {
1433 nullError(thread);
1434 return -1;
1435 }
1436 HandleScope scope(thread);
1437 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1438 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1439 Object result(&scope, thread->invokeFunction2(ID(operator), ID(countOf),
1440 seq_obj, object));
1441 if (result.isError()) {
1442 return -1;
1443 }
1444 return SmallInt::cast(*result).value();
1445}
1446
1447PY_EXPORT int PySequence_DelItem(PyObject* seq, Py_ssize_t idx) {
1448 Thread* thread = Thread::current();
1449 if (seq == nullptr) {
1450 return -1;
1451 }
1452 HandleScope scope(thread);
1453 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1454 Object idx_obj(&scope, thread->runtime()->newInt(idx));
1455 Object result(&scope,
1456 thread->invokeMethod2(seq_obj, ID(__delitem__), idx_obj));
1457 if (result.isError()) {
1458 return -1;
1459 }
1460 return 0;
1461}
1462
1463static RawObject makeSlice(Thread* thread, Py_ssize_t low, Py_ssize_t high) {
1464 HandleScope scope(thread);
1465 Runtime* runtime = thread->runtime();
1466 Object start(&scope, runtime->newInt(low));
1467 Object stop(&scope, runtime->newInt(high));
1468 Object step(&scope, NoneType::object());
1469 return runtime->newSlice(start, stop, step);
1470}
1471
1472PY_EXPORT int PySequence_DelSlice(PyObject* seq, Py_ssize_t low,
1473 Py_ssize_t high) {
1474 Thread* thread = Thread::current();
1475 if (seq == nullptr) {
1476 nullError(thread);
1477 return -1;
1478 }
1479 HandleScope scope(thread);
1480 Object slice(&scope, makeSlice(thread, low, high));
1481 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1482 Object result(&scope, thread->invokeMethod2(seq_obj, ID(__delitem__), slice));
1483 if (result.isError()) {
1484 if (result.isErrorNotFound()) {
1485 thread->raiseWithFmt(LayoutId::kTypeError,
1486 "object does not support slice deletion");
1487 }
1488 return -1;
1489 }
1490 return 0;
1491}
1492
1493PY_EXPORT PyObject* PySequence_Fast(PyObject* seq, const char* msg) {
1494 Thread* thread = Thread::current();
1495 if (seq == nullptr) {
1496 return nullError(thread);
1497 }
1498 HandleScope scope(thread);
1499 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1500
1501 Runtime* runtime = thread->runtime();
1502 if (seq_obj.isList() || seq_obj.isTuple()) {
1503 return ApiHandle::newReference(runtime, *seq_obj);
1504 }
1505 Object iter(&scope, Interpreter::createIterator(thread, seq_obj));
1506 if (iter.isError()) {
1507 Object given(&scope, thread->pendingExceptionType());
1508 Object exc(&scope, runtime->typeAt(LayoutId::kTypeError));
1509 if (givenExceptionMatches(thread, given, exc)) {
1510 thread->setPendingExceptionValue(runtime->newStrFromCStr(msg));
1511 }
1512 return nullptr;
1513 }
1514
1515 Object result(&scope,
1516 thread->invokeFunction1(ID(builtins), ID(list), seq_obj));
1517 if (result.isError()) {
1518 return nullptr;
1519 }
1520 return ApiHandle::newReference(runtime, *result);
1521}
1522
1523PY_EXPORT Py_ssize_t PySequence_Fast_GET_SIZE_Func(PyObject* seq) {
1524 return PyList_Check(seq) ? PyList_GET_SIZE(seq) : PyTuple_GET_SIZE(seq);
1525}
1526
1527PY_EXPORT PyObject* PySequence_Fast_GET_ITEM_Func(PyObject* seq,
1528 Py_ssize_t idx) {
1529 return PyList_Check(seq) ? PyList_GET_ITEM(seq, idx)
1530 : PyTuple_GET_ITEM(seq, idx);
1531}
1532
1533PY_EXPORT PyObject* PySequence_GetItem(PyObject* seq, Py_ssize_t idx) {
1534 Thread* thread = Thread::current();
1535 if (seq == nullptr) {
1536 return nullError(thread);
1537 }
1538 HandleScope scope(thread);
1539 Runtime* runtime = thread->runtime();
1540 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1541 if (seq_obj.isTuple()) {
1542 // Fast path: return `tuple`'s element directly.
1543 RawTuple tuple = Tuple::cast(*seq_obj);
1544 if (0 <= idx && idx < tuple.length()) {
1545 return ApiHandle::newReference(runtime, tuple.at(idx));
1546 }
1547 } else if (seq_obj.isList()) {
1548 // Fast path: return `list`'s element directly.
1549 RawList list = List::cast(*seq_obj);
1550 if (0 <= idx && idx < list.numItems()) {
1551 return ApiHandle::newReference(runtime, list.at(idx));
1552 }
1553 }
1554 Object idx_obj(&scope, thread->runtime()->newInt(idx));
1555 Object result(&scope,
1556 thread->invokeMethod2(seq_obj, ID(__getitem__), idx_obj));
1557 if (result.isError()) {
1558 if (result.isErrorNotFound()) {
1559 thread->raiseWithFmt(LayoutId::kTypeError, "could not call __getitem__");
1560 }
1561 return nullptr;
1562 }
1563 return ApiHandle::newReference(runtime, *result);
1564}
1565
1566PY_EXPORT PyObject* PySequence_ITEM_Func(PyObject* seq, Py_ssize_t i) {
1567 DCHECK(seq != nullptr, "sequence must not be nullptr");
1568 DCHECK(i >= 0, "index can't be negative");
1569 Thread* thread = Thread::current();
1570 HandleScope scope(thread);
1571 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1572 Runtime* runtime = thread->runtime();
1573 DCHECK(runtime->isSequence(thread, seq_obj), "seq must be a sequence");
1574 Object idx(&scope, runtime->newInt(i));
1575 Object result(&scope, thread->invokeMethod2(seq_obj, ID(__getitem__), idx));
1576 if (result.isError()) return nullptr;
1577 return ApiHandle::newReference(runtime, *result);
1578}
1579
1580PY_EXPORT PyObject* PySequence_GetSlice(PyObject* seq, Py_ssize_t low,
1581 Py_ssize_t high) {
1582 Thread* thread = Thread::current();
1583 if (seq == nullptr) {
1584 return nullError(thread);
1585 }
1586 HandleScope scope(thread);
1587 Object slice(&scope, makeSlice(thread, low, high));
1588 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1589 Object result(&scope, thread->invokeMethod2(seq_obj, ID(__getitem__), slice));
1590 if (result.isError()) {
1591 if (result.isErrorNotFound()) {
1592 thread->raiseWithFmt(LayoutId::kTypeError, "could not call __getitem__");
1593 }
1594 return nullptr;
1595 }
1596 return ApiHandle::newReference(thread->runtime(), *result);
1597}
1598
1599PY_EXPORT int PySequence_In(PyObject* pyseq, PyObject* pyobj) {
1600 return PySequence_Contains(pyseq, pyobj);
1601}
1602
1603PY_EXPORT Py_ssize_t PySequence_Index(PyObject* seq, PyObject* obj) {
1604 Thread* thread = Thread::current();
1605 if (seq == nullptr || obj == nullptr) {
1606 nullError(thread);
1607 return -1;
1608 }
1609 HandleScope scope(thread);
1610 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1611 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1612 Object result(&scope, thread->invokeFunction2(ID(operator), ID(indexOf),
1613 seq_obj, object));
1614 if (result.isError()) {
1615 return -1;
1616 }
1617 return SmallInt::cast(*result).value();
1618}
1619
1620PY_EXPORT PyObject* PySequence_InPlaceConcat(PyObject* left, PyObject* right) {
1621 Thread* thread = Thread::current();
1622 if (left == nullptr || right == nullptr) {
1623 return nullError(thread);
1624 }
1625 HandleScope scope(thread);
1626 Object left_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(left)));
1627 Object right_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(right)));
1628 Object result(&scope, thread->invokeFunction2(ID(operator), ID(iconcat),
1629 left_obj, right_obj));
1630 return result.isError() ? nullptr
1631 : ApiHandle::newReference(thread->runtime(), *result);
1632}
1633
1634PY_EXPORT PyObject* PySequence_InPlaceRepeat(PyObject* seq, Py_ssize_t count) {
1635 Thread* thread = Thread::current();
1636 if (seq == nullptr) {
1637 return nullError(thread);
1638 }
1639 HandleScope scope(thread);
1640 Runtime* runtime = thread->runtime();
1641 Object sequence(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1642 Object count_obj(&scope, runtime->newInt(count));
1643 Object result(&scope, thread->invokeFunction2(ID(operator), ID(irepeat),
1644 sequence, count_obj));
1645 return result.isError() ? nullptr : ApiHandle::newReference(runtime, *result);
1646}
1647
1648PY_EXPORT Py_ssize_t PySequence_Length(PyObject* pyobj) {
1649 return objectLength(pyobj);
1650}
1651
1652PY_EXPORT PyObject* PySequence_List(PyObject* seq) {
1653 Thread* thread = Thread::current();
1654 if (seq == nullptr) {
1655 return nullError(thread);
1656 }
1657 HandleScope scope(thread);
1658 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1659 RawObject result = thread->invokeFunction1(ID(builtins), ID(list), seq_obj);
1660 return result.isError() ? nullptr
1661 : ApiHandle::newReference(thread->runtime(), result);
1662}
1663
1664PY_EXPORT PyObject* PySequence_Repeat(PyObject* pyseq, Py_ssize_t count) {
1665 Thread* thread = Thread::current();
1666 if (pyseq == nullptr) {
1667 return nullError(thread);
1668 }
1669 if (!PySequence_Check(pyseq)) {
1670 thread->raiseWithFmt(LayoutId::kTypeError, "object cannot be repeated");
1671 return nullptr;
1672 }
1673 PyObject* count_obj(PyLong_FromSsize_t(count));
1674 PyObject* result = PyNumber_Multiply(pyseq, count_obj);
1675 Py_DECREF(count_obj);
1676 return result;
1677}
1678
1679PY_EXPORT int PySequence_SetItem(PyObject* seq, Py_ssize_t idx, PyObject* obj) {
1680 Thread* thread = Thread::current();
1681 if (seq == nullptr) {
1682 nullError(thread);
1683 return -1;
1684 }
1685 HandleScope scope(thread);
1686 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1687 Object idx_obj(&scope, thread->runtime()->newInt(idx));
1688 Object result(&scope, NoneType::object());
1689 if (obj == nullptr) {
1690 // Equivalent to PySequence_DelItem
1691 result = thread->invokeMethod2(seq_obj, ID(__delitem__), idx_obj);
1692 } else {
1693 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1694 result = thread->invokeMethod3(seq_obj, ID(__setitem__), idx_obj, object);
1695 }
1696 if (result.isError()) {
1697 if (result.isErrorNotFound()) {
1698 thread->raiseWithFmt(LayoutId::kTypeError, "object is not subscriptable");
1699 }
1700 return -1;
1701 }
1702 return 0;
1703}
1704
1705PY_EXPORT int PySequence_SetSlice(PyObject* seq, Py_ssize_t low,
1706 Py_ssize_t high, PyObject* obj) {
1707 Thread* thread = Thread::current();
1708 if (seq == nullptr) {
1709 nullError(thread);
1710 return -1;
1711 }
1712 HandleScope scope(thread);
1713 Object slice(&scope, makeSlice(thread, low, high));
1714 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1715 Object result(&scope, NoneType::object());
1716 if (obj == nullptr) {
1717 result = thread->invokeMethod2(seq_obj, ID(__delitem__), slice);
1718 } else {
1719 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
1720 result = thread->invokeMethod3(seq_obj, ID(__setitem__), slice, object);
1721 }
1722 if (result.isError()) {
1723 if (result.isErrorNotFound()) {
1724 thread->raiseWithFmt(LayoutId::kTypeError,
1725 "object does not support slice assignment");
1726 }
1727 return -1;
1728 }
1729 return 0;
1730}
1731
1732PY_EXPORT Py_ssize_t PySequence_Size(PyObject* pyobj) {
1733 return objectLength(pyobj);
1734}
1735
1736PY_EXPORT PyObject* PySequence_Tuple(PyObject* seq) {
1737 Thread* thread = Thread::current();
1738 if (seq == nullptr) {
1739 return nullError(thread);
1740 }
1741 HandleScope scope(thread);
1742 Object seq_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(seq)));
1743 Runtime* runtime = thread->runtime();
1744 if (seq_obj.isTuple()) {
1745 return ApiHandle::newReference(runtime, *seq_obj);
1746 }
1747 Object result(&scope,
1748 thread->invokeFunction1(ID(builtins), ID(tuple), seq_obj));
1749 if (result.isError()) {
1750 return nullptr;
1751 }
1752 return ApiHandle::newReference(runtime, *result);
1753}
1754
1755} // namespace py