[pypy-commit] pypy default: (fijal, reviewed by agaynor) Merge string-promote-2 branch. This branch lets
fijal
noreply at buildbot.pypy.org
Thu Oct 13 22:01:57 CEST 2011
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r48017:85ccfa8d2773
Date: 2011-10-13 22:01 +0200
http://bitbucket.org/pypy/pypy/changeset/85ccfa8d2773/
Log: (fijal, reviewed by agaynor) Merge string-promote-2 branch. This
branch lets you promote strings by value by using
jit.promote_string(s). It's used in typeobject for promoting getattr
on types.
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -455,6 +455,23 @@
# the special return value None forces op.result to be considered
# equal to op.args[0]
return [op0, op1, None]
+ if (hints.get('promote_string') and
+ op.args[0].concretetype is not lltype.Void):
+ S = lltype.Ptr(rstr.STR)
+ assert op.args[0].concretetype == S
+ self._register_extra_helper(EffectInfo.OS_STREQ_NONNULL,
+ "str.eq_nonnull",
+ [S, S],
+ lltype.Signed,
+ EffectInfo.EF_ELIDABLE_CANNOT_RAISE)
+ descr, p = self.callcontrol.callinfocollection.callinfo_for_oopspec(
+ EffectInfo.OS_STREQ_NONNULL)
+ # XXX this is fairly ugly way of creating a constant,
+ # however, callinfocollection has no better interface
+ c = Constant(p.adr.ptr, lltype.typeOf(p.adr.ptr))
+ op1 = SpaceOperation('str_guard_value', [op.args[0], c, descr],
+ op.result)
+ return [SpaceOperation('-live-', [], None), op1, None]
else:
log.WARNING('ignoring hint %r at %r' % (hints, self.graph))
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -99,6 +99,12 @@
if i == oopspecindex:
return True
return False
+ def callinfo_for_oopspec(self, oopspecindex):
+ assert oopspecindex == effectinfo.EffectInfo.OS_STREQ_NONNULL
+ class c:
+ class adr:
+ ptr = 1
+ return ('calldescr', c)
class FakeBuiltinCallControl:
def __init__(self):
@@ -119,6 +125,7 @@
EI.OS_STR2UNICODE:([PSTR], PUNICODE),
EI.OS_STR_CONCAT: ([PSTR, PSTR], PSTR),
EI.OS_STR_SLICE: ([PSTR, INT, INT], PSTR),
+ EI.OS_STREQ_NONNULL: ([PSTR, PSTR], INT),
EI.OS_UNI_CONCAT: ([PUNICODE, PUNICODE], PUNICODE),
EI.OS_UNI_SLICE: ([PUNICODE, INT, INT], PUNICODE),
EI.OS_UNI_EQUAL: ([PUNICODE, PUNICODE], lltype.Bool),
@@ -844,6 +851,21 @@
assert op1.args[2] == ListOfKind('ref', [v1, v2])
assert op1.result == v3
+def test_str_promote():
+ PSTR = lltype.Ptr(rstr.STR)
+ v1 = varoftype(PSTR)
+ v2 = varoftype(PSTR)
+ op = SpaceOperation('hint',
+ [v1, Constant({'promote_string': True}, lltype.Void)],
+ v2)
+ tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+ op0, op1, _ = tr.rewrite_operation(op)
+ assert op1.opname == 'str_guard_value'
+ assert op1.args[0] == v1
+ assert op1.args[2] == 'calldescr'
+ assert op1.result == v2
+ assert op0.opname == '-live-'
+
def test_unicode_concat():
# test that the oopspec is present and correctly transformed
PSTR = lltype.Ptr(rstr.UNICODE)
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -523,6 +523,9 @@
@arguments("f")
def bhimpl_float_guard_value(a):
pass
+ @arguments("r", "i", "d", returns="r")
+ def bhimpl_str_guard_value(a, i, d):
+ return a
@arguments("self", "i")
def bhimpl_int_push(self, a):
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
@@ -168,11 +168,12 @@
def make_result_of_lastop(self, resultbox):
got_type = resultbox.type
- if not we_are_translated():
- typeof = {'i': history.INT,
- 'r': history.REF,
- 'f': history.FLOAT}
- assert typeof[self.jitcode._resulttypes[self.pc]] == got_type
+ # XXX disabled for now, conflicts with str_guard_value
+ #if not we_are_translated():
+ # typeof = {'i': history.INT,
+ # 'r': history.REF,
+ # 'f': history.FLOAT}
+ # assert typeof[self.jitcode._resulttypes[self.pc]] == got_type
target_index = ord(self.bytecode[self.pc-1])
if got_type == history.INT:
self.registers_i[target_index] = resultbox
@@ -897,6 +898,21 @@
def _opimpl_guard_value(self, orgpc, box):
self.implement_guard_value(orgpc, box)
+ @arguments("orgpc", "box", "box", "descr")
+ def opimpl_str_guard_value(self, orgpc, box, funcbox, descr):
+ if isinstance(box, Const):
+ return box # no promotion needed, already a Const
+ else:
+ constbox = box.constbox()
+ resbox = self.do_residual_call(funcbox, descr, [box, constbox])
+ promoted_box = resbox.constbox()
+ # This is GUARD_VALUE because GUARD_TRUE assumes the existance
+ # of a label when computing resumepc
+ self.generate_guard(rop.GUARD_VALUE, resbox, [promoted_box],
+ resumepc=orgpc)
+ self.metainterp.replace_box(box, constbox)
+ return constbox
+
opimpl_int_guard_value = _opimpl_guard_value
opimpl_ref_guard_value = _opimpl_guard_value
opimpl_float_guard_value = _opimpl_guard_value
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
@@ -13,7 +13,7 @@
from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
loop_invariant, elidable, promote, jit_debug, assert_green,
AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
- isconstant, isvirtual)
+ isconstant, isvirtual, promote_string)
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rpython.ootypesystem import ootype
diff --git a/pypy/jit/metainterp/test/test_string.py b/pypy/jit/metainterp/test/test_string.py
--- a/pypy/jit/metainterp/test/test_string.py
+++ b/pypy/jit/metainterp/test/test_string.py
@@ -3,7 +3,8 @@
from pypy.jit.codewriter.policy import StopAtXPolicy
from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
from pypy.rlib.debug import debug_print
-from pypy.rlib.jit import JitDriver, dont_look_inside, we_are_jitted
+from pypy.rlib.jit import JitDriver, dont_look_inside, we_are_jitted,\
+ promote_string
from pypy.rlib.rstring import StringBuilder
from pypy.rpython.ootypesystem import ootype
@@ -507,6 +508,18 @@
'jump': 1, 'int_is_true': 1,
'guard_not_invalidated': 1})
+ def test_promote_string(self):
+ driver = JitDriver(greens = [], reds = ['n'])
+
+ def f(n):
+ while n < 21:
+ driver.jit_merge_point(n=n)
+ promote_string(str(n % 3))
+ n += 1
+ return 0
+
+ self.meta_interp(f, [0])
+ self.check_loops(call=3 + 1) # one for int2str
#class TestOOtype(StringTests, OOJitMixin):
# CALL = "oosend"
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -156,4 +156,41 @@
i40 = int_sub(i4, 1)
--TICK--
jump(p0, p1, p2, p3, i40, i38, descr=<Loop0>)
- """)
\ No newline at end of file
+ """)
+
+ def test_getattr_promote(self):
+ def main(n):
+ class A(object):
+ def meth_a(self):
+ return 1
+ def meth_b(self):
+ return 2
+ a = A()
+
+ l = ['a', 'b']
+ s = 0
+ for i in range(n):
+ name = 'meth_' + l[i & 1]
+ meth = getattr(a, name) # ID: getattr
+ s += meth()
+ return s
+
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loops = log.loops_by_filename(self.filepath)
+ assert len(loops) == 2
+ for loop in loops:
+ loop.match_by_id('getattr','''
+ guard_not_invalidated(descr=...)
+ i32 = strlen(p31)
+ i34 = int_add(5, i32)
+ p35 = newstr(i34)
+ strsetitem(p35, 0, 109)
+ strsetitem(p35, 1, 101)
+ strsetitem(p35, 2, 116)
+ strsetitem(p35, 3, 104)
+ strsetitem(p35, 4, 95)
+ copystrcontent(p31, p35, 0, 5, i32)
+ i49 = call(ConstClass(_ll_2_str_eq_nonnull__rpy_stringPtr_rpy_stringPtr), p35, ConstPtr(ptr48), descr=<SignedCallDescr>)
+ guard_value(i49, 1, descr=<Guard8>)
+ ''')
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -10,7 +10,8 @@
from pypy.objspace.std import identitydict
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.objectmodel import current_object_addr_as_int, compute_hash
-from pypy.rlib.jit import promote, elidable_promote, we_are_jitted
+from pypy.rlib.jit import promote, elidable_promote, we_are_jitted,\
+ promote_string
from pypy.rlib.jit import elidable, dont_look_inside, unroll_safe
from pypy.rlib.rarithmetic import intmask, r_uint
@@ -399,6 +400,7 @@
if version_tag is None:
tup = w_self._lookup_where(name)
return tup
+ name = promote_string(name)
w_class, w_value = w_self._pure_lookup_where_with_method_cache(name, version_tag)
return w_class, unwrap_cell(space, w_value)
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -38,6 +38,7 @@
possible arguments are:
* promote - promote the argument from a variable into a constant
+ * promote_string - same, but promote string by *value*
* access_directly - directly access a virtualizable, as a structure
and don't treat it as a virtualizable
* fresh_virtualizable - means that virtualizable was just allocated.
@@ -51,6 +52,9 @@
def promote(x):
return hint(x, promote=True)
+def promote_string(x):
+ return hint(x, promote_string=True)
+
def dont_look_inside(func):
""" Make sure the JIT does not trace inside decorated function
(it becomes a call instead)
More information about the pypy-commit
mailing list