Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
7bdf2826
Commit
7bdf2826
authored
Sep 18, 2018
by
Serhiy Storchaka
Committed by
GitHub
Sep 18, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-32455: Add jump parameter to dis.stack_effect(). (GH-6610)
Add C API function PyCompile_OpcodeStackEffectWithJump().
parent
b042cf10
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
99 additions
and
26 deletions
+99
-26
Doc/library/dis.rst
Doc/library/dis.rst
+10
-1
Include/compile.h
Include/compile.h
+1
-0
Lib/test/test__opcode.py
Lib/test/test__opcode.py
+47
-14
Misc/NEWS.d/next/C API/2018-07-08-12-06-18.bpo-32455.KVHlkz.rst
...EWS.d/next/C API/2018-07-08-12-06-18.bpo-32455.KVHlkz.rst
+1
-0
Misc/NEWS.d/next/Library/2018-04-26-13-31-10.bpo-32455.KPWg3K.rst
...S.d/next/Library/2018-04-26-13-31-10.bpo-32455.KPWg3K.rst
+1
-0
Modules/_opcode.c
Modules/_opcode.c
+21
-3
Modules/clinic/_opcode.c.h
Modules/clinic/_opcode.c.h
+12
-8
Python/compile.c
Python/compile.c
+6
-0
No files found.
Doc/library/dis.rst
View file @
7bdf2826
...
...
@@ -248,12 +248,21 @@ operation is being performed, so the intermediate analysis object isn't useful:
return a list of these offsets.
.. function:: stack_effect(opcode,
[oparg]
)
.. function:: stack_effect(opcode,
oparg=None, *, jump=None
)
Compute the stack effect of *opcode* with argument *oparg*.
If the code has a jump target and *jump* is ``True``, :func:`~stack_effect`
will return the stack effect of jumping. If *jump* is ``False``,
it will return the stack effect of not jumping. And if *jump* is
``None`` (default), it will return the maximal stack effect of both cases.
.. versionadded:: 3.4
.. versionchanged:: 3.8
Added *jump* parameter.
.. _bytecodes:
Python Bytecode Instructions
...
...
Include/compile.h
View file @
7bdf2826
...
...
@@ -75,6 +75,7 @@ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);
#define PY_INVALID_STACK_EFFECT INT_MAX
PyAPI_FUNC
(
int
)
PyCompile_OpcodeStackEffect
(
int
opcode
,
int
oparg
);
PyAPI_FUNC
(
int
)
PyCompile_OpcodeStackEffectWithJump
(
int
opcode
,
int
oparg
,
int
jump
);
PyAPI_FUNC
(
int
)
_PyAST_Optimize
(
struct
_mod
*
,
PyArena
*
arena
,
int
optimize
);
...
...
Lib/test/test__opcode.py
View file @
7bdf2826
...
...
@@ -3,32 +3,65 @@ from test.support import import_module
import
unittest
_opcode
=
import_module
(
"_opcode"
)
from
_opcode
import
stack_effect
class
OpcodeTests
(
unittest
.
TestCase
):
def
test_stack_effect
(
self
):
self
.
assertEqual
(
_opcode
.
stack_effect
(
dis
.
opmap
[
'POP_TOP'
]),
-
1
)
self
.
assertEqual
(
_opcode
.
stack_effect
(
dis
.
opmap
[
'DUP_TOP_TWO'
]),
2
)
self
.
assertEqual
(
_opcode
.
stack_effect
(
dis
.
opmap
[
'BUILD_SLICE'
],
0
),
-
1
)
self
.
assertEqual
(
_opcode
.
stack_effect
(
dis
.
opmap
[
'BUILD_SLICE'
],
1
),
-
1
)
self
.
assertEqual
(
_opcode
.
stack_effect
(
dis
.
opmap
[
'BUILD_SLICE'
],
3
),
-
2
)
self
.
assertRaises
(
ValueError
,
_opcode
.
stack_effect
,
30000
)
self
.
assertRaises
(
ValueError
,
_opcode
.
stack_effect
,
dis
.
opmap
[
'BUILD_SLICE'
])
self
.
assertRaises
(
ValueError
,
_opcode
.
stack_effect
,
dis
.
opmap
[
'POP_TOP'
],
0
)
self
.
assertEqual
(
stack_effect
(
dis
.
opmap
[
'POP_TOP'
]),
-
1
)
self
.
assertEqual
(
stack_effect
(
dis
.
opmap
[
'DUP_TOP_TWO'
]),
2
)
self
.
assertEqual
(
stack_effect
(
dis
.
opmap
[
'BUILD_SLICE'
],
0
),
-
1
)
self
.
assertEqual
(
stack_effect
(
dis
.
opmap
[
'BUILD_SLICE'
],
1
),
-
1
)
self
.
assertEqual
(
stack_effect
(
dis
.
opmap
[
'BUILD_SLICE'
],
3
),
-
2
)
self
.
assertRaises
(
ValueError
,
stack_effect
,
30000
)
self
.
assertRaises
(
ValueError
,
stack_effect
,
dis
.
opmap
[
'BUILD_SLICE'
])
self
.
assertRaises
(
ValueError
,
stack_effect
,
dis
.
opmap
[
'POP_TOP'
],
0
)
# All defined opcodes
for
name
,
code
in
dis
.
opmap
.
items
():
with
self
.
subTest
(
opname
=
name
):
if
code
<
dis
.
HAVE_ARGUMENT
:
_opcode
.
stack_effect
(
code
)
self
.
assertRaises
(
ValueError
,
_opcode
.
stack_effect
,
code
,
0
)
stack_effect
(
code
)
self
.
assertRaises
(
ValueError
,
stack_effect
,
code
,
0
)
else
:
_opcode
.
stack_effect
(
code
,
0
)
self
.
assertRaises
(
ValueError
,
_opcode
.
stack_effect
,
code
)
stack_effect
(
code
,
0
)
self
.
assertRaises
(
ValueError
,
stack_effect
,
code
)
# All not defined opcodes
for
code
in
set
(
range
(
256
))
-
set
(
dis
.
opmap
.
values
()):
with
self
.
subTest
(
opcode
=
code
):
self
.
assertRaises
(
ValueError
,
_opcode
.
stack_effect
,
code
)
self
.
assertRaises
(
ValueError
,
_opcode
.
stack_effect
,
code
,
0
)
self
.
assertRaises
(
ValueError
,
stack_effect
,
code
)
self
.
assertRaises
(
ValueError
,
stack_effect
,
code
,
0
)
def
test_stack_effect_jump
(
self
):
JUMP_IF_TRUE_OR_POP
=
dis
.
opmap
[
'JUMP_IF_TRUE_OR_POP'
]
self
.
assertEqual
(
stack_effect
(
JUMP_IF_TRUE_OR_POP
,
0
),
0
)
self
.
assertEqual
(
stack_effect
(
JUMP_IF_TRUE_OR_POP
,
0
,
jump
=
True
),
0
)
self
.
assertEqual
(
stack_effect
(
JUMP_IF_TRUE_OR_POP
,
0
,
jump
=
False
),
-
1
)
FOR_ITER
=
dis
.
opmap
[
'FOR_ITER'
]
self
.
assertEqual
(
stack_effect
(
FOR_ITER
,
0
),
1
)
self
.
assertEqual
(
stack_effect
(
FOR_ITER
,
0
,
jump
=
True
),
-
1
)
self
.
assertEqual
(
stack_effect
(
FOR_ITER
,
0
,
jump
=
False
),
1
)
JUMP_FORWARD
=
dis
.
opmap
[
'JUMP_FORWARD'
]
self
.
assertEqual
(
stack_effect
(
JUMP_FORWARD
,
0
),
0
)
self
.
assertEqual
(
stack_effect
(
JUMP_FORWARD
,
0
,
jump
=
True
),
0
)
self
.
assertEqual
(
stack_effect
(
JUMP_FORWARD
,
0
,
jump
=
False
),
0
)
# All defined opcodes
has_jump
=
dis
.
hasjabs
+
dis
.
hasjrel
for
name
,
code
in
dis
.
opmap
.
items
():
with
self
.
subTest
(
opname
=
name
):
if
code
<
dis
.
HAVE_ARGUMENT
:
common
=
stack_effect
(
code
)
jump
=
stack_effect
(
code
,
jump
=
True
)
nojump
=
stack_effect
(
code
,
jump
=
False
)
else
:
common
=
stack_effect
(
code
,
0
)
jump
=
stack_effect
(
code
,
0
,
jump
=
True
)
nojump
=
stack_effect
(
code
,
0
,
jump
=
False
)
if
code
in
has_jump
:
self
.
assertEqual
(
common
,
max
(
jump
,
nojump
))
else
:
self
.
assertEqual
(
jump
,
common
)
self
.
assertEqual
(
nojump
,
common
)
if
__name__
==
"__main__"
:
...
...
Misc/NEWS.d/next/C API/2018-07-08-12-06-18.bpo-32455.KVHlkz.rst
0 → 100644
View file @
7bdf2826
Added :c:func:`PyCompile_OpcodeStackEffectWithJump`.
Misc/NEWS.d/next/Library/2018-04-26-13-31-10.bpo-32455.KPWg3K.rst
0 → 100644
View file @
7bdf2826
Added *jump* parameter to :func:`dis.stack_effect`.
Modules/_opcode.c
View file @
7bdf2826
...
...
@@ -15,16 +15,20 @@ _opcode.stack_effect -> int
opcode: int
oparg: object = None
/
*
jump: object = None
Compute the stack effect of the opcode.
[clinic start generated code]*/
static
int
_opcode_stack_effect_impl
(
PyObject
*
module
,
int
opcode
,
PyObject
*
oparg
)
/*[clinic end generated code: output=ad39467fa3ad22ce input=2d0a9ee53c0418f5]*/
_opcode_stack_effect_impl
(
PyObject
*
module
,
int
opcode
,
PyObject
*
oparg
,
PyObject
*
jump
)
/*[clinic end generated code: output=64a18f2ead954dbb input=461c9d4a44851898]*/
{
int
effect
;
int
oparg_int
=
0
;
int
jump_int
;
if
(
HAS_ARG
(
opcode
))
{
if
(
oparg
==
Py_None
)
{
PyErr_SetString
(
PyExc_ValueError
,
...
...
@@ -40,7 +44,21 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg)
"stack_effect: opcode does not permit oparg but oparg was specified"
);
return
-
1
;
}
effect
=
PyCompile_OpcodeStackEffect
(
opcode
,
oparg_int
);
if
(
jump
==
Py_None
)
{
jump_int
=
-
1
;
}
else
if
(
jump
==
Py_True
)
{
jump_int
=
1
;
}
else
if
(
jump
==
Py_False
)
{
jump_int
=
0
;
}
else
{
PyErr_SetString
(
PyExc_ValueError
,
"stack_effect: jump must be False, True or None"
);
return
-
1
;
}
effect
=
PyCompile_OpcodeStackEffectWithJump
(
opcode
,
oparg_int
,
jump_int
);
if
(
effect
==
PY_INVALID_STACK_EFFECT
)
{
PyErr_SetString
(
PyExc_ValueError
,
"invalid opcode or oparg"
);
...
...
Modules/clinic/_opcode.c.h
View file @
7bdf2826
...
...
@@ -3,30 +3,34 @@ preserve
[clinic start generated code]*/
PyDoc_STRVAR
(
_opcode_stack_effect__doc__
,
"stack_effect($module, opcode, oparg=None, /)
\n
"
"stack_effect($module, opcode, oparg=None, /
, *, jump=None
)
\n
"
"--
\n
"
"
\n
"
"Compute the stack effect of the opcode."
);
#define _OPCODE_STACK_EFFECT_METHODDEF \
{"stack_effect", (PyCFunction)_opcode_stack_effect, METH_FASTCALL, _opcode_stack_effect__doc__},
{"stack_effect", (PyCFunction)_opcode_stack_effect, METH_FASTCALL
|METH_KEYWORDS
, _opcode_stack_effect__doc__},
static
int
_opcode_stack_effect_impl
(
PyObject
*
module
,
int
opcode
,
PyObject
*
oparg
);
_opcode_stack_effect_impl
(
PyObject
*
module
,
int
opcode
,
PyObject
*
oparg
,
PyObject
*
jump
);
static
PyObject
*
_opcode_stack_effect
(
PyObject
*
module
,
PyObject
*
const
*
args
,
Py_ssize_t
nargs
)
_opcode_stack_effect
(
PyObject
*
module
,
PyObject
*
const
*
args
,
Py_ssize_t
nargs
,
PyObject
*
kwnames
)
{
PyObject
*
return_value
=
NULL
;
static
const
char
*
const
_keywords
[]
=
{
""
,
""
,
"jump"
,
NULL
};
static
_PyArg_Parser
_parser
=
{
"i|O$O:stack_effect"
,
_keywords
,
0
};
int
opcode
;
PyObject
*
oparg
=
Py_None
;
PyObject
*
jump
=
Py_None
;
int
_return_value
;
if
(
!
_PyArg_ParseStack
(
args
,
nargs
,
"i|O:stack_effect"
,
&
opcode
,
&
oparg
))
{
if
(
!
_PyArg_ParseStack
AndKeywords
(
args
,
nargs
,
kwnames
,
&
_parser
,
&
opcode
,
&
oparg
,
&
jump
))
{
goto
exit
;
}
_return_value
=
_opcode_stack_effect_impl
(
module
,
opcode
,
oparg
);
_return_value
=
_opcode_stack_effect_impl
(
module
,
opcode
,
oparg
,
jump
);
if
((
_return_value
==
-
1
)
&&
PyErr_Occurred
())
{
goto
exit
;
}
...
...
@@ -35,4 +39,4 @@ _opcode_stack_effect(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return
return_value
;
}
/*[clinic end generated code: output=
577a91c9aa5559a
9 input=a9049054013a1b77]*/
/*[clinic end generated code: output=
bbf6c4cfc91edc2
9 input=a9049054013a1b77]*/
Python/compile.c
View file @
7bdf2826
...
...
@@ -1116,6 +1116,12 @@ stack_effect(int opcode, int oparg, int jump)
return
PY_INVALID_STACK_EFFECT
;
/* not reachable */
}
int
PyCompile_OpcodeStackEffectWithJump
(
int
opcode
,
int
oparg
,
int
jump
)
{
return
stack_effect
(
opcode
,
oparg
,
jump
);
}
int
PyCompile_OpcodeStackEffect
(
int
opcode
,
int
oparg
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment