Author: Maciej Fijalkowski <[email protected]>
Branch:
Changeset: r45415:70d9564fe923
Date: 2011-07-08 11:55 +0200
http://bitbucket.org/pypy/pypy/changeset/70d9564fe923/
Log: merge
diff --git a/lib_pypy/binascii.py b/lib_pypy/binascii.py
--- a/lib_pypy/binascii.py
+++ b/lib_pypy/binascii.py
@@ -659,7 +659,7 @@
crc = crc_32_tab[(crc ^ long(ord(c))) & 0xffL] ^ (crc >> 8)
#/* Note: (crc >> 8) MUST zero fill on left
- result = crc ^ 0xffffffffL
+ result = crc ^ 0xffffffffL
if result > 2**31:
result = ((result + 2**31) % 2**32) - 2**31
diff --git a/pypy/doc/interpreter-optimizations.rst
b/pypy/doc/interpreter-optimizations.rst
--- a/pypy/doc/interpreter-optimizations.rst
+++ b/pypy/doc/interpreter-optimizations.rst
@@ -263,34 +263,6 @@
You can enable this feature with the :config:`objspace.opcodes.CALL_METHOD`
option.
-.. _`call likely builtin`:
-
-CALL_LIKELY_BUILTIN
-+++++++++++++++++++
-
-A often heard "tip" for speeding up Python programs is to give an often used
-builtin a local name, since local lookups are faster than lookups of builtins,
-which involve doing two dictionary lookups: one in the globals dictionary and
-one in the the builtins dictionary. PyPy approaches this problem at the
-implementation level, with the introduction of the new ``CALL_LIKELY_BUILTIN``
-bytecode. This bytecode is produced by the compiler for a call whose target is
-the name of a builtin. Since such a syntactic construct is very often actually
-invoking the expected builtin at run-time, this information can be used to make
-the call to the builtin directly, without going through any dictionary lookup.
-
-However, it can occur that the name is shadowed by a global name from the
-current module. To catch this case, a special dictionary implementation for
-multidicts is introduced, which is used for the dictionaries of modules. This
-implementation keeps track which builtin name is shadowed by it. The
-``CALL_LIKELY_BUILTIN`` bytecode asks the dictionary whether it is shadowing
the
-builtin that is about to be called and asks the dictionary of ``__builtin__``
-whether the original builtin was changed. These two checks are cheaper than
-full lookups. In the common case, neither of these cases is true, so the
-builtin can be directly invoked.
-
-You can enable this feature with the
-:config:`objspace.opcodes.CALL_LIKELY_BUILTIN` option.
-
.. more here?
Overall Effects
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -310,26 +310,27 @@
self.opimpl_goto_if_not(condbox, target)
''' % (_opimpl, _opimpl.upper())).compile()
+
+ def _establish_nullity(self, box, orgpc):
+ value = box.nonnull()
+ if value:
+ if box not in self.metainterp.known_class_boxes:
+ self.generate_guard(rop.GUARD_NONNULL, box, resumepc=orgpc)
+ else:
+ if not isinstance(box, Const):
+ self.generate_guard(rop.GUARD_ISNULL, box, resumepc=orgpc)
+ promoted_box = box.constbox()
+ self.metainterp.replace_box(box, promoted_box)
+ return value
+
@arguments("orgpc", "box", "label")
def opimpl_goto_if_not_ptr_nonzero(self, orgpc, box, target):
- value = box.nonnull()
- if value:
- opnum = rop.GUARD_NONNULL
- else:
- opnum = rop.GUARD_ISNULL
- self.generate_guard(opnum, box, resumepc=orgpc)
- if not value:
+ if not self._establish_nullity(box, orgpc):
self.pc = target
@arguments("orgpc", "box", "label")
def opimpl_goto_if_not_ptr_iszero(self, orgpc, box, target):
- value = box.nonnull()
- if value:
- opnum = rop.GUARD_NONNULL
- else:
- opnum = rop.GUARD_ISNULL
- self.generate_guard(opnum, box, resumepc=orgpc)
- if value:
+ if self._establish_nullity(box, orgpc):
self.pc = target
@arguments("box", "box", "box")
@@ -364,7 +365,9 @@
def opimpl_new_with_vtable(self, sizedescr):
cpu = self.metainterp.cpu
cls = heaptracker.descr2vtable(cpu, sizedescr)
- return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
+ resbox = self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
+ self.metainterp.known_class_boxes[resbox] = None
+ return resbox
## @FixME #arguments("box")
## def opimpl_runtimenew(self, classbox):
@@ -845,7 +848,9 @@
@arguments("orgpc", "box")
def opimpl_guard_class(self, orgpc, box):
clsbox = self.cls_of_box(box)
- self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
+ if box not in self.metainterp.known_class_boxes:
+ self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
+ self.metainterp.known_class_boxes[box] = None
return clsbox
@arguments("int", "orgpc")
@@ -1449,6 +1454,8 @@
self.last_exc_value_box = None
self.retracing_loop_from = None
self.call_pure_results = args_dict_box()
+ # contains boxes where the class is already known
+ self.known_class_boxes = {}
def perform_call(self, jitcode, boxes, greenkey=None):
# causes the metainterp to enter the given subfunction
@@ -1789,6 +1796,8 @@
duplicates[box] = None
def reached_loop_header(self, greenboxes, redboxes, resumedescr):
+ self.known_class_boxes = {}
+
duplicates = {}
self.remove_consts_and_duplicates(redboxes, len(redboxes),
duplicates)
diff --git a/pypy/jit/metainterp/test/test_ajit.py
b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -1021,6 +1021,69 @@
res = self.meta_interp(main, [])
assert res == 55
+ def test_dont_record_repeated_guard_class(self):
+ class A:
+ pass
+ class B(A):
+ pass
+ a = A()
+ b = B()
+ def fn(n):
+ if n == -7:
+ obj = None
+ elif n:
+ obj = a
+ else:
+ obj = b
+ return isinstance(obj, B) + isinstance(obj, B) + isinstance(obj,
B) + isinstance(obj, B)
+ res = self.interp_operations(fn, [0])
+ assert res == 4
+ self.check_operations_history(guard_class=1, guard_nonnull=1)
+ res = self.interp_operations(fn, [1])
+ assert not res
+
+ def test_dont_record_guard_class_after_new(self):
+ class A:
+ pass
+ class B(A):
+ pass
+ def fn(n):
+ if n == -7:
+ obj = None
+ elif n:
+ obj = A()
+ else:
+ obj = B()
+ return isinstance(obj, B) + isinstance(obj, B) + isinstance(obj,
B) + isinstance(obj, B)
+ res = self.interp_operations(fn, [0])
+ assert res == 4
+ self.check_operations_history(guard_class=0, guard_nonnull=0)
+ res = self.interp_operations(fn, [1])
+ assert not res
+
+ def test_guard_isnull_nullifies(self):
+ class A:
+ pass
+ a = A()
+ a.x = None
+ def fn(n):
+ if n == -7:
+ a.x = ""
+ obj = a.x
+ res = 0
+ if not obj:
+ res += 1
+ if obj:
+ res += 1
+ if obj is None:
+ res += 1
+ if obj is not None:
+ res += 1
+ return res
+ res = self.interp_operations(fn, [0])
+ assert res == 2
+ self.check_operations_history(guard_isnull=1)
+
def test_assert_isinstance(self):
class A:
pass
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit