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
6a7506a7
Commit
6a7506a7
authored
Jun 12, 2016
by
Serhiy Storchaka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #27140: Added BUILD_CONST_KEY_MAP opcode.
parent
d611f4cf
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1361 additions
and
1187 deletions
+1361
-1187
Doc/library/dis.rst
Doc/library/dis.rst
+9
-0
Include/opcode.h
Include/opcode.h
+1
-0
Lib/importlib/_bootstrap_external.py
Lib/importlib/_bootstrap_external.py
+2
-1
Lib/opcode.py
Lib/opcode.py
+1
-0
Misc/NEWS
Misc/NEWS
+2
-0
PC/launcher.c
PC/launcher.c
+1
-1
Python/ceval.c
Python/ceval.c
+33
-0
Python/compile.c
Python/compile.c
+156
-29
Python/importlib_external.h
Python/importlib_external.h
+1155
-1155
Python/opcode_targets.h
Python/opcode_targets.h
+1
-1
No files found.
Doc/library/dis.rst
View file @
6a7506a7
...
...
@@ -768,6 +768,15 @@ All of the following opcodes use their arguments.
to hold *count* entries.
.. opcode:: BUILD_CONST_KEY_MAP (count)
The version of :opcode:`BUILD_MAP` specialized for constant keys. *count*
values are consumed from the stack. The top element on the stack contains
a tuple of keys.
.. versionadded:: 3.6
.. opcode:: LOAD_ATTR (namei)
Replaces TOS with ``getattr(TOS, co_names[namei])``.
...
...
Include/opcode.h
View file @
6a7506a7
...
...
@@ -123,6 +123,7 @@ extern "C" {
#define BUILD_SET_UNPACK 153
#define SETUP_ASYNC_WITH 154
#define FORMAT_VALUE 155
#define BUILD_CONST_KEY_MAP 156
/* EXCEPT_HANDLER is a special, implicit block type which is created when
entering an except handler. It is not an opcode but we define it here
...
...
Lib/importlib/_bootstrap_external.py
View file @
6a7506a7
...
...
@@ -226,6 +226,7 @@ _code_type = type(_write_atomic.__code__)
# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483
# Python 3.6a0 3361 (lineno delta of code.co_lnotab becomes signed)
# Python 3.6a0 3370 (16 bit wordcode)
# Python 3.6a0 3371 (add BUILD_CONST_KEY_MAP opcode #27140)
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
...
...
@@ -234,7 +235,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
MAGIC_NUMBER
=
(
337
0
).
to_bytes
(
2
,
'little'
)
+
b'
\
r
\
n
'
MAGIC_NUMBER
=
(
337
1
).
to_bytes
(
2
,
'little'
)
+
b'
\
r
\
n
'
_RAW_MAGIC_NUMBER
=
int
.
from_bytes
(
MAGIC_NUMBER
,
'little'
)
# For import.c
_PYCACHE
=
'__pycache__'
...
...
Lib/opcode.py
View file @
6a7506a7
...
...
@@ -213,5 +213,6 @@ def_op('BUILD_TUPLE_UNPACK', 152)
def_op
(
'BUILD_SET_UNPACK'
,
153
)
def_op
(
'FORMAT_VALUE'
,
155
)
def_op
(
'BUILD_CONST_KEY_MAP'
,
156
)
del
def_op
,
name_op
,
jrel_op
,
jabs_op
Misc/NEWS
View file @
6a7506a7
...
...
@@ -10,6 +10,8 @@ What's New in Python 3.6.0 alpha 2
Core and Builtins
-----------------
- Issue #27140: Added BUILD_CONST_KEY_MAP opcode.
- Issue #27186: Add support for os.PathLike objects to open() (part of PEP 519).
- Issue #27066: Fixed SystemError if a custom opener (for open()) returns a
...
...
PC/launcher.c
View file @
6a7506a7
...
...
@@ -1089,7 +1089,7 @@ static PYC_MAGIC magic_values[] = {
{
3190
,
3230
,
L"3.3"
},
{
3250
,
3310
,
L"3.4"
},
{
3320
,
3350
,
L"3.5"
},
{
3360
,
337
0
,
L"3.6"
},
{
3360
,
337
1
,
L"3.6"
},
{
0
}
};
...
...
Python/ceval.c
View file @
6a7506a7
...
...
@@ -2647,6 +2647,39 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH
();
}
TARGET
(
BUILD_CONST_KEY_MAP
)
{
int
i
;
PyObject
*
map
;
PyObject
*
keys
=
TOP
();
if
(
!
PyTuple_CheckExact
(
keys
)
||
PyTuple_GET_SIZE
(
keys
)
!=
(
Py_ssize_t
)
oparg
)
{
PyErr_SetString
(
PyExc_SystemError
,
"bad BUILD_CONST_KEY_MAP keys argument"
);
goto
error
;
}
map
=
_PyDict_NewPresized
((
Py_ssize_t
)
oparg
);
if
(
map
==
NULL
)
{
goto
error
;
}
for
(
i
=
oparg
;
i
>
0
;
i
--
)
{
int
err
;
PyObject
*
key
=
PyTuple_GET_ITEM
(
keys
,
oparg
-
i
);
PyObject
*
value
=
PEEK
(
i
+
1
);
err
=
PyDict_SetItem
(
map
,
key
,
value
);
if
(
err
!=
0
)
{
Py_DECREF
(
map
);
goto
error
;
}
}
Py_DECREF
(
POP
());
while
(
oparg
--
)
{
Py_DECREF
(
POP
());
}
PUSH
(
map
);
DISPATCH
();
}
TARGET
(
BUILD_MAP_UNPACK_WITH_CALL
)
TARGET
(
BUILD_MAP_UNPACK
)
{
int
with_call
=
opcode
==
BUILD_MAP_UNPACK_WITH_CALL
;
...
...
Python/compile.c
View file @
6a7506a7
...
...
@@ -980,6 +980,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return
1
-
(
oparg
&
0xFF
);
case
BUILD_MAP
:
return
1
-
2
*
oparg
;
case
BUILD_CONST_KEY_MAP
:
return
-
oparg
;
case
LOAD_ATTR
:
return
0
;
case
COMPARE_OP
:
...
...
@@ -1234,6 +1236,15 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
return 0; \
}
/* Same as ADDOP_O, but steals a reference. */
#define ADDOP_N(C, OP, O, TYPE) { \
if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) { \
Py_DECREF((O)); \
return 0; \
} \
Py_DECREF((O)); \
}
#define ADDOP_NAME(C, OP, O, TYPE) { \
if (!compiler_addop_name((C), (OP), (C)->u->u_ ## TYPE, (O))) \
return 0; \
...
...
@@ -1309,6 +1320,44 @@ compiler_isdocstring(stmt_ty s)
return
0
;
}
static
int
is_const
(
expr_ty
e
)
{
switch
(
e
->
kind
)
{
case
Constant_kind
:
case
Num_kind
:
case
Str_kind
:
case
Bytes_kind
:
case
Ellipsis_kind
:
case
NameConstant_kind
:
return
1
;
default:
return
0
;
}
}
static
PyObject
*
get_const_value
(
expr_ty
e
)
{
switch
(
e
->
kind
)
{
case
Constant_kind
:
return
e
->
v
.
Constant
.
value
;
case
Num_kind
:
return
e
->
v
.
Num
.
n
;
case
Str_kind
:
return
e
->
v
.
Str
.
s
;
case
Bytes_kind
:
return
e
->
v
.
Bytes
.
s
;
case
Ellipsis_kind
:
return
Py_Ellipsis
;
case
NameConstant_kind
:
return
e
->
v
.
NameConstant
.
value
;
default:
assert
(
!
is_const
(
e
));
return
NULL
;
}
}
/* Compile a sequence of statements, checking for a docstring. */
static
int
...
...
@@ -2604,19 +2653,9 @@ compiler_visit_stmt_expr(struct compiler *c, expr_ty value)
return
1
;
}
switch
(
value
->
kind
)
{
case
Str_kind
:
case
Num_kind
:
case
Ellipsis_kind
:
case
Bytes_kind
:
case
NameConstant_kind
:
case
Constant_kind
:
if
(
is_const
(
value
))
{
/* ignore constant statement */
return
1
;
default:
break
;
}
VISIT
(
c
,
expr
,
value
);
...
...
@@ -3095,6 +3134,49 @@ compiler_set(struct compiler *c, expr_ty e)
BUILD_SET
,
BUILD_SET_UNPACK
);
}
static
int
are_all_items_const
(
asdl_seq
*
seq
,
Py_ssize_t
begin
,
Py_ssize_t
end
)
{
Py_ssize_t
i
;
for
(
i
=
begin
;
i
<
end
;
i
++
)
{
expr_ty
key
=
(
expr_ty
)
asdl_seq_GET
(
seq
,
i
);
if
(
key
==
NULL
||
!
is_const
(
key
))
return
0
;
}
return
1
;
}
static
int
compiler_subdict
(
struct
compiler
*
c
,
expr_ty
e
,
Py_ssize_t
begin
,
Py_ssize_t
end
)
{
Py_ssize_t
i
,
n
=
end
-
begin
;
PyObject
*
keys
,
*
key
;
if
(
n
>
1
&&
are_all_items_const
(
e
->
v
.
Dict
.
keys
,
begin
,
end
))
{
for
(
i
=
begin
;
i
<
end
;
i
++
)
{
VISIT
(
c
,
expr
,
(
expr_ty
)
asdl_seq_GET
(
e
->
v
.
Dict
.
values
,
i
));
}
keys
=
PyTuple_New
(
n
);
if
(
keys
==
NULL
)
{
return
0
;
}
for
(
i
=
begin
;
i
<
end
;
i
++
)
{
key
=
get_const_value
((
expr_ty
)
asdl_seq_GET
(
e
->
v
.
Dict
.
keys
,
i
));
Py_INCREF
(
key
);
PyTuple_SET_ITEM
(
keys
,
i
-
begin
,
key
);
}
ADDOP_N
(
c
,
LOAD_CONST
,
keys
,
consts
);
ADDOP_I
(
c
,
BUILD_CONST_KEY_MAP
,
n
);
}
else
{
for
(
i
=
begin
;
i
<
end
;
i
++
)
{
VISIT
(
c
,
expr
,
(
expr_ty
)
asdl_seq_GET
(
e
->
v
.
Dict
.
keys
,
i
));
VISIT
(
c
,
expr
,
(
expr_ty
)
asdl_seq_GET
(
e
->
v
.
Dict
.
values
,
i
));
}
ADDOP_I
(
c
,
BUILD_MAP
,
n
);
}
return
1
;
}
static
int
compiler_dict
(
struct
compiler
*
c
,
expr_ty
e
)
{
...
...
@@ -3107,7 +3189,8 @@ compiler_dict(struct compiler *c, expr_ty e)
for
(
i
=
0
;
i
<
n
;
i
++
)
{
is_unpacking
=
(
expr_ty
)
asdl_seq_GET
(
e
->
v
.
Dict
.
keys
,
i
)
==
NULL
;
if
(
elements
==
0xFFFF
||
(
elements
&&
is_unpacking
))
{
ADDOP_I
(
c
,
BUILD_MAP
,
elements
);
if
(
!
compiler_subdict
(
c
,
e
,
i
-
elements
,
i
))
return
0
;
containers
++
;
elements
=
0
;
}
...
...
@@ -3116,13 +3199,12 @@ compiler_dict(struct compiler *c, expr_ty e)
containers
++
;
}
else
{
VISIT
(
c
,
expr
,
(
expr_ty
)
asdl_seq_GET
(
e
->
v
.
Dict
.
keys
,
i
));
VISIT
(
c
,
expr
,
(
expr_ty
)
asdl_seq_GET
(
e
->
v
.
Dict
.
values
,
i
));
elements
++
;
}
}
if
(
elements
||
containers
==
0
)
{
ADDOP_I
(
c
,
BUILD_MAP
,
elements
);
if
(
!
compiler_subdict
(
c
,
e
,
n
-
elements
,
n
))
return
0
;
containers
++
;
}
/* If there is more than one dict, they need to be merged into a new
...
...
@@ -3266,6 +3348,42 @@ compiler_formatted_value(struct compiler *c, expr_ty e)
return
1
;
}
static
int
compiler_subkwargs
(
struct
compiler
*
c
,
asdl_seq
*
keywords
,
Py_ssize_t
begin
,
Py_ssize_t
end
)
{
Py_ssize_t
i
,
n
=
end
-
begin
;
keyword_ty
kw
;
PyObject
*
keys
,
*
key
;
assert
(
n
>
0
);
if
(
n
>
1
)
{
for
(
i
=
begin
;
i
<
end
;
i
++
)
{
kw
=
asdl_seq_GET
(
keywords
,
i
);
VISIT
(
c
,
expr
,
kw
->
value
);
}
keys
=
PyTuple_New
(
n
);
if
(
keys
==
NULL
)
{
return
0
;
}
for
(
i
=
begin
;
i
<
end
;
i
++
)
{
key
=
((
keyword_ty
)
asdl_seq_GET
(
keywords
,
i
))
->
arg
;
Py_INCREF
(
key
);
PyTuple_SET_ITEM
(
keys
,
i
-
begin
,
key
);
}
ADDOP_N
(
c
,
LOAD_CONST
,
keys
,
consts
);
ADDOP_I
(
c
,
BUILD_CONST_KEY_MAP
,
n
);
}
else
{
/* a for loop only executes once */
for
(
i
=
begin
;
i
<
end
;
i
++
)
{
kw
=
asdl_seq_GET
(
keywords
,
i
);
ADDOP_O
(
c
,
LOAD_CONST
,
kw
->
arg
,
consts
);
VISIT
(
c
,
expr
,
kw
->
value
);
}
ADDOP_I
(
c
,
BUILD_MAP
,
n
);
}
return
1
;
}
/* shared code between compiler_call and compiler_class */
static
int
compiler_call_helper
(
struct
compiler
*
c
,
...
...
@@ -3332,30 +3450,39 @@ compiler_call_helper(struct compiler *c,
if
(
kw
->
arg
==
NULL
)
{
/* A keyword argument unpacking. */
if
(
nseen
)
{
ADDOP_I
(
c
,
BUILD_MAP
,
nseen
);
nseen
=
0
;
if
(
nsubkwargs
)
{
if
(
!
compiler_subkwargs
(
c
,
keywords
,
i
-
nseen
,
i
))
return
0
;
nsubkwargs
++
;
}
VISIT
(
c
,
expr
,
kw
->
value
);
nsubkwargs
++
;
else
{
Py_ssize_t
j
;
for
(
j
=
0
;
j
<
nseen
;
j
++
)
{
VISIT
(
c
,
keyword
,
asdl_seq_GET
(
keywords
,
j
));
}
nkw
=
nseen
;
}
nseen
=
0
;
}
else
if
(
nsubkwargs
)
{
/* A keyword argument and we already have a dict. */
ADDOP_O
(
c
,
LOAD_CONST
,
kw
->
arg
,
consts
);
VISIT
(
c
,
expr
,
kw
->
value
);
ns
een
++
;
ns
ubkwargs
++
;
}
else
{
/* keyword argument */
VISIT
(
c
,
keyword
,
kw
)
nkw
++
;
nseen
++
;
}
}
if
(
nseen
)
{
if
(
nsubkwargs
)
{
/* Pack up any trailing keyword arguments. */
ADDOP_I
(
c
,
BUILD_MAP
,
nseen
);
if
(
!
compiler_subkwargs
(
c
,
keywords
,
nelts
-
nseen
,
nelts
))
return
0
;
nsubkwargs
++
;
}
else
{
VISIT_SEQ
(
c
,
keyword
,
keywords
);
nkw
=
nseen
;
}
}
if
(
nsubkwargs
)
{
code
|=
2
;
if
(
nsubkwargs
>
1
)
{
...
...
Python/importlib_external.h
View file @
6a7506a7
This source diff could not be displayed because it is too large. You can
view the blob
instead.
Python/opcode_targets.h
View file @
6a7506a7
...
...
@@ -155,7 +155,7 @@ static void *opcode_targets[256] = {
&&
TARGET_BUILD_SET_UNPACK
,
&&
TARGET_SETUP_ASYNC_WITH
,
&&
TARGET_FORMAT_VALUE
,
&&
_unknown_opcode
,
&&
TARGET_BUILD_CONST_KEY_MAP
,
&&
_unknown_opcode
,
&&
_unknown_opcode
,
&&
_unknown_opcode
,
...
...
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