Add speedups from pyston (#264)

This should make Python go 30% faster. It does that by trading
away some debuggability, like _tracemalloc. It can be re-enabled
using `make MODE=dbg`.
This commit is contained in:
Gautham 2021-09-04 14:51:37 +05:30 committed by GitHub
parent 31dd714081
commit 27f7ffd4fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 175 additions and 12 deletions

View file

@ -36,8 +36,12 @@ PyObject *_PyObject_FastCallKeywords(PyObject *func, PyObject **args,
PyObject *_PyObject_Call_Prepend(PyObject *func, PyObject *obj, PyObject *args,
PyObject *kwargs);
#ifdef USE_CHECKFUNCRESULT
PyObject *_Py_CheckFunctionResult(PyObject *func, PyObject *result,
const char *where);
#else
#define _Py_CheckFunctionResult(func, result, where) (result)
#endif
#endif /* Py_LIMITED_API */
PyObject *PyObject_CallObject(PyObject *callable_object, PyObject *args);

9
third_party/python/Include/cosmo.h vendored Normal file
View file

@ -0,0 +1,9 @@
#ifndef Py_COSMO_H
#define Py_COSMO_H
#include "third_party/python/Include/object.h"
COSMOPOLITAN_C_START_
PyMODINIT_FUNC PyInit_cosmo(void);
COSMOPOLITAN_C_END_
#endif /* !Py_IMPORT_H */

View file

@ -318,8 +318,11 @@ void PyErr_BadInternalCall(void);
void _PyErr_BadInternalCall(const char *filename, int lineno);
/* Mask the old API with a call to the new API for code compiled under
Python 2.0: */
#ifdef USE_BADINTERNALCALL
#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
#else
#define PyErr_BadInternalCall()
#endif
/* Function to create a new exception */
PyObject * PyErr_NewException(
const char *name, PyObject *base, PyObject *dict);

View file

@ -63,6 +63,11 @@ int _PyTraceMalloc_Untrack(
PyObject* _PyTraceMalloc_GetTraceback(
_PyTraceMalloc_domain_t domain,
uintptr_t ptr);
#ifndef MODE_DBG
#define _PyTraceMalloc_Track(domain, ptr, size) (-2)
#define _PyTraceMalloc_Untrack(domain, ptr) (-2)
#define _PyTraceMalloc_GetTraceback(domain, ptr) (&_Py_NoneStruct)
#endif
int _PyMem_IsFreed(void *ptr, size_t size);
#endif /* !defined(Py_LIMITED_API) */

View file

@ -593,7 +593,7 @@ build_time_vars = {'ABIFLAGS': 'm',
'MODNAMES': '_decimal posix errno pwd _sre '
'_codecs _functools _operator _collections itertools atexit '
'_signal _stat time _locale _io zipimport faulthandler '
'_tracemalloc _symtable array cmath math _struct _weakref '
'_symtable array cmath math _struct _weakref '
'_testcapi _random _elementtree _pickle _datetime _bisect _heapq '
'unicodedata fcntl grp select mmap _csv _socket resource '
'_posixsubprocess _md5 _sha1 _sha256 _sha512 _sha3 syslog '
@ -614,7 +614,7 @@ build_time_vars = {'ABIFLAGS': 'm',
'Modules/_iomodule.o Modules/iobase.o Modules/fileio.o '
'Modules/bytesio.o Modules/bufferedio.o Modules/textio.o '
'Modules/stringio.o Modules/zipimport.o Modules/faulthandler.o '
'Modules/_tracemalloc.o Modules/hashtable.o '
'Modules/hashtable.o '
'Modules/symtablemodule.o Modules/arraymodule.o '
'Modules/cmathmodule.o Modules/mathmodule.o Modules/_math.o '
'Modules/_struct.o Modules/_weakref.o Modules/_testcapimodule.o '

View file

@ -263,8 +263,8 @@ def _args_from_interpreter_flags():
# -X options
xoptions = getattr(sys, '_xoptions', {})
for opt in ('faulthandler', 'tracemalloc',
'showalloccount', 'showrefcount', 'utf8'):
for opt in ('faulthandler', 'showalloccount',
'showrefcount', 'utf8'):
if opt in xoptions:
value = xoptions[opt]
if value is True:

View file

@ -102,6 +102,7 @@ consts: ('None',)
"""
import _cosmo
import inspect
import sys
try:
@ -298,6 +299,7 @@ if check_impl_detail(cpython=True) and ctypes is not None:
# away, so we eval a lambda.
return eval('lambda:42')
@unittest.skipUnless(_cosmo.MODE == "dbg", "requires APE debug build")
def test_get_non_code(self):
f = self.get_func()
@ -306,6 +308,7 @@ if check_impl_detail(cpython=True) and ctypes is not None:
self.assertRaises(SystemError, GetExtra, 42, FREE_INDEX,
ctypes.c_voidp(100))
@unittest.skipUnless(_cosmo.MODE == "dbg", "requires APE debug build")
def test_bad_index(self):
f = self.get_func()
self.assertRaises(SystemError, SetExtra, f.__code__,

View file

@ -1,3 +1,4 @@
import _cosmo
import collections
import collections.abc
import gc
@ -1221,7 +1222,9 @@ class CAPITest(unittest.TestCase):
self.assertEqual(dict_getitem_knownhash(d, 'z', hash('z')), 3)
# not a dict
self.assertRaises(SystemError, dict_getitem_knownhash, [], 1, hash(1))
# find the APE compilation mode, run this test in dbg only #
if _cosmo.MODE == "dbg":
self.assertRaises(SystemError, dict_getitem_knownhash, [], 1, hash(1))
# key does not exist
self.assertRaises(KeyError, dict_getitem_knownhash, {}, 1, hash(1))

View file

@ -1794,7 +1794,7 @@ _PyTraceMalloc_Fini(void)
}
int
_PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
(_PyTraceMalloc_Track)(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
size_t size)
{
int res;
@ -1823,7 +1823,7 @@ _PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
int
_PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
(_PyTraceMalloc_Untrack)(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
{
if (!tracemalloc_config.tracing) {
/* tracemalloc is not tracing: do nothing */
@ -1839,7 +1839,7 @@ _PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
PyObject*
_PyTraceMalloc_GetTraceback(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
(_PyTraceMalloc_GetTraceback)(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
{
traceback_t *traceback;

View file

@ -27,6 +27,7 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#include "third_party/python/Include/pyport.h"
#include "third_party/python/Include/pyport.h"
#include "third_party/python/Include/Python.h"
#include "third_party/python/Include/cosmo.h"
PyObject* PyInit__decimal(void);
PyObject* PyInit_audioop(void);
@ -47,7 +48,9 @@ PyObject* PyInit__locale(void);
PyObject* PyInit__io(void);
PyObject* PyInit_zipimport(void);
PyObject* PyInit_faulthandler(void);
#ifdef MODE_DBG
PyObject* PyInit__tracemalloc(void);
#endif
PyObject* PyInit__symtable(void);
PyObject* PyInit_array(void);
PyObject* PyInit_cmath(void);
@ -99,6 +102,7 @@ PyObject *PyInit__sqlite3(void);
PyObject* PyMarshal_Init(void);
PyObject* PyInit_imp(void);
PyObject* PyInit_cosmo(void);
PyObject* PyInit_gc(void);
PyObject* PyInit__ast(void);
PyObject* _PyWarnings_Init(void);
@ -123,7 +127,9 @@ struct _inittab _PyImport_Inittab[] = {
{"_locale", PyInit__locale},
{"_io", PyInit__io},
{"faulthandler", PyInit_faulthandler},
#ifdef USE_TRACEMALLOC
{"_tracemalloc", PyInit__tracemalloc},
#endif
{"_symtable", PyInit__symtable},
{"array", PyInit_array},
{"cmath", PyInit_cmath},
@ -184,6 +190,9 @@ struct _inittab _PyImport_Inittab[] = {
/* This lives in import.c */
{"_imp", PyInit_imp},
/* This lives in cosmomodule.c */
{"_cosmo", PyInit_cosmo},
/* This lives in Python/Python-ast.c */
{"_ast", PyInit__ast},

View file

@ -2210,6 +2210,7 @@ PyObject_CallObject(PyObject *o, PyObject *a)
return PyEval_CallObjectWithKeywords(o, a, NULL);
}
#ifdef MODE_DBG
PyObject*
_Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
{
@ -2257,6 +2258,7 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
}
return result;
}
#endif
PyObject *
PyObject_Call(PyObject *func, PyObject *args, PyObject *kwargs)

View file

@ -16,9 +16,10 @@
#include "third_party/python/Include/pymem.h"
/* clang-format off */
#ifdef MODE_DBG
/* Defined in tracemalloc.c */
extern void _PyMem_DumpTraceback(int fd, const void *ptr);
#endif
/* Python's malloc wrappers (see pymem.h) */
@ -2196,7 +2197,9 @@ _PyObject_DebugDumpAddress(const void *p)
fputc('\n', stderr);
fflush(stderr);
#ifdef USE_TRACEMALLOC
_PyMem_DumpTraceback(fileno(stderr), p);
#endif
}

102
third_party/python/Python/cosmomodule.c vendored Normal file
View file

@ -0,0 +1,102 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "third_party/python/Include/Python-ast.h"
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/boolobject.h"
#include "third_party/python/Include/ceval.h"
#include "third_party/python/Include/code.h"
#include "third_party/python/Include/cosmo.h"
#include "third_party/python/Include/dictobject.h"
#include "third_party/python/Include/errcode.h"
#include "third_party/python/Include/eval.h"
#include "third_party/python/Include/fileutils.h"
#include "third_party/python/Include/frameobject.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/listobject.h"
#include "third_party/python/Include/longobject.h"
#include "third_party/python/Include/marshal.h"
#include "third_party/python/Include/modsupport.h"
#include "third_party/python/Include/objimpl.h"
#include "third_party/python/Include/osdefs.h"
#include "third_party/python/Include/pgenheaders.h"
#include "third_party/python/Include/pydebug.h"
#include "third_party/python/Include/pyerrors.h"
#include "third_party/python/Include/pylifecycle.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pythonrun.h"
#include "third_party/python/Include/sysmodule.h"
#include "third_party/python/Include/traceback.h"
#include "third_party/python/Include/tupleobject.h"
#include "third_party/python/Include/warnings.h"
#include "third_party/python/Include/weakrefobject.h"
#include "third_party/python/Python/importdl.h"
/* clang-format off */
static int cosmo_constants(PyObject *m)
{
if(PyModule_AddStringMacro(m, MODE)) return -1;
return 0;
}
PyDoc_STRVAR(doc_cosmo,
"additional information and special functions provided by Cosmopolitan Libc.");
static PyMethodDef cosmo_methods[] = {
{NULL, NULL} /* sentinel */
};
static struct PyModuleDef cosmomodule = {
PyModuleDef_HEAD_INIT,
"_cosmo",
doc_cosmo,
-1,
cosmo_methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit_cosmo(void)
{
PyObject *m, *d;
m = PyModule_Create(&cosmomodule);
if (m == NULL)
goto failure;
if(cosmo_constants(m))
goto failure;
return m;
failure:
Py_XDECREF(m);
return NULL;
}

View file

@ -21,6 +21,7 @@
#include "third_party/python/Include/ast.h"
#include "third_party/python/Include/boolobject.h"
#include "third_party/python/Include/code.h"
#include "third_party/python/Include/cosmo.h"
#include "third_party/python/Include/codecs.h"
#include "third_party/python/Include/dictobject.h"
#include "third_party/python/Include/errcode.h"
@ -75,9 +76,10 @@ extern void PyLong_Fini(void);
extern int _PyFaulthandler_Init(void);
extern void _PyFaulthandler_Fini(void);
extern void _PyHash_Fini(void);
#ifdef MODE_DBG
extern int _PyTraceMalloc_Init(void);
extern int _PyTraceMalloc_Fini(void);
#endif
#ifdef WITH_THREAD
extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
extern void _PyGILState_Fini(void);
@ -257,6 +259,7 @@ import_init(PyInterpreterState *interp, PyObject *sysmod)
{
PyObject *importlib;
PyObject *impmod;
PyObject *cosmomod;
PyObject *sys_modules;
PyObject *value;
@ -296,6 +299,18 @@ import_init(PyInterpreterState *interp, PyObject *sysmod)
Py_FatalError("Py_Initialize: can't save _imp to sys.modules");
}
/* Import the _cosmo module */
cosmomod = PyInit_cosmo();
if (impmod == NULL) {
Py_FatalError("Py_Initialize: can't import _cosmo");
}
else if (Py_VerboseFlag) {
PySys_FormatStderr("import _cosmo # for bonus Cosmopolitan Libc features\n");
}
if (PyDict_SetItemString(sys_modules, "_cosmo", cosmomod) < 0) {
Py_FatalError("Py_Initialize: can't save _cosmo to sys.modules");
}
/* Install importlib as the implementation of import */
value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
if (value == NULL) {
@ -462,8 +477,10 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
if (install_sigs)
initsigs(); /* Signal handling stuff, including initintr() */
#ifdef MODE_DBG
if (_PyTraceMalloc_Init() < 0)
Py_FatalError("Py_Initialize: can't initialize tracemalloc");
#endif
initmain(interp); /* Module __main__ */
if (initstdio() < 0) {
@ -652,10 +669,11 @@ Py_FinalizeEx(void)
_PyGC_CollectIfEnabled();
#endif
#ifdef MODE_DBG
/* Disable tracemalloc after all Python objects have been destroyed,
so it is possible to use tracemalloc in objects destructor. */
_PyTraceMalloc_Fini();
#endif
/* Destroy the database used by _PyImport_{Fixup,Find}Extension */
_PyImport_Fini();

View file

@ -71,6 +71,7 @@ THIRD_PARTY_PYTHON_HDRS = \
third_party/python/Include/codecs.h \
third_party/python/Include/compile.h \
third_party/python/Include/complexobject.h \
third_party/python/Include/cosmo.h \
third_party/python/Include/datetime.h \
third_party/python/Include/descrobject.h \
third_party/python/Include/dictobject.h \
@ -370,6 +371,7 @@ THIRD_PARTY_PYTHON_STAGE1_A_SRCS = \
third_party/python/Python/ceval.c \
third_party/python/Python/codecs.c \
third_party/python/Python/compile.c \
third_party/python/Python/cosmomodule.c \
third_party/python/Python/dtoa.c \
third_party/python/Python/dynload_shlib.c \
third_party/python/Python/errors.c \