Commit 2b2c76a9 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

IDL compiler: Fix make_copy.make_copy to better memoize.

Bug: 839389
Change-Id: I996d2415fff94a084f1a48a7ec92b8d741fde42d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1777344Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#691954}
parent 807336f9
......@@ -15,34 +15,43 @@ def make_copy(obj, memo=None):
if memo is None:
memo = dict()
if obj is None:
return None
if (obj is None
or isinstance(obj, (bool, int, long, float, complex, basestring))):
# Do not make a copy if the object is of an immutable primitive type
# (or its subclass).
#
# Memoization is tricky in case that both of Identifier('x') and
# Component('x') exist. We could memoize them as
# |memo[(type(obj), obj)] = copy|, though.
return obj
if hasattr(obj, 'make_copy'):
return obj.make_copy(memo=memo)
if obj.__hash__ is not None:
memoizable = obj.__hash__ is not None
if memoizable:
copy = memo.get(obj, None)
if copy is not None:
return copy
cls = type(obj)
def memoize(copy):
if memoizable:
memo[obj] = copy
return copy
if isinstance(obj, (bool, int, long, float, complex, basestring)):
# Subclasses of simple builtin types are expected to have a copy
# constructor.
return cls.__new__(cls, obj)
cls = type(obj)
if isinstance(obj, (list, tuple, set, frozenset)):
return cls(map(lambda x: make_copy(x, memo), obj))
return memoize(cls(map(lambda x: make_copy(x, memo), obj)))
if isinstance(obj, dict):
return cls([(make_copy(key, memo), make_copy(value, memo))
for key, value in obj.iteritems()])
return memoize(
cls([(make_copy(key, memo), make_copy(value, memo))
for key, value in obj.iteritems()]))
if hasattr(obj, '__dict__'):
copy = cls.__new__(cls)
memo[obj] = copy
copy = memoize(cls.__new__(cls))
for name, value in obj.__dict__.iteritems():
setattr(copy, name, make_copy(value, memo))
return copy
......
......@@ -4,6 +4,8 @@
import unittest
from .composition_parts import Component
from .composition_parts import Identifier
from .make_copy import make_copy
......@@ -16,6 +18,16 @@ class MakeCopyTest(unittest.TestCase):
self.assertEqual(3.14, make_copy(3.14))
self.assertEqual('abc', make_copy('abc'))
def test_primitives_subclasses(self):
# Identifier and Component are subclasses of str. Copies of them
# shouldn't change their type.
original = (Identifier('x'), Component('x'))
copy = make_copy(original)
self.assertEqual(original[0], copy[0])
self.assertEqual(original[1], copy[1])
self.assertIsInstance(copy[0], Identifier)
self.assertIsInstance(copy[1], Component)
def test_object_identity(self):
# A diamond structure must be preserved when making a copy.
# /--> B --\
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment