mirror of https://github.com/python/cpython
gh-119744: move a few functions from compile.c to flowgraph.c (#119745)
This commit is contained in:
parent
9732ed5ca9
commit
13a5fdc72f
|
@ -101,12 +101,6 @@ PyAPI_FUNC(PyObject*) _PyCompile_CodeGen(
|
||||||
int optimize,
|
int optimize,
|
||||||
int compile_mode);
|
int compile_mode);
|
||||||
|
|
||||||
// Export for '_testinternalcapi' shared extension
|
|
||||||
PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg(
|
|
||||||
PyObject *instructions,
|
|
||||||
PyObject *consts,
|
|
||||||
int nlocals);
|
|
||||||
|
|
||||||
// Export for '_testinternalcapi' shared extension
|
// Export for '_testinternalcapi' shared extension
|
||||||
PyAPI_FUNC(PyCodeObject*)
|
PyAPI_FUNC(PyCodeObject*)
|
||||||
_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
|
_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
|
||||||
|
|
|
@ -24,6 +24,7 @@ int _PyCfgBuilder_CheckSize(struct _PyCfgBuilder* g);
|
||||||
int _PyCfg_OptimizeCodeUnit(struct _PyCfgBuilder *g, PyObject *consts, PyObject *const_cache,
|
int _PyCfg_OptimizeCodeUnit(struct _PyCfgBuilder *g, PyObject *consts, PyObject *const_cache,
|
||||||
int nlocals, int nparams, int firstlineno);
|
int nlocals, int nparams, int firstlineno);
|
||||||
|
|
||||||
|
struct _PyCfgBuilder* _PyCfg_FromInstructionSequence(_PyInstructionSequence *seq);
|
||||||
int _PyCfg_ToInstructionSequence(struct _PyCfgBuilder *g, _PyInstructionSequence *seq);
|
int _PyCfg_ToInstructionSequence(struct _PyCfgBuilder *g, _PyInstructionSequence *seq);
|
||||||
int _PyCfg_OptimizedCfgToInstructionSequence(struct _PyCfgBuilder *g, _PyCompile_CodeUnitMetadata *umd,
|
int _PyCfg_OptimizedCfgToInstructionSequence(struct _PyCfgBuilder *g, _PyCompile_CodeUnitMetadata *umd,
|
||||||
int code_flags, int *stackdepth, int *nlocalsplus,
|
int code_flags, int *stackdepth, int *nlocalsplus,
|
||||||
|
@ -34,6 +35,12 @@ _PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *u, PyObject *const_cache
|
||||||
PyObject *consts, int maxdepth, _PyInstructionSequence *instrs,
|
PyObject *consts, int maxdepth, _PyInstructionSequence *instrs,
|
||||||
int nlocalsplus, int code_flags, PyObject *filename);
|
int nlocalsplus, int code_flags, PyObject *filename);
|
||||||
|
|
||||||
|
// Export for '_testinternalcapi' shared extension
|
||||||
|
PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg(
|
||||||
|
PyObject *instructions,
|
||||||
|
PyObject *consts,
|
||||||
|
int nlocals);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "pycore_context.h" // _PyContext_NewHamtForTests()
|
#include "pycore_context.h" // _PyContext_NewHamtForTests()
|
||||||
#include "pycore_dict.h" // _PyManagedDictPointer_GetValues()
|
#include "pycore_dict.h" // _PyManagedDictPointer_GetValues()
|
||||||
#include "pycore_fileutils.h" // _Py_normpath()
|
#include "pycore_fileutils.h" // _Py_normpath()
|
||||||
|
#include "pycore_flowgraph.h" // _PyCompile_OptimizeCfg()
|
||||||
#include "pycore_frame.h" // _PyInterpreterFrame
|
#include "pycore_frame.h" // _PyInterpreterFrame
|
||||||
#include "pycore_gc.h" // PyGC_Head
|
#include "pycore_gc.h" // PyGC_Head
|
||||||
#include "pycore_hashtable.h" // _Py_hashtable_new()
|
#include "pycore_hashtable.h" // _Py_hashtable_new()
|
||||||
|
|
155
Python/compile.c
155
Python/compile.c
|
@ -197,47 +197,6 @@ _PyCompile_EnsureArrayLargeEnough(int idx, void **array, int *alloc,
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cfg_builder*
|
|
||||||
instr_sequence_to_cfg(instr_sequence *seq) {
|
|
||||||
if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
cfg_builder *g = _PyCfgBuilder_New();
|
|
||||||
if (g == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < seq->s_used; i++) {
|
|
||||||
seq->s_instrs[i].i_target = 0;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < seq->s_used; i++) {
|
|
||||||
instruction *instr = &seq->s_instrs[i];
|
|
||||||
if (HAS_TARGET(instr->i_opcode)) {
|
|
||||||
assert(instr->i_oparg >= 0 && instr->i_oparg < seq->s_used);
|
|
||||||
seq->s_instrs[instr->i_oparg].i_target = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < seq->s_used; i++) {
|
|
||||||
instruction *instr = &seq->s_instrs[i];
|
|
||||||
if (instr->i_target) {
|
|
||||||
jump_target_label lbl_ = {i};
|
|
||||||
if (_PyCfgBuilder_UseLabel(g, lbl_) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int opcode = instr->i_opcode;
|
|
||||||
int oparg = instr->i_oparg;
|
|
||||||
if (_PyCfgBuilder_Addop(g, opcode, oparg, instr->i_loc) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_PyCfgBuilder_CheckSize(g) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
return g;
|
|
||||||
error:
|
|
||||||
_PyCfgBuilder_Free(g);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The following items change on entry and exit of code blocks.
|
/* The following items change on entry and exit of code blocks.
|
||||||
They must be saved and restored when returning to a block.
|
They must be saved and restored when returning to a block.
|
||||||
|
@ -691,48 +650,6 @@ compiler_set_qualname(struct compiler *c)
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the stack effect of opcode with argument oparg.
|
|
||||||
|
|
||||||
Some opcodes have different stack effect when jump to the target and
|
|
||||||
when not jump. The 'jump' parameter specifies the case:
|
|
||||||
|
|
||||||
* 0 -- when not jump
|
|
||||||
* 1 -- when jump
|
|
||||||
* -1 -- maximal
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
stack_effect(int opcode, int oparg, int jump)
|
|
||||||
{
|
|
||||||
if (opcode < 0) {
|
|
||||||
return PY_INVALID_STACK_EFFECT;
|
|
||||||
}
|
|
||||||
if ((opcode <= MAX_REAL_OPCODE) && (_PyOpcode_Deopt[opcode] != opcode)) {
|
|
||||||
// Specialized instructions are not supported.
|
|
||||||
return PY_INVALID_STACK_EFFECT;
|
|
||||||
}
|
|
||||||
int popped = _PyOpcode_num_popped(opcode, oparg);
|
|
||||||
int pushed = _PyOpcode_num_pushed(opcode, oparg);
|
|
||||||
if (popped < 0 || pushed < 0) {
|
|
||||||
return PY_INVALID_STACK_EFFECT;
|
|
||||||
}
|
|
||||||
if (IS_BLOCK_PUSH_OPCODE(opcode) && !jump) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return pushed - popped;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump)
|
|
||||||
{
|
|
||||||
return stack_effect(opcode, oparg, jump);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PyCompile_OpcodeStackEffect(int opcode, int oparg)
|
|
||||||
{
|
|
||||||
return stack_effect(opcode, oparg, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyCompile_OpcodeIsValid(int opcode)
|
_PyCompile_OpcodeIsValid(int opcode)
|
||||||
{
|
{
|
||||||
|
@ -7592,7 +7509,7 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
|
||||||
if (consts == NULL) {
|
if (consts == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
g = instr_sequence_to_cfg(u->u_instr_sequence);
|
g = _PyCfg_FromInstructionSequence(u->u_instr_sequence);
|
||||||
if (g == NULL) {
|
if (g == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -7645,39 +7562,6 @@ optimize_and_assemble(struct compiler *c, int addNone)
|
||||||
return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename);
|
return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Access to compiler optimizations for unit tests.
|
|
||||||
*
|
|
||||||
* _PyCompile_CodeGen takes and AST, applies code-gen and
|
|
||||||
* returns the unoptimized CFG as an instruction list.
|
|
||||||
*
|
|
||||||
* _PyCompile_OptimizeCfg takes an instruction list, constructs
|
|
||||||
* a CFG, optimizes it and converts back to an instruction list.
|
|
||||||
*
|
|
||||||
* An instruction list is a PyList where each item is either
|
|
||||||
* a tuple describing a single instruction:
|
|
||||||
* (opcode, oparg, lineno, end_lineno, col, end_col), or
|
|
||||||
* a jump target label marking the beginning of a basic block.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
cfg_to_instruction_sequence(cfg_builder *g)
|
|
||||||
{
|
|
||||||
instr_sequence *seq = (instr_sequence *)_PyInstructionSequence_New();
|
|
||||||
if (seq != NULL) {
|
|
||||||
if (_PyCfg_ToInstructionSequence(g, seq) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (PyObject*)seq;
|
|
||||||
error:
|
|
||||||
PyInstructionSequence_Fini(seq);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// C implementation of inspect.cleandoc()
|
// C implementation of inspect.cleandoc()
|
||||||
//
|
//
|
||||||
// Difference from inspect.cleandoc():
|
// Difference from inspect.cleandoc():
|
||||||
|
@ -7768,6 +7652,12 @@ _PyCompile_CleanDoc(PyObject *doc)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Access to compiler optimizations for unit tests.
|
||||||
|
*
|
||||||
|
* _PyCompile_CodeGen takes an AST, applies code-gen and
|
||||||
|
* returns the unoptimized CFG as an instruction list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,
|
_PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,
|
||||||
|
@ -7859,35 +7749,6 @@ finally:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
|
||||||
_PyCompile_OptimizeCfg(PyObject *seq, PyObject *consts, int nlocals)
|
|
||||||
{
|
|
||||||
if (!_PyInstructionSequence_Check(seq)) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "expected an instruction sequence");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyObject *const_cache = PyDict_New();
|
|
||||||
if (const_cache == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *res = NULL;
|
|
||||||
cfg_builder *g = instr_sequence_to_cfg((instr_sequence*)seq);
|
|
||||||
if (g == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
int nparams = 0, firstlineno = 1;
|
|
||||||
if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals,
|
|
||||||
nparams, firstlineno) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
res = cfg_to_instruction_sequence(g);
|
|
||||||
error:
|
|
||||||
Py_DECREF(const_cache);
|
|
||||||
_PyCfgBuilder_Free(g);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _PyCfg_JumpLabelsToTargets(cfg_builder *g);
|
int _PyCfg_JumpLabelsToTargets(cfg_builder *g);
|
||||||
|
|
||||||
PyCodeObject *
|
PyCodeObject *
|
||||||
|
@ -7908,7 +7769,7 @@ _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g = instr_sequence_to_cfg((instr_sequence*)seq);
|
g = _PyCfg_FromInstructionSequence((instr_sequence*)seq);
|
||||||
if (g == NULL) {
|
if (g == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -751,6 +751,36 @@ make_cfg_traversal_stack(basicblock *entryblock) {
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the stack effect of opcode with argument oparg.
|
||||||
|
|
||||||
|
Some opcodes have different stack effect when jump to the target and
|
||||||
|
when not jump. The 'jump' parameter specifies the case:
|
||||||
|
|
||||||
|
* 0 -- when not jump
|
||||||
|
* 1 -- when jump
|
||||||
|
* -1 -- maximal
|
||||||
|
*/
|
||||||
|
Py_LOCAL(int)
|
||||||
|
stack_effect(int opcode, int oparg, int jump)
|
||||||
|
{
|
||||||
|
if (opcode < 0) {
|
||||||
|
return PY_INVALID_STACK_EFFECT;
|
||||||
|
}
|
||||||
|
if ((opcode <= MAX_REAL_OPCODE) && (_PyOpcode_Deopt[opcode] != opcode)) {
|
||||||
|
// Specialized instructions are not supported.
|
||||||
|
return PY_INVALID_STACK_EFFECT;
|
||||||
|
}
|
||||||
|
int popped = _PyOpcode_num_popped(opcode, oparg);
|
||||||
|
int pushed = _PyOpcode_num_pushed(opcode, oparg);
|
||||||
|
if (popped < 0 || pushed < 0) {
|
||||||
|
return PY_INVALID_STACK_EFFECT;
|
||||||
|
}
|
||||||
|
if (IS_BLOCK_PUSH_OPCODE(opcode) && !jump) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return pushed - popped;
|
||||||
|
}
|
||||||
|
|
||||||
Py_LOCAL_INLINE(int)
|
Py_LOCAL_INLINE(int)
|
||||||
stackdepth_push(basicblock ***sp, basicblock *b, int depth)
|
stackdepth_push(basicblock ***sp, basicblock *b, int depth)
|
||||||
{
|
{
|
||||||
|
@ -795,8 +825,7 @@ calculate_stackdepth(cfg_builder *g)
|
||||||
basicblock *next = b->b_next;
|
basicblock *next = b->b_next;
|
||||||
for (int i = 0; i < b->b_iused; i++) {
|
for (int i = 0; i < b->b_iused; i++) {
|
||||||
cfg_instr *instr = &b->b_instr[i];
|
cfg_instr *instr = &b->b_instr[i];
|
||||||
int effect = PyCompile_OpcodeStackEffectWithJump(
|
int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0);
|
||||||
instr->i_opcode, instr->i_oparg, 0);
|
|
||||||
if (effect == PY_INVALID_STACK_EFFECT) {
|
if (effect == PY_INVALID_STACK_EFFECT) {
|
||||||
PyErr_Format(PyExc_SystemError,
|
PyErr_Format(PyExc_SystemError,
|
||||||
"Invalid stack effect for opcode=%d, arg=%i",
|
"Invalid stack effect for opcode=%d, arg=%i",
|
||||||
|
@ -813,8 +842,7 @@ calculate_stackdepth(cfg_builder *g)
|
||||||
maxdepth = new_depth;
|
maxdepth = new_depth;
|
||||||
}
|
}
|
||||||
if (HAS_TARGET(instr->i_opcode)) {
|
if (HAS_TARGET(instr->i_opcode)) {
|
||||||
effect = PyCompile_OpcodeStackEffectWithJump(
|
effect = stack_effect(instr->i_opcode, instr->i_oparg, 1);
|
||||||
instr->i_opcode, instr->i_oparg, 1);
|
|
||||||
if (effect == PY_INVALID_STACK_EFFECT) {
|
if (effect == PY_INVALID_STACK_EFFECT) {
|
||||||
PyErr_Format(PyExc_SystemError,
|
PyErr_Format(PyExc_SystemError,
|
||||||
"Invalid stack effect for opcode=%d, arg=%i",
|
"Invalid stack effect for opcode=%d, arg=%i",
|
||||||
|
@ -2711,6 +2739,49 @@ prepare_localsplus(_PyCompile_CodeUnitMetadata *umd, cfg_builder *g, int code_fl
|
||||||
return nlocalsplus;
|
return nlocalsplus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_builder *
|
||||||
|
_PyCfg_FromInstructionSequence(_PyInstructionSequence *seq)
|
||||||
|
{
|
||||||
|
if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cfg_builder *g = _PyCfgBuilder_New();
|
||||||
|
if (g == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < seq->s_used; i++) {
|
||||||
|
seq->s_instrs[i].i_target = 0;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < seq->s_used; i++) {
|
||||||
|
_PyInstruction *instr = &seq->s_instrs[i];
|
||||||
|
if (HAS_TARGET(instr->i_opcode)) {
|
||||||
|
assert(instr->i_oparg >= 0 && instr->i_oparg < seq->s_used);
|
||||||
|
seq->s_instrs[instr->i_oparg].i_target = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < seq->s_used; i++) {
|
||||||
|
_PyInstruction *instr = &seq->s_instrs[i];
|
||||||
|
if (instr->i_target) {
|
||||||
|
jump_target_label lbl_ = {i};
|
||||||
|
if (_PyCfgBuilder_UseLabel(g, lbl_) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int opcode = instr->i_opcode;
|
||||||
|
int oparg = instr->i_oparg;
|
||||||
|
if (_PyCfgBuilder_Addop(g, opcode, oparg, instr->i_loc) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_PyCfgBuilder_CheckSize(g) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
error:
|
||||||
|
_PyCfgBuilder_Free(g);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyCfg_ToInstructionSequence(cfg_builder *g, _PyInstructionSequence *seq)
|
_PyCfg_ToInstructionSequence(cfg_builder *g, _PyInstructionSequence *seq)
|
||||||
{
|
{
|
||||||
|
@ -2742,6 +2813,9 @@ _PyCfg_ToInstructionSequence(cfg_builder *g, _PyInstructionSequence *seq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2796,3 +2870,66 @@ _PyCfg_JumpLabelsToTargets(cfg_builder *g)
|
||||||
RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));
|
RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exported API functions */
|
||||||
|
|
||||||
|
int
|
||||||
|
PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump)
|
||||||
|
{
|
||||||
|
return stack_effect(opcode, oparg, jump);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyCompile_OpcodeStackEffect(int opcode, int oparg)
|
||||||
|
{
|
||||||
|
return stack_effect(opcode, oparg, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Access to compiler optimizations for unit tests.
|
||||||
|
|
||||||
|
* _PyCompile_OptimizeCfg takes an instruction list, constructs
|
||||||
|
* a CFG, optimizes it and converts back to an instruction list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
cfg_to_instruction_sequence(cfg_builder *g)
|
||||||
|
{
|
||||||
|
_PyInstructionSequence *seq = (_PyInstructionSequence *)_PyInstructionSequence_New();
|
||||||
|
if (seq == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (_PyCfg_ToInstructionSequence(g, seq) < 0) {
|
||||||
|
PyInstructionSequence_Fini(seq);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (PyObject*)seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyCompile_OptimizeCfg(PyObject *seq, PyObject *consts, int nlocals)
|
||||||
|
{
|
||||||
|
if (!_PyInstructionSequence_Check(seq)) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "expected an instruction sequence");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyObject *const_cache = PyDict_New();
|
||||||
|
if (const_cache == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *res = NULL;
|
||||||
|
cfg_builder *g = _PyCfg_FromInstructionSequence((_PyInstructionSequence*)seq);
|
||||||
|
if (g == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
int nparams = 0, firstlineno = 1;
|
||||||
|
if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals,
|
||||||
|
nparams, firstlineno) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
res = cfg_to_instruction_sequence(g);
|
||||||
|
error:
|
||||||
|
Py_DECREF(const_cache);
|
||||||
|
_PyCfgBuilder_Free(g);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue