Skip to content

Commit

Permalink
Merge pull request #54 from thautwarm/more-general-const-key
Browse files Browse the repository at this point in the history
Simplifying and enhancing const_key
  • Loading branch information
MatthieuDartiailh committed Jan 31, 2020
2 parents 2d93b01 + dddf3ec commit 119e75a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 52 deletions.
59 changes: 7 additions & 52 deletions bytecode/instr.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import enum
import dis
import math
import opcode as _opcode
import sys
import types
from marshal import dumps as _dumps

import bytecode as _bytecode

Expand All @@ -27,56 +26,12 @@ class Compare(enum.IntEnum):


def const_key(obj):
# Python implmentation of the C function _PyCode_ConstantKey()
# of Python 3.6

obj_type = type(obj)
# Note: check obj_type == test_type rather than isinstance(obj, test_type)
# to not merge instance of subtypes

if (obj is None
or obj is Ellipsis
or obj_type in {int, bool, bytes, str, types.CodeType}):
return (obj_type, obj)

if obj_type == float:
# all we need is to make the tuple different in either the 0.0
# or -0.0 case from all others, just to avoid the "coercion".
if obj == 0.0 and math.copysign(1.0, obj) < 0:
return (obj_type, obj, None)
else:
return (obj_type, obj)

if obj_type == complex:
# For the complex case we must make complex(x, 0.)
# different from complex(x, -0.) and complex(0., y)
# different from complex(-0., y), for any x and y.
# All four complex zeros must be distinguished.
real_negzero = (obj.real == 0.0 and math.copysign(1.0, obj.real) < 0.0)
imag_negzero = (obj.imag == 0.0 and math.copysign(1.0, obj.imag) < 0.0)

# use True, False and None singleton as tags for the real and imag
# sign, to make tuples different
if real_negzero and imag_negzero:
return (obj_type, obj, True)
elif imag_negzero:
return (obj_type, obj, False)
elif real_negzero:
return (obj_type, obj, None)
else:
return (obj_type, obj)

if type(obj) == tuple:
key = tuple(const_key(item) for item in obj)
return (obj_type, obj, key)

if type(obj) == frozenset:
key = frozenset(const_key(item) for item in obj)
return (obj_type, obj, key)

# For other types, we use the object identifier as an unique identifier
# to ensure that they are seen as unequal.
return (obj_type, id(obj))
try:
return _dumps(obj)
except ValueError:
# For other types, we use the object identifier as an unique identifier
# to ensure that they are seen as unequal.
return (type(obj), id(obj))


def _check_lineno(lineno):
Expand Down
29 changes: 29 additions & 0 deletions bytecode/tests/test_instr.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,35 @@ def check(instr):
for arg in 2**31, 2**32, 2**63, 2**64, -1:
self.assertEqual(Instr('LOAD_CONST', arg).stack_effect(), 1)

def test_code_object_containing_mutable_data(self):
from bytecode import Bytecode, Instr
from types import CodeType

def f():
def g():
return "value"
return g

f_code = Bytecode.from_code(f.__code__)
instr_load_code = None
mutable_datum = [4, 2]

for each in f_code:
if (isinstance(each, Instr)
and each.name == 'LOAD_CONST'
and isinstance(each.arg, CodeType)):
instr_load_code = each
break

self.assertIsNotNone(instr_load_code)

g_code = Bytecode.from_code(instr_load_code.arg)
g_code[0].arg = mutable_datum
instr_load_code.arg = g_code.to_code()
f.__code__ = f_code.to_code()

self.assertIs(f()(), mutable_datum)


if __name__ == "__main__":
unittest.main()
4 changes: 4 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ New features:
- :class:`Bytecode`, :class:`ConcreteBytecode`, :class:`BasicBlock` and
:class:`ControlFlowGraph` have a new :meth:`legalize` method validating
their content and removing SetLineno. PR #52
- Modify the implementation of :code:`const_key` to avoid manual
synchronizations with :code:`_PyCode_ConstantKey` in CPython codebase and
allow the use of arbitrary Python objects as constants of nested code
objects. #54

API changes:

Expand Down

0 comments on commit 119e75a

Please sign in to comment.