From 56129743787f474bff8ea9464297f4c0368ed026 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Wed, 3 Oct 2018 21:31:15 -0400 Subject: [PATCH 1/2] bpo-2506: Experiment with adding a "-X noopt" flag --- Include/coreconfig.h | 1 + Modules/_testcapimodule.c | 2 ++ Programs/_testembed.c | 1 + Python/compile.c | 31 +++++++++++++++++++++++++------ Python/coreconfig.c | 5 +++++ Python/sysmodule.c | 2 ++ 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Include/coreconfig.h b/Include/coreconfig.h index ef043ab02df6d4..1d3573aa63c0de 100644 --- a/Include/coreconfig.h +++ b/Include/coreconfig.h @@ -49,6 +49,7 @@ typedef struct { const char *allocator; /* Memory allocator: PYTHONMALLOC */ int dev_mode; /* PYTHONDEVMODE, -X dev */ + int noopt_mode; /* -X noopt */ /* Enable faulthandler? Set to 1 by -X faulthandler and PYTHONFAULTHANDLER. -1 means unset. */ diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index add642f223afdc..ee1afeae8573ff 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4687,6 +4687,8 @@ get_coreconfig(PyObject *self, PyObject *Py_UNUSED(args)) FROM_STRING(config->allocator)); SET_ITEM("dev_mode", PyLong_FromLong(config->dev_mode)); + SET_ITEM("noopt_mode", + PyLong_FromLong(config->noopt_mode)); SET_ITEM("faulthandler", PyLong_FromLong(config->faulthandler)); SET_ITEM("tracemalloc", diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 99772eacbdc42a..616e03b9e32bab 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -320,6 +320,7 @@ dump_config(void) printf("allocator = %s\n", config->allocator); printf("dev_mode = %i\n", config->dev_mode); + printf("noopt_mode = %i\n", config->noopt_mode); printf("faulthandler = %i\n", config->faulthandler); printf("tracemalloc = %i\n", config->tracemalloc); printf("import_time = %i\n", config->import_time); diff --git a/Python/compile.c b/Python/compile.c index 096b762f36bb0d..66ace8c1a53f68 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -27,6 +27,7 @@ #include "node.h" #include "ast.h" #include "code.h" +#include "internal/pystate.h" #include "symtable.h" #include "opcode.h" #include "wordcode_helpers.h" @@ -158,6 +159,7 @@ struct compiler { PyCompilerFlags *c_flags; int c_optimize; /* optimization level */ + int c_noopt; int c_interactive; /* true if in interactive mode */ int c_nestlevel; @@ -300,6 +302,7 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, PyCodeObject *co = NULL; PyCompilerFlags local_flags; int merged; + const _PyCoreConfig *conf = &_PyInterpreterState_GET_UNSAFE()->core_config; if (!__doc__) { __doc__ = PyUnicode_InternFromString("__doc__"); @@ -330,8 +333,14 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize; c.c_nestlevel = 0; - if (!_PyAST_Optimize(mod, arena, c.c_optimize)) { - goto finally; + if (conf->noopt_mode) { + c.c_noopt = 1; + } + else { + c.c_noopt = 0; + if (!_PyAST_Optimize(mod, arena, c.c_optimize)) { + goto finally; + } } c.c_st = PySymtable_BuildObject(mod, filename, c.c_future); @@ -2478,7 +2487,11 @@ static int compiler_while(struct compiler *c, stmt_ty s) { basicblock *loop, *orelse, *end, *anchor = NULL; - int constant = expr_constant(s->v.While.test); + + int constant = -1; + if (!c->c_noopt) { + constant = expr_constant(s->v.While.test); + } if (constant == 0) { if (s->v.While.orelse) @@ -5387,9 +5400,15 @@ makecode(struct compiler *c, struct assembler *a) if (flags < 0) goto error; - bytecode = PyCode_Optimize(a->a_bytecode, consts, names, a->a_lnotab); - if (!bytecode) - goto error; + if (!c->c_noopt) { + bytecode = PyCode_Optimize(a->a_bytecode, consts, names, a->a_lnotab); + if (!bytecode) + goto error; + } + else { + bytecode = a->a_bytecode; + Py_INCREF(bytecode); + } tmp = PyList_AsTuple(consts); /* PyCode_New requires a tuple */ if (!tmp) diff --git a/Python/coreconfig.c b/Python/coreconfig.c index fae32e533aa9cd..f91216af1424e6 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -295,6 +295,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_ATTR(_install_importlib); COPY_ATTR(allocator); COPY_ATTR(dev_mode); + COPY_ATTR(noopt_mode); COPY_ATTR(faulthandler); COPY_ATTR(tracemalloc); COPY_ATTR(import_time); @@ -945,6 +946,10 @@ config_read_complex_options(_PyCoreConfig *config) { config->dev_mode = 1; } + if (config_get_xoption(config, L"noopt")) + { + config->noopt_mode = 1; + } _PyInitError err; if (config->tracemalloc < 0) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 58ea60595cd3c0..1d3cc9fb944d40 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2060,6 +2060,7 @@ static PyStructSequence_Field flags_fields[] = { {"hash_randomization", "-R"}, {"isolated", "-I"}, {"dev_mode", "-X dev"}, + {"noopt_mode", "-X noopt"}, {"utf8_mode", "-X utf8"}, {0} }; @@ -2101,6 +2102,7 @@ make_flags(void) SetFlag(config->use_hash_seed == 0 || config->hash_seed != 0); SetFlag(config->isolated); PyStructSequence_SET_ITEM(seq, pos++, PyBool_FromLong(config->dev_mode)); + PyStructSequence_SET_ITEM(seq, pos++, PyBool_FromLong(config->noopt_mode)); SetFlag(config->utf8_mode); #undef SetFlag From 10d3814187affa000f3cc82740acd0da0bf5afc6 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Wed, 3 Oct 2018 22:55:59 -0400 Subject: [PATCH 2/2] Disable both "if " and "while " optimizations --- Python/compile.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 66ace8c1a53f68..ba45c266135f98 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -188,7 +188,7 @@ static int compiler_visit_slice(struct compiler *, slice_ty, expr_context_ty); static int inplace_binop(struct compiler *, operator_ty); -static int expr_constant(expr_ty); +static int expr_constant(struct compiler *, expr_ty); static int compiler_with(struct compiler *, stmt_ty, int); static int compiler_async_with(struct compiler *, stmt_ty, int); @@ -2374,7 +2374,7 @@ compiler_if(struct compiler *c, stmt_ty s) if (end == NULL) return 0; - constant = expr_constant(s->v.If.test); + constant = expr_constant(c, s->v.If.test); /* constant = 0: "if 0" * constant = 1: "if 1", "if 2", ... * constant = -1: rest */ @@ -2488,10 +2488,7 @@ compiler_while(struct compiler *c, stmt_ty s) { basicblock *loop, *orelse, *end, *anchor = NULL; - int constant = -1; - if (!c->c_noopt) { - constant = expr_constant(s->v.While.test); - } + int constant = expr_constant(c, s->v.While.test); if (constant == 0) { if (s->v.While.orelse) @@ -4218,8 +4215,11 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) */ static int -expr_constant(expr_ty e) +expr_constant(struct compiler *c, expr_ty e) { + if (c->c_noopt) { + return -1; + } if (e->kind == Constant_kind) { return PyObject_IsTrue(e->v.Constant.value); }