Author: Maciej Fijalkowski <fij...@gmail.com> 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 pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit