Productionize new APE loader and more

The APE_NO_MODIFY_SELF loader payload has been moved out of the examples
folder and improved so that it works on BSD systems, and permits general
elf program headers. This brings its quality up enough that it should be
acceptable to use by default for many programs, e.g. Python, Lua, SQLite
and Python. It's the responsibility of the user to define an appropriate
TMPDIR if /tmp is considered an adversarial environment. Mac OS shall be
supported by APE_NO_MODIFY_SELF soon.

Fixes and improvements have been made to program_executable_name as it's
now the one true way to get the absolute path of the executing image.

This change fixes a memory leak in linenoise history loading, introduced
by performance optimizations in 51904e2687
This change fixes a longstanding regression with Mach system calls, that
23ae9dfceb back in February which impacted
our sched_yield() implementation, which is why no one noticed until now.

The Blinkenlights PC emulator has been improved. We now fix rendering on
XNU and BSD by not making the assumption that the kernel terminal driver
understands UTF8 since that seems to break its internal modeling of \r\n
which is now being addressed by using \e[𝑦H instead. The paneling is now
more compact in real mode so you won't need to make your font as tiny if
you're only emulating an 8086 program. The CLMUL ISA is now emulated too

This change also makes improvement to time. CLOCK_MONOTONIC now does the
right thing on Windows NT. The nanosecond time module functions added in
Python 3.7 have been backported.

This change doubles the performance of Argon2 password stretching simply
by not using its copy_block and xor_block helper functions, as they were
trivial to inline thus resulting in us needing to iterate over each 1024
byte block four fewer times.

This change makes code size improvements. _PyUnicode_ToNumeric() was 64k
in size and now it's 10k. The CJK codec lookup tables now use lazy delta
zigzag deflate (δzd) encoding which reduces their size from 600k to 200k
plus the code bloat caused by macro abuse in _decimal.c is now addressed
so our fully-loaded statically-linked hermetically-sealed Python virtual
interpreter container is now 9.4 megs in the default build mode and 5.5m
in MODE=tiny which leaves plenty of room for chibicc.

The pydoc web server now accommodates the use case of people who work by
SSH'ing into a different machine w/ python.com -m pydoc -p8080 -h0.0.0.0

Finally Python Capsulae delenda est and won't be supported in the future
This commit is contained in:
Justine Tunney 2021-10-02 08:17:04 -07:00
parent 9cb54218ab
commit 47a53e143b
270 changed files with 214544 additions and 23331 deletions

View file

@ -303,21 +303,18 @@ PyEval_ReleaseThread(PyThreadState *tstate)
* not running in the child process, and clear internal locks which might be
* held by those threads. (This could also be done using pthread_atfork
* mechanism, at least for the pthreads implementation.) */
void
PyEval_ReInitThreads(void)
{
_Py_IDENTIFIER(_after_fork);
PyObject *threading, *result;
PyThreadState *current_tstate = PyThreadState_GET();
if (!gil_created())
return;
recreate_gil();
pending_lock = PyThread_allocate_lock();
take_gil(current_tstate);
main_thread = PyThread_get_thread_ident();
/* Update the threading module with the new state.
*/
threading = PyMapping_GetItemString(current_tstate->interp->modules,
@ -333,7 +330,6 @@ PyEval_ReInitThreads(void)
else
Py_DECREF(result);
Py_DECREF(threading);
/* Destroy all threads except the current one */
_PyThreadState_DeleteExcept(current_tstate);
}
@ -342,7 +338,6 @@ PyEval_ReInitThreads(void)
/* This function is used to signal that async exceptions are waiting to be
raised, therefore it is also useful in non-threaded builds. */
void
_PyEval_SignalAsyncExc(void)
{
@ -352,7 +347,6 @@ _PyEval_SignalAsyncExc(void)
/* Functions save_thread and restore_thread are always defined so
dynamically loaded modules needn't be compiled separately for use
with and without threads: */
PyThreadState *
PyEval_SaveThread(void)
{
@ -387,7 +381,6 @@ PyEval_RestoreThread(PyThreadState *tstate)
PyThreadState_Swap(tstate);
}
/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX
signal handlers or Mac I/O completion routines) can schedule calls
to a function to be called synchronously.
@ -441,7 +434,6 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
{
int i, j, result=0;
PyThread_type_lock lock = pending_lock;
/* try a few times for the lock. Since this mechanism is used
* for signal handling (on the main thread), there is a (slim)
* chance that a signal is delivered on the same thread while we
@ -461,7 +453,6 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
if (i == 100)
return -1;
}
i = pendinglast;
j = (i + 1) % NPENDINGCALLS;
if (j == pendingfirst) {
@ -484,16 +475,13 @@ Py_MakePendingCalls(void)
static int busy = 0;
int i;
int r = 0;
assert(PyGILState_Check());
if (!pending_lock) {
/* initial allocation of the lock */
pending_lock = PyThread_allocate_lock();
if (pending_lock == NULL)
return -1;
}
/* only service pending calls on main thread */
if (main_thread && PyThread_get_thread_ident() != main_thread)
return 0;
@ -504,19 +492,16 @@ Py_MakePendingCalls(void)
/* unsignal before starting to call callbacks, so that any callback
added in-between re-signals */
UNSIGNAL_PENDING_CALLS();
/* Python signal handler doesn't really queue a callback: it only signals
that a signal was received, see _PyEval_SignalReceived(). */
if (PyErr_CheckSignals() < 0) {
goto error;
}
/* perform a bounded number of calls, in case of recursion */
for (i=0; i<NPENDINGCALLS; i++) {
int j;
int (*func)(void *);
void *arg = NULL;
/* pop one item off the queue while holding the lock */
PyThread_acquire_lock(pending_lock, WAIT_LOCK);
j = pendingfirst;
@ -536,10 +521,8 @@ Py_MakePendingCalls(void)
goto error;
}
}
busy = 0;
return r;
error:
busy = 0;
SIGNAL_PENDING_CALLS(); /* We're not done yet */
@ -611,7 +594,6 @@ Py_MakePendingCalls(void)
if (busy)
return 0;
busy = 1;
/* unsignal before starting to call callbacks, so that any callback
added in-between re-signals */
UNSIGNAL_PENDING_CALLS();
@ -620,7 +602,6 @@ Py_MakePendingCalls(void)
if (PyErr_CheckSignals() < 0) {
goto error;
}
for (;;) {
int i;
int (*func)(void *);
@ -637,7 +618,6 @@ Py_MakePendingCalls(void)
}
busy = 0;
return 0;
error:
busy = 0;
SIGNAL_PENDING_CALLS(); /* We're not done yet */
@ -646,7 +626,6 @@ error:
#endif /* WITH_THREAD */
/* The interpreter's recursion limit */
#ifndef Py_DEFAULT_RECURSION_LIMIT
@ -677,7 +656,6 @@ int
_Py_CheckRecursiveCall(const char *where)
{
PyThreadState *tstate = PyThreadState_GET();
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
--tstate->recursion_depth;
@ -3762,7 +3740,6 @@ format_missing(const char *kind, PyCodeObject *co, PyObject *names)
int err;
Py_ssize_t len = PyList_GET_SIZE(names);
PyObject *name_str, *comma, *tail, *tmp;
assert(PyList_CheckExact(names));
assert(len >= 1);
/* Deal with the joys of natural language. */
@ -3827,7 +3804,6 @@ missing_arguments(PyCodeObject *co, Py_ssize_t missing, Py_ssize_t defcount,
int positional = (defcount != -1);
const char *kind = positional ? "positional" : "keyword-only";
PyObject *missing_names;
/* Compute the names of the arguments that are missing. */
missing_names = PyList_New(missing);
if (missing_names == NULL)
@ -3865,7 +3841,6 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount,
Py_ssize_t i;
PyObject *sig, *kwonly_sig;
Py_ssize_t co_argcount = co->co_argcount;
assert((co->co_flags & CO_VARARGS) == 0);
/* Count missing keyword-only args. */
for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {
@ -3915,7 +3890,6 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount,
/* This is gonna seem *real weird*, but if you put some other code between
PyEval_EvalFrame() and _PyEval_EvalFrameDefault() you will need to adjust
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
static PyObject *
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **args, Py_ssize_t argcount,
@ -3934,13 +3908,11 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
Py_ssize_t i, n;
PyObject *kwdict;
if (globals == NULL) {
PyErr_SetString(PyExc_SystemError,
"PyEval_EvalCodeEx: NULL globals");
return NULL;
}
/* Create the frame */
tstate = PyThreadState_GET();
assert(tstate != NULL);
@ -3950,7 +3922,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
}
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + co->co_nlocals;
/* Create a dictionary for keyword parameters (**kwags) */
if (co->co_flags & CO_VARKEYWORDS) {
kwdict = PyDict_New();
@ -3965,7 +3936,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
else {
kwdict = NULL;
}
/* Copy positional arguments into local variables */
if (argcount > co->co_argcount) {
n = co->co_argcount;
@ -3978,7 +3948,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
Py_INCREF(x);
SETLOCAL(i, x);
}
/* Pack other positional arguments into the *args argument */
if (co->co_flags & CO_VARARGS) {
u = PyTuple_New(argcount - n);
@ -3992,7 +3961,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyTuple_SET_ITEM(u, i-n, x);
}
}
/* Handle keyword arguments passed as two strided arrays */
kwcount *= kwstep;
for (i = 0; i < kwcount; i += kwstep) {
@ -4000,14 +3968,12 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject *keyword = kwnames[i];
PyObject *value = kwargs[i];
Py_ssize_t j;
if (keyword == NULL || !PyUnicode_Check(keyword)) {
PyErr_Format(PyExc_TypeError,
"%U() keywords must be strings",
co->co_name);
goto fail;
}
/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
@ -4017,7 +3983,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
goto kw_found;
}
}
/* Slow fallback, just in case */
for (j = 0; j < total_args; j++) {
PyObject *name = co_varnames[j];
@ -4029,19 +3994,16 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
goto fail;
}
}
if (j >= total_args && kwdict == NULL) {
PyErr_Format(PyExc_TypeError,
"%U() got an unexpected keyword argument '%S'",
co->co_name, keyword);
goto fail;
}
if (PyDict_SetItem(kwdict, keyword, value) == -1) {
goto fail;
}
continue;
kw_found:
if (GETLOCAL(j) != NULL) {
PyErr_Format(PyExc_TypeError,
@ -4052,13 +4014,11 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
Py_INCREF(value);
SETLOCAL(j, value);
}
/* Check the number of positional arguments */
if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
too_many_positional(co, argcount, defcount, fastlocals);
goto fail;
}
/* Add missing positional arguments (copy default values from defs) */
if (argcount < co->co_argcount) {
Py_ssize_t m = co->co_argcount - defcount;
@ -4084,7 +4044,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
}
}
}
/* Add missing keyword arguments (copy default values from kwdefs) */
if (co->co_kwonlyargcount > 0) {
Py_ssize_t missing = 0;
@ -4108,7 +4067,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
goto fail;
}
}
/* Allocate and initialize storage for cell vars, and copy free
vars into frame. */
for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
@ -4128,20 +4086,17 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
goto fail;
SETLOCAL(co->co_nlocals + i, c);
}
/* Copy closure variables to free variables */
for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
PyObject *o = PyTuple_GET_ITEM(closure, i);
Py_INCREF(o);
freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
}
/* Handle generator/coroutine/asynchronous generator */
if (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {
PyObject *gen;
PyObject *coro_wrapper = tstate->coroutine_wrapper;
int is_coro = co->co_flags & CO_COROUTINE;
if (is_coro && tstate->in_coroutine_wrapper) {
assert(coro_wrapper != NULL);
PyErr_Format(PyExc_RuntimeError,
@ -4151,13 +4106,10 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
co);
goto fail;
}
/* Don't need to keep the reference to f_back, it will be set
* when the generator is resumed. */
Py_CLEAR(f->f_back);
PCALL(PCALL_GENERATOR);
/* Create a new generator that owns the ready to run frame
* and return that as the value. */
if (is_coro) {
@ -4169,7 +4121,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
}
if (gen == NULL)
return NULL;
if (is_coro && coro_wrapper != NULL) {
PyObject *wrapped;
tstate->in_coroutine_wrapper = 1;
@ -4177,14 +4128,10 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
tstate->in_coroutine_wrapper = 0;
return wrapped;
}
return gen;
}
retval = PyEval_EvalFrameEx(f,0);
fail: /* Jump here from prelude on failure */
/* decref'ing the frame can cause __del__ methods to get invoked,
which can call back into Python. While we're done with the
current Python frame (f), the associated C stack is still in use,
@ -4199,8 +4146,8 @@ fail: /* Jump here from prelude on failure */
PyObject *
PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **args, int argcount, PyObject **kws, int kwcount,
PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
PyObject **args, int argcount, PyObject **kws, int kwcount,
PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
{
return _PyEval_EvalCodeWithName(_co, globals, locals,
args, argcount,
@ -4223,9 +4170,7 @@ special_lookup(PyObject *o, _Py_Identifier *id)
return res;
}
/* These 3 functions deal with the exception state of generators. */
static void
save_exc_state(PyThreadState *tstate, PyFrameObject *f)
{
@ -4283,7 +4228,6 @@ static noinline int
do_raise(PyObject *exc, PyObject *cause)
{
PyObject *type = NULL, *value = NULL;
if (exc == NULL) {
/* Reraise */
PyThreadState *tstate = PyThreadState_GET();
@ -4302,12 +4246,10 @@ do_raise(PyObject *exc, PyObject *cause)
PyErr_Restore(type, value, tb);
return 1;
}
/* We support the following forms of raise:
raise
raise <instance>
raise <type> */
if (PyExceptionClass_Check(exc)) {
type = exc;
value = PyObject_CallObject(exc, NULL);
@ -4334,7 +4276,6 @@ do_raise(PyObject *exc, PyObject *cause)
"exceptions must derive from BaseException");
goto raise_error;
}
if (cause) {
PyObject *fixed_cause;
if (PyExceptionClass_Check(cause)) {
@ -4358,13 +4299,11 @@ do_raise(PyObject *exc, PyObject *cause)
}
PyException_SetCause(value, fixed_cause);
}
PyErr_SetObject(type, value);
/* PyErr_SetObject incref's its arguments */
Py_XDECREF(value);
Py_XDECREF(type);
return 0;
raise_error:
Py_XDECREF(value);
Py_XDECREF(type);
@ -4373,12 +4312,11 @@ raise_error:
}
/* Iterate v argcnt times and store the results on the stack (via decreasing
sp). Return 1 for success, 0 if error.
If argcntafter == -1, do a simple unpack. If it is >= 0, do an unpack
with a variable target.
*/
* sp). Return 1 for success, 0 if error.
*
* If argcntafter == -1, do a simple unpack. If it is >= 0, do an unpack
* with a variable target.
*/
static int
unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
{
@ -4387,13 +4325,10 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
PyObject *it; /* iter(v) */
PyObject *w;
PyObject *l = NULL; /* variable list */
assert(v != NULL);
it = PyObject_GetIter(v);
if (it == NULL)
goto Error;
for (; i < argcnt; i++) {
w = PyIter_Next(it);
if (w == NULL) {
@ -4415,7 +4350,6 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
}
*--sp = w;
}
if (argcntafter == -1) {
/* We better have exhausted the iterator now. */
w = PyIter_Next(it);
@ -4431,13 +4365,11 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
argcnt);
goto Error;
}
l = PySequence_List(it);
if (l == NULL)
goto Error;
*--sp = l;
i++;
ll = PyList_GET_SIZE(l);
if (ll < argcntafter) {
PyErr_Format(PyExc_ValueError,
@ -4445,7 +4377,6 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
argcnt + argcntafter, argcnt + ll);
goto Error;
}
/* Pop the "after-variable" args off the list. */
for (j = argcntafter; j > 0; j--, i++) {
*--sp = PyList_GET_ITEM(l, ll - j);
@ -4454,7 +4385,6 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
Py_SIZE(l) = ll - argcntafter;
Py_DECREF(it);
return 1;
Error:
for (; i > 0; i--, sp++)
Py_DECREF(*sp);
@ -4566,7 +4496,6 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
{
int result = 0;
int line = frame->f_lineno;
/* If the last instruction executed isn't in the current
instruction window, reset the window.
*/
@ -4628,7 +4557,6 @@ void
_PyEval_SetCoroutineWrapper(PyObject *wrapper)
{
PyThreadState *tstate = PyThreadState_GET();
Py_XINCREF(wrapper);
Py_XSETREF(tstate->coroutine_wrapper, wrapper);
}
@ -4644,7 +4572,6 @@ void
_PyEval_SetAsyncGenFirstiter(PyObject *firstiter)
{
PyThreadState *tstate = PyThreadState_GET();
Py_XINCREF(firstiter);
Py_XSETREF(tstate->async_gen_firstiter, firstiter);
}
@ -4660,7 +4587,6 @@ void
_PyEval_SetAsyncGenFinalizer(PyObject *finalizer)
{
PyThreadState *tstate = PyThreadState_GET();
Py_XINCREF(finalizer);
Py_XSETREF(tstate->async_gen_finalizer, finalizer);
}
@ -4704,10 +4630,8 @@ PyEval_GetLocals(void)
PyErr_SetString(PyExc_SystemError, "frame does not exist");
return NULL;
}
if (PyFrame_FastToLocalsWithError(current_frame) < 0)
return NULL;
assert(current_frame->f_locals != NULL);
return current_frame->f_locals;
}
@ -4718,7 +4642,6 @@ PyEval_GetGlobals(void)
PyFrameObject *current_frame = PyEval_GetFrame();
if (current_frame == NULL)
return NULL;
assert(current_frame->f_globals != NULL);
return current_frame->f_globals;
}
@ -4735,7 +4658,6 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
{
PyFrameObject *current_frame = PyEval_GetFrame();
int result = cf->cf_flags != 0;
if (current_frame != NULL) {
const int codeflags = current_frame->f_code->co_flags;
const int compilerflags = codeflags & PyCF_MASK;
@ -4756,7 +4678,6 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
/* External interface to call any callable object.
The arg must be a tuple or NULL. The kw must be a dict or NULL. */
PyObject *
PyEval_CallObjectWithKeywords(PyObject *func, PyObject *args, PyObject *kwargs)
{
@ -4766,19 +4687,16 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *args, PyObject *kwargs)
PyTuple_New() fails, and so the original exception is lost. */
assert(!PyErr_Occurred());
#endif
if (args != NULL && !PyTuple_Check(args)) {
PyErr_SetString(PyExc_TypeError,
"argument list must be a tuple");
return NULL;
}
if (kwargs != NULL && !PyDict_Check(kwargs)) {
PyErr_SetString(PyExc_TypeError,
"keyword list must be a dictionary");
return NULL;
}
if (args == NULL) {
return _PyObject_FastCallDict(func, NULL, 0, kwargs);
}
@ -4853,15 +4771,12 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
Py_ssize_t nargs = oparg - nkwargs;
PyObject **stack;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
*/
if (PyCFunction_Check(func)) {
PyThreadState *tstate = PyThreadState_GET();
PCALL(PCALL_CFUNCTION);
stack = (*pp_stack) - nargs - nkwargs;
C_TRACE(x, _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames));
}
@ -4880,21 +4795,16 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
else {
Py_INCREF(func);
}
stack = (*pp_stack) - nargs - nkwargs;
if (PyFunction_Check(func)) {
x = fast_function(func, stack, nargs, kwnames);
}
else {
x = _PyObject_FastCallKeywords(func, stack, nargs, kwnames);
}
Py_DECREF(func);
}
assert((x != NULL) ^ (PyErr_Occurred() != NULL));
/* Clear the stack of the function object. Also removes
the arguments in case they weren't consumed already
(fast_function() and err_args() leave them on the stack).
@ -4904,7 +4814,6 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
Py_DECREF(w);
PCALL(PCALL_POP);
}
return x;
}
@ -4916,7 +4825,6 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
PyEval_EvalCodeEx(), which vastly reduces the checks that must be
done before evaluating the frame.
*/
static PyObject*
_PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
PyObject *globals)
@ -4926,7 +4834,6 @@ _PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
PyObject **fastlocals;
Py_ssize_t i;
PyObject *result;
PCALL(PCALL_FASTER_FUNCTION);
assert(globals != NULL);
/* XXX Perhaps we should create a specialized
@ -4938,19 +4845,15 @@ _PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
if (f == NULL) {
return NULL;
}
fastlocals = f->f_localsplus;
for (i = 0; i < nargs; i++) {
Py_INCREF(*args);
fastlocals[i] = *args++;
}
result = PyEval_EvalFrameEx(f,0);
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
return result;
}
@ -4965,17 +4868,14 @@ fast_function(PyObject *func, PyObject **stack,
PyObject **d;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
Py_ssize_t nd;
assert(PyFunction_Check(func));
assert(nargs >= 0);
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
assert((nargs == 0 && nkwargs == 0) || stack != NULL);
/* kwnames must only contains str strings, no subclass, and all keys must
be unique */
PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION);
if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
{
@ -4990,12 +4890,10 @@ fast_function(PyObject *func, PyObject **stack,
return _PyFunction_FastCall(co, stack, Py_SIZE(argdefs), globals);
}
}
kwdefs = PyFunction_GET_KW_DEFAULTS(func);
closure = PyFunction_GET_CLOSURE(func);
name = ((PyFunctionObject *)func) -> func_name;
qualname = ((PyFunctionObject *)func) -> func_qualname;
if (argdefs != NULL) {
d = &PyTuple_GET_ITEM(argdefs, 0);
nd = Py_SIZE(argdefs);
@ -5032,15 +4930,12 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
PyObject **d;
Py_ssize_t nd, nk;
PyObject *result;
assert(func != NULL);
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION);
if (co->co_kwonlyargcount == 0 &&
(kwargs == NULL || PyDict_Size(kwargs) == 0) &&
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
@ -5057,16 +4952,13 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
return _PyFunction_FastCall(co, args, Py_SIZE(argdefs), globals);
}
}
if (kwargs != NULL) {
Py_ssize_t pos, i;
nk = PyDict_Size(kwargs);
kwtuple = PyTuple_New(2 * nk);
if (kwtuple == NULL) {
return NULL;
}
k = &PyTuple_GET_ITEM(kwtuple, 0);
pos = i = 0;
while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) {
@ -5081,12 +4973,10 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
k = NULL;
nk = 0;
}
kwdefs = PyFunction_GET_KW_DEFAULTS(func);
closure = PyFunction_GET_CLOSURE(func);
name = ((PyFunctionObject *)func) -> func_name;
qualname = ((PyFunctionObject *)func) -> func_qualname;
if (argdefs != NULL) {
d = &PyTuple_GET_ITEM(argdefs, 0);
nd = Py_SIZE(argdefs);
@ -5095,7 +4985,6 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
d = NULL;
nd = 0;
}
result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
args, nargs,
k, k != NULL ? k + 1 : NULL, nk, 2,
@ -5124,7 +5013,6 @@ do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
else
PCALL(PCALL_OTHER);
#endif
if (PyCFunction_Check(func)) {
PyObject *result;
PyThreadState *tstate = PyThreadState_GET();
@ -5244,13 +5132,11 @@ import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *leve
_Py_IDENTIFIER(__import__);
PyObject *import_func, *res;
PyObject* stack[5];
import_func = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
if (import_func == NULL) {
PyErr_SetString(PyExc_ImportError, "__import__ not found");
return NULL;
}
/* Fast path for not overloaded __import__. */
if (import_func == PyThreadState_GET()->interp->import_func) {
int ilevel = _PyLong_AsInt(level);
@ -5265,9 +5151,7 @@ import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *leve
ilevel);
return res;
}
Py_INCREF(import_func);
stack[0] = name;
stack[1] = f->f_globals;
stack[2] = f->f_locals == NULL ? Py_None : f->f_locals;
@ -5412,14 +5296,11 @@ static void
format_exc_check_arg(PyObject *exc, const char *format_str, PyObject *obj)
{
const char *obj_str;
if (!obj)
return;
obj_str = PyUnicode_AsUTF8(obj);
if (!obj_str)
return;
PyErr_Format(exc, format_str, obj_str);
}
@ -5564,7 +5445,6 @@ _PyEval_RequestCodeExtraIndex(freefunc free)
{
__PyCodeExtraState *state = __PyCodeExtraState_Get();
Py_ssize_t new_index;
if (state->co_extra_user_count == MAX_CO_EXTRA_USERS - 1) {
return -1;
}
@ -5579,11 +5459,9 @@ dtrace_function_entry(PyFrameObject *f)
char* filename;
char* funcname;
int lineno;
filename = PyUnicode_AsUTF8(f->f_code->co_filename);
funcname = PyUnicode_AsUTF8(f->f_code->co_name);
lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
}
@ -5593,11 +5471,9 @@ dtrace_function_return(PyFrameObject *f)
char* filename;
char* funcname;
int lineno;
filename = PyUnicode_AsUTF8(f->f_code->co_filename);
funcname = PyUnicode_AsUTF8(f->f_code->co_name);
lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
PyDTrace_FUNCTION_RETURN(filename, funcname, lineno);
}
@ -5608,7 +5484,6 @@ maybe_dtrace_line(PyFrameObject *frame,
{
int line = frame->f_lineno;
char *co_filename, *co_name;
/* If the last instruction executed isn't in the current
instruction window, reset the window.
*/