Author: Carl Friedrich Bolz <[email protected]>
Branch: int-tag-untag-as-operations
Changeset: r48364:300e42e0ee80
Date: 2011-10-22 14:13 +0200
http://bitbucket.org/pypy/pypy/changeset/300e42e0ee80/
Log: introduce int_tag (which can overflow) and int_untag
diff --git a/pypy/jit/backend/llgraph/llimpl.py
b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -692,6 +692,17 @@
if not flag:
raise GuardFailed
+ def op_int_tag(self, _, x):
+ try:
+ z = ovfcheck(x << 1) + 1
+ except OverflowError:
+ ovf = True
+ z = 0
+ else:
+ ovf = False
+ self.overflow_flag = ovf
+ return z
+
def op_int_add_ovf(self, _, x, y):
try:
z = ovfcheck(x + y)
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
@@ -269,6 +269,10 @@
op1 = SpaceOperation('-live-', [], None)
return [op, op1]
+ def rewrite_op_int_tag(self, op):
+ op1 = SpaceOperation('-live-', [], None)
+ return [op, op1]
+
# ----------
# Various kinds of calls
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -38,9 +38,10 @@
return a.typeannotation(t)
def annotate(func, values, inline=None, backendoptimize=True,
- type_system="lltype"):
+ type_system="lltype", taggedpointers=False):
# build the normal ll graphs for ll_function
t = TranslationContext()
+ t.config.translation.taggedpointers = taggedpointers
annpolicy = AnnotatorPolicy()
annpolicy.allow_someobjects = False
a = t.buildannotator(policy=annpolicy)
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
@@ -447,6 +447,14 @@
def bhimpl_int_invert(a):
return intmask(~a)
+ @arguments("i", returns="i")
+ def bhimpl_int_untag(a):
+ return a >> 1
+ @arguments("i", returns="i")
+ def bhimpl_int_tag(a):
+ return ovfcheck(a << 1) + 1
+
+
@arguments("i", "i", returns="i")
def bhimpl_int_lt(a, b):
return a < b
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -204,6 +204,18 @@
z = 0
return BoxInt(z)
+def do_int_tag(cpu, metainterp, box1):
+ # the overflow operations can be called without a metainterp, if an
+ # overflow cannot occur
+ a = box1.getint()
+ try:
+ z = ovfcheck(a << 1)
+ except OverflowError:
+ assert metainterp is not None
+ metainterp.execute_raised(OverflowError(), constant=True)
+ z = 0
+ return BoxInt(z + 1)
+
def do_same_as(cpu, _, box):
return box.clonebox()
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py
b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -284,6 +284,10 @@
else:
self.emit_operation(op)
+ def optimize_INT_TAG(self, op):
+ self.emit_operation(op) # XXX for now
+ self.emit_operation(self.nextop)
+
def optimize_ARRAYLEN_GC(self, op):
self.emit_operation(op)
array = self.getvalue(op.getarg(0))
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
@@ -218,7 +218,7 @@
return resbox
''' % (_opimpl, _opimpl.upper())).compile()
- for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert',
+ for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert',
'int_untag',
'cast_float_to_int', 'cast_int_to_float',
'cast_float_to_singlefloat', 'cast_singlefloat_to_float',
'float_neg', 'float_abs',
@@ -231,6 +231,15 @@
''' % (_opimpl, _opimpl.upper())).compile()
@arguments("box")
+ def opimpl_int_tag(self, b1):
+ self.metainterp.clear_exception()
+ resbox = self.execute(rop.INT_TAG, b1)
+ self.make_result_of_lastop(resbox)
+ if not isinstance(resbox, Const):
+ self.metainterp.handle_possible_overflow_error()
+ return resbox
+
+ @arguments("box")
def opimpl_ptr_nonzero(self, box):
return self.execute(rop.PTR_NE, box, history.CONST_NULL)
diff --git a/pypy/jit/metainterp/resoperation.py
b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -431,6 +431,7 @@
'INT_IS_TRUE/1b',
'INT_NEG/1',
'INT_INVERT/1',
+ 'INT_UNTAG/1',
#
'SAME_AS/1', # gets a Const or a Box, turns it into another Box
'CAST_PTR_TO_INT/1',
@@ -504,6 +505,7 @@
'INT_ADD_OVF/2',
'INT_SUB_OVF/2',
'INT_MUL_OVF/2',
+ 'INT_TAG/1',
'_OVF_LAST', # ----- end of is_ovf operations -----
'_LAST', # for the backend to add more internal operations
]
diff --git a/pypy/jit/metainterp/test/support.py
b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -42,7 +42,7 @@
enable_opts = ALL_OPTS_DICT
func._jit_unroll_safe_ = True
- rtyper = support.annotate(func, values, type_system=type_system)
+ rtyper = support.annotate(func, values, type_system=type_system, **kwds)
graphs = rtyper.annotator.translator.graphs
testself.all_graphs = graphs
result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
diff --git a/pypy/rlib/rerased.py b/pypy/rlib/rerased.py
--- a/pypy/rlib/rerased.py
+++ b/pypy/rlib/rerased.py
@@ -160,7 +160,7 @@
from pypy.rlib.debug import ll_assert
x = llop.cast_ptr_to_int(lltype.Signed, gcref)
ll_assert((x&1) != 0, "unerased_int(): not an integer")
- return x >> 1
+ return llop.int_untag(lltype.Signed, x)
class Entry(ExtRegistryEntry):
@@ -220,11 +220,9 @@
[v_value] = hop.inputargs(lltype.Signed)
c_one = hop.inputconst(lltype.Signed, 1)
hop.exception_is_here()
- v2 = hop.genop('int_add_ovf', [v_value, v_value],
+ v2 = hop.genop('int_tag', [v_value],
resulttype = lltype.Signed)
- v2p1 = hop.genop('int_add', [v2, c_one],
- resulttype = lltype.Signed)
- v_instance = hop.genop('cast_int_to_ptr', [v2p1],
+ v_instance = hop.genop('cast_int_to_ptr', [v2],
resulttype=self.lowleveltype)
return v_instance
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -1095,6 +1095,16 @@
assert y >= 0
return self.op_int_add_ovf(x, y)
+ def op_int_tag(self, x):
+ try:
+ return ovfcheck(x + x + 1)
+ except OverflowError:
+ self.make_llexception()
+
+ def op_int_untag(self, x):
+ assert x & 1, "argument has to be tagged!"
+ return x >> 1
+
def op_cast_float_to_int(self, f):
assert type(f) is float
try:
diff --git a/pypy/rpython/lltypesystem/lloperation.py
b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -207,6 +207,8 @@
'int_abs': LLOp(canfold=True),
'int_abs_ovf': LLOp(canraise=(OverflowError,), tryfold=True),
'int_invert': LLOp(canfold=True),
+ 'int_tag': LLOp(canraise=(OverflowError, ), tryfold=True),
+ 'int_untag': LLOp(canfold=True),
'int_add': LLOp(canfold=True),
'int_sub': LLOp(canfold=True),
diff --git a/pypy/translator/c/src/int.h b/pypy/translator/c/src/int.h
--- a/pypy/translator/c/src/int.h
+++ b/pypy/translator/c/src/int.h
@@ -19,6 +19,14 @@
if ((x) == LONG_MIN) FAIL_OVF("integer absolute"); \
OP_INT_ABS(x,r)
+#define OP_INT_TAG(x, r) \
+ r = (long)((unsigned long)x << 1); \
+ if ((r ^ x) < 0) FAIL_OVF("integer tagging"); \
+ r = r + 1
+
+#define OP_INT_UNTAG(x, r) \
+ r = x >> 1
+
/*** binary operations ***/
#define OP_INT_EQ(x,y,r) r = ((x) == (y))
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit