mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-10 11:50:29 +00:00
parent
ec91a15584
commit
19e2a530b3
3 changed files with 105 additions and 41 deletions
2
third_party/python/Include/abstract.h
vendored
2
third_party/python/Include/abstract.h
vendored
|
@ -44,6 +44,8 @@ PyObject *_PyObject_Call_Prepend(PyObject *func, PyObject *obj, PyObject *args,
|
||||||
|
|
||||||
#define _PY_FASTCALL_SMALL_STACK 5
|
#define _PY_FASTCALL_SMALL_STACK 5
|
||||||
|
|
||||||
|
int _PyObject_HasFastCall(PyObject *callable);
|
||||||
|
|
||||||
PyObject *_PyObject_FastCall_Prepend(
|
PyObject *_PyObject_FastCall_Prepend(
|
||||||
PyObject *callable,
|
PyObject *callable,
|
||||||
PyObject *obj,
|
PyObject *obj,
|
||||||
|
|
129
third_party/python/Modules/_functoolsmodule.c
vendored
129
third_party/python/Modules/_functoolsmodule.c
vendored
|
@ -43,6 +43,7 @@ typedef struct {
|
||||||
PyObject *kw;
|
PyObject *kw;
|
||||||
PyObject *dict;
|
PyObject *dict;
|
||||||
PyObject *weakreflist; /* List of weak references */
|
PyObject *weakreflist; /* List of weak references */
|
||||||
|
int use_fastcall;
|
||||||
} partialobject;
|
} partialobject;
|
||||||
|
|
||||||
static PyTypeObject partial_type;
|
static PyTypeObject partial_type;
|
||||||
|
@ -135,6 +136,7 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pto->use_fastcall = _PyObject_HasFastCall(func);
|
||||||
return (PyObject *)pto;
|
return (PyObject *)pto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,66 +155,110 @@ partial_dealloc(partialobject *pto)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
partial_call(partialobject *pto, PyObject *args, PyObject *kw)
|
partial_fastcall(partialobject *pto, PyObject **args, Py_ssize_t nargs,
|
||||||
|
PyObject *kwargs)
|
||||||
{
|
{
|
||||||
|
PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
PyObject *argappl, *kwappl;
|
PyObject **stack, **stack_buf = NULL;
|
||||||
PyObject **stack;
|
Py_ssize_t nargs2, pto_nargs;
|
||||||
Py_ssize_t nargs;
|
|
||||||
|
pto_nargs = PyTuple_GET_SIZE(pto->args);
|
||||||
|
nargs2 = pto_nargs + nargs;
|
||||||
|
|
||||||
|
if (pto_nargs == 0) {
|
||||||
|
stack = args;
|
||||||
|
}
|
||||||
|
else if (nargs == 0) {
|
||||||
|
stack = &PyTuple_GET_ITEM(pto->args, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nargs2 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
|
||||||
|
stack = small_stack;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stack_buf = PyMem_Malloc(nargs2 * sizeof(PyObject *));
|
||||||
|
if (stack_buf == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
stack = stack_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use borrowed references */
|
||||||
|
memcpy(stack,
|
||||||
|
&PyTuple_GET_ITEM(pto->args, 0),
|
||||||
|
pto_nargs * sizeof(PyObject*));
|
||||||
|
memcpy(&stack[pto_nargs],
|
||||||
|
args,
|
||||||
|
nargs * sizeof(PyObject*));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _PyObject_FastCallDict(pto->fn, stack, nargs2, kwargs);
|
||||||
|
PyMem_Free(stack_buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
partial_call_impl(partialobject *pto, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
PyObject *ret, *args2;
|
||||||
|
|
||||||
|
/* Note: tupleconcat() is optimized for empty tuples */
|
||||||
|
args2 = PySequence_Concat(pto->args, args);
|
||||||
|
if (args2 == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
assert(PyTuple_Check(args2));
|
||||||
|
|
||||||
|
ret = PyObject_Call(pto->fn, args2, kwargs);
|
||||||
|
Py_DECREF(args2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
PyObject *kwargs2, *res;
|
||||||
|
|
||||||
assert (PyCallable_Check(pto->fn));
|
assert (PyCallable_Check(pto->fn));
|
||||||
assert (PyTuple_Check(pto->args));
|
assert (PyTuple_Check(pto->args));
|
||||||
assert (PyDict_Check(pto->kw));
|
assert (PyDict_Check(pto->kw));
|
||||||
|
|
||||||
if (PyTuple_GET_SIZE(pto->args) == 0) {
|
if (PyDict_GET_SIZE(pto->kw) == 0) {
|
||||||
stack = &PyTuple_GET_ITEM(args, 0);
|
/* kwargs can be NULL */
|
||||||
nargs = PyTuple_GET_SIZE(args);
|
kwargs2 = kwargs;
|
||||||
argappl = NULL;
|
Py_XINCREF(kwargs2);
|
||||||
}
|
|
||||||
else if (PyTuple_GET_SIZE(args) == 0) {
|
|
||||||
stack = &PyTuple_GET_ITEM(pto->args, 0);
|
|
||||||
nargs = PyTuple_GET_SIZE(pto->args);
|
|
||||||
argappl = NULL;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
stack = NULL;
|
/* bpo-27840, bpo-29318: dictionary of keyword parameters must be
|
||||||
argappl = PySequence_Concat(pto->args, args);
|
copied, because a function using "**kwargs" can modify the
|
||||||
if (argappl == NULL) {
|
dictionary. */
|
||||||
|
kwargs2 = PyDict_Copy(pto->kw);
|
||||||
|
if (kwargs2 == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(PyTuple_Check(argappl));
|
if (kwargs != NULL) {
|
||||||
}
|
if (PyDict_Merge(kwargs2, kwargs, 1) != 0) {
|
||||||
|
Py_DECREF(kwargs2);
|
||||||
if (PyDict_Size(pto->kw) == 0) {
|
|
||||||
kwappl = kw;
|
|
||||||
Py_XINCREF(kwappl);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
kwappl = PyDict_Copy(pto->kw);
|
|
||||||
if (kwappl == NULL) {
|
|
||||||
Py_XDECREF(argappl);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kw != NULL) {
|
|
||||||
if (PyDict_Merge(kwappl, kw, 1) != 0) {
|
|
||||||
Py_XDECREF(argappl);
|
|
||||||
Py_DECREF(kwappl);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack) {
|
|
||||||
ret = _PyObject_FastCallDict(pto->fn, stack, nargs, kwappl);
|
if (pto->use_fastcall) {
|
||||||
|
res = partial_fastcall(pto,
|
||||||
|
&PyTuple_GET_ITEM(args, 0),
|
||||||
|
PyTuple_GET_SIZE(args),
|
||||||
|
kwargs2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = PyObject_Call(pto->fn, argappl, kwappl);
|
res = partial_call_impl(pto, args, kwargs2);
|
||||||
Py_DECREF(argappl);
|
|
||||||
}
|
}
|
||||||
Py_XDECREF(kwappl);
|
Py_XDECREF(kwargs2);
|
||||||
return ret;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -341,12 +387,13 @@ partial_setstate(partialobject *pto, PyObject *state)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(fn);
|
|
||||||
if (dict == Py_None)
|
if (dict == Py_None)
|
||||||
dict = NULL;
|
dict = NULL;
|
||||||
else
|
else
|
||||||
Py_INCREF(dict);
|
Py_INCREF(dict);
|
||||||
|
|
||||||
|
Py_INCREF(fn);
|
||||||
|
pto->use_fastcall = _PyObject_HasFastCall(fn);
|
||||||
Py_SETREF(pto->fn, fn);
|
Py_SETREF(pto->fn, fn);
|
||||||
Py_SETREF(pto->args, fnargs);
|
Py_SETREF(pto->args, fnargs);
|
||||||
Py_SETREF(pto->kw, kw);
|
Py_SETREF(pto->kw, kw);
|
||||||
|
|
15
third_party/python/Objects/call.c
vendored
15
third_party/python/Objects/call.c
vendored
|
@ -30,6 +30,21 @@
|
||||||
#include "third_party/python/Include/warnings.h"
|
#include "third_party/python/Include/warnings.h"
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyObject_HasFastCall(PyObject *callable)
|
||||||
|
{
|
||||||
|
if (PyFunction_Check(callable)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (PyCFunction_Check(callable)) {
|
||||||
|
return !(PyCFunction_GET_FLAGS(callable) & METH_VARARGS);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert (PyCallable_Check(callable));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
null_error(void)
|
null_error(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue