Author: Alex Gaynor <alex.gay...@gmail.com> Branch: Changeset: r45960:c3cdcacec880 Date: 2011-07-24 18:10 -0700 http://bitbucket.org/pypy/pypy/changeset/c3cdcacec880/
Log: merged upstream. diff --git a/pypy/rlib/rerased.py b/pypy/rlib/rerased.py --- a/pypy/rlib/rerased.py +++ b/pypy/rlib/rerased.py @@ -113,7 +113,7 @@ if hop.r_result.lowleveltype is lltype.Void: return hop.inputconst(lltype.Void, None) [v] = hop.inputargs(hop.args_r[0]) - return hop.genop('cast_opaque_ptr', [v], resulttype = hop.r_result) + return hop.args_r[0].rtype_unerase(hop, v) return erase, unerase @@ -147,7 +147,7 @@ def specialize_call(self, hop): [v] = hop.inputargs(hop.args_r[0]) assert isinstance(hop.s_result, annmodel.SomeInteger) - return hop.gendirectcall(ll_unerase_int, v) + return hop.args_r[0].rtype_unerase_int(hop, v) def ll_unerase_int(gcref): from pypy.rpython.lltypesystem.lloperation import llop @@ -174,7 +174,10 @@ return False # cannot be None, but can contain a None def rtyper_makerepr(self, rtyper): + if rtyper.type_system.name == 'lltypesystem': return ErasedRepr(rtyper) + elif rtyper.type_system.name == 'ootypesystem': + return OOErasedRepr(rtyper) def rtyper_makekey(self): return self.__class__, @@ -200,6 +203,13 @@ return hop.genop('cast_opaque_ptr', [v_obj], resulttype=self.lowleveltype) + def rtype_unerase(self, hop, s_obj): + [v] = hop.inputargs(hop.args_r[0]) + return hop.genop('cast_opaque_ptr', [v], resulttype=hop.r_result) + + def rtype_unerase_int(self, hop, v): + return hop.gendirectcall(ll_unerase_int, v) + def rtype_erase_int(self, hop): [v_value] = hop.inputargs(lltype.Signed) c_one = hop.inputconst(lltype.Signed, 1) @@ -224,3 +234,50 @@ return lltype.nullptr(self.lowleveltype.TO) v = r_obj.convert_const(value._x) return lltype.cast_opaque_ptr(self.lowleveltype, v) + +from pypy.rpython.ootypesystem import ootype + +class OOErasedRepr(Repr): + lowleveltype = ootype.Object + def __init__(self, rtyper): + self.rtyper = rtyper + + def rtype_erase(self, hop, s_obj): + hop.exception_cannot_occur() + r_obj = self.rtyper.getrepr(s_obj) + if r_obj.lowleveltype is lltype.Void: + return hop.inputconst(self.lowleveltype, + ootype.NULL) + [v_obj] = hop.inputargs(r_obj) + return hop.genop('cast_to_object', [v_obj], + resulttype=self.lowleveltype) + + def rtype_unerase(self, hop, s_obj): + [v] = hop.inputargs(hop.args_r[0]) + return hop.genop('cast_from_object', [v], resulttype=hop.r_result) + + def rtype_unerase_int(self, hop, v): + c_one = hop.inputconst(lltype.Signed, 1) + v2 = hop.genop('oounbox_int', [v], resulttype=hop.r_result) + return hop.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed) + + def rtype_erase_int(self, hop): + hop.exception_is_here() + [v_value] = hop.inputargs(lltype.Signed) + c_one = hop.inputconst(lltype.Signed, 1) + v2 = hop.genop('int_lshift_ovf', [v_value, c_one], + resulttype = lltype.Signed) + v2p1 = hop.genop('int_add', [v2, c_one], + resulttype = lltype.Signed) + return hop.genop('oobox_int', [v2p1], resulttype=hop.r_result) + + def convert_const(self, value): + if value._identity is _identity_for_ints: + return value._x # FIXME: what should we do here? + bk = self.rtyper.annotator.bookkeeper + s_obj = value._identity.get_input_annotation(bk) + r_obj = self.rtyper.getrepr(s_obj) + if r_obj.lowleveltype is lltype.Void: + return ootype.NULL + v = r_obj.convert_const(value._x) + return ootype.cast_to_object(v) diff --git a/pypy/rlib/test/test_rerased.py b/pypy/rlib/test/test_rerased.py --- a/pypy/rlib/test/test_rerased.py +++ b/pypy/rlib/test/test_rerased.py @@ -5,8 +5,10 @@ from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.lltypesystem.rclass import OBJECTPTR +from pypy.rpython.ootypesystem.rclass import OBJECT from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin class X(object): pass @@ -79,136 +81,6 @@ s = a.build_types(f, []) assert isinstance(s, annmodel.SomeInteger) -def test_rtype_1(): - def f(): - return eraseX(X()) - x = interpret(f, []) - assert lltype.typeOf(x) == llmemory.GCREF - -def test_rtype_2(): - def f(): - x1 = X() - e = eraseX(x1) - #assert not is_integer(e) - x2 = uneraseX(e) - return x2 - x = interpret(f, []) - assert lltype.castable(OBJECTPTR, lltype.typeOf(x)) > 0 - -def test_rtype_3(): - def f(): - e = erase_int(16) - #assert is_integer(e) - x2 = unerase_int(e) - return x2 - x = interpret(f, []) - assert x == 16 - - -def test_prebuilt_erased(): - e1 = erase_int(16) - x1 = X() - x1.foobar = 42 - e2 = eraseX(x1) - - def f(): - #assert is_integer(e1) - #assert not is_integer(e2) - x1.foobar += 1 - x2 = unerase_int(e1) + uneraseX(e2).foobar - return x2 - x = interpret(f, []) - assert x == 16 + 42 + 1 - -def test_prebuilt_erased_in_instance(): - erase_empty, unerase_empty = new_erasing_pair("empty") - class FakeList(object): - pass - - x1 = X() - x1.foobar = 42 - l1 = FakeList() - l1.storage = eraseX(x1) - l2 = FakeList() - l2.storage = erase_empty(None) - - def f(): - #assert is_integer(e1) - #assert not is_integer(e2) - x1.foobar += 1 - x2 = uneraseX(l1.storage).foobar + (unerase_empty(l2.storage) is None) - return x2 - x = interpret(f, []) - assert x == 43 + True - - -def test_overflow(): - def f(i): - try: - e = erase_int(i) - except OverflowError: - return -1 - #assert is_integer(e) - return unerase_int(e) - x = interpret(f, [16]) - assert x == 16 - x = interpret(f, [sys.maxint]) - assert x == -1 - -def test_none(): - def foo(): - return uneraseX(eraseX(None)) - assert foo() is None - res = interpret(foo, []) - assert not res - # - def foo(): - eraseX(X()) - return uneraseX(eraseX(None)) - assert foo() is None - res = interpret(foo, []) - assert not res - -def test_union(): - s_e1 = SomeErased() - s_e1.const = 1 - s_e2 = SomeErased() - s_e2.const = 3 - assert not annmodel.pair(s_e1, s_e2).union().is_constant() - - -def test_rtype_list(): - prebuilt_l = [X()] - prebuilt_e = erase_list_X(prebuilt_l) - def l(flag): - if flag == 1: - l = [X()] - e = erase_list_X(l) - elif flag == 2: - l = prebuilt_l - e = erase_list_X(l) - else: - l = prebuilt_l - e = prebuilt_e - #assert is_integer(e) is False - assert unerase_list_X(e) is l - interpret(l, [0]) - interpret(l, [1]) - interpret(l, [2]) - -# ____________________________________________________________ - -def test_erasing_pair(): - erase, unerase = new_erasing_pair("test1") - class X: - pass - x = X() - erased = erase(x) - assert unerase(erased) is x - # - erase2, unerase2 = new_erasing_pair("test2") - py.test.raises(AssertionError, unerase2, erased) - def test_annotate_erasing_pair(): erase, unerase = new_erasing_pair("test1") erase2, unerase2 = new_erasing_pair("test2") @@ -296,3 +168,148 @@ a = RPythonAnnotator() s = a.build_types(f, [int]) assert isinstance(s, annmodel.SomeInteger) + +class BaseTestRErased(BaseRtypingTest): + def test_rtype_1(self): + def f(): + return eraseX(X()) + x = self.interpret(f, []) + assert lltype.typeOf(x) == self.ERASED_TYPE + + def test_rtype_2(self): + def f(): + x1 = X() + e = eraseX(x1) + #assert not is_integer(e) + x2 = uneraseX(e) + return x2 + x = self.interpret(f, []) + assert self.castable(self.UNERASED_TYPE, x) + + def test_rtype_3(self): + def f(): + e = erase_int(16) + #assert is_integer(e) + x2 = unerase_int(e) + return x2 + x = self.interpret(f, []) + assert x == 16 + + def test_prebuilt_erased(self): + e1 = erase_int(16) + x1 = X() + x1.foobar = 42 + e2 = eraseX(x1) + + def f(): + #assert is_integer(e1) + #assert not is_integer(e2) + x1.foobar += 1 + x2 = unerase_int(e1) + uneraseX(e2).foobar + return x2 + x = self.interpret(f, []) + assert x == 16 + 42 + 1 + + def test_prebuilt_erased_in_instance(self): + erase_empty, unerase_empty = new_erasing_pair("empty") + class FakeList(object): + pass + + x1 = X() + x1.foobar = 42 + l1 = FakeList() + l1.storage = eraseX(x1) + l2 = FakeList() + l2.storage = erase_empty(None) + + def f(): + #assert is_integer(e1) + #assert not is_integer(e2) + x1.foobar += 1 + x2 = uneraseX(l1.storage).foobar + (unerase_empty(l2.storage) is None) + return x2 + x = self.interpret(f, []) + assert x == 43 + True + + def test_overflow(self): + def f(i): + try: + e = erase_int(i) + except OverflowError: + return -1 + #assert is_integer(e) + return unerase_int(e) + x = self.interpret(f, [16]) + assert x == 16 + x = self.interpret(f, [sys.maxint]) + assert x == -1 + + def test_none(self): + def foo(): + return uneraseX(eraseX(None)) + assert foo() is None + res = self.interpret(foo, []) + assert not res + # + def foo(): + eraseX(X()) + return uneraseX(eraseX(None)) + assert foo() is None + res = self.interpret(foo, []) + assert not res + + def test_rtype_list(self): + prebuilt_l = [X()] + prebuilt_e = erase_list_X(prebuilt_l) + def l(flag): + if flag == 1: + l = [X()] + e = erase_list_X(l) + elif flag == 2: + l = prebuilt_l + e = erase_list_X(l) + else: + l = prebuilt_l + e = prebuilt_e + #assert is_integer(e) is False + assert unerase_list_X(e) is l + self.interpret(l, [0]) + self.interpret(l, [1]) + self.interpret(l, [2]) + +class TestLLtype(BaseTestRErased, LLRtypeMixin): + ERASED_TYPE = llmemory.GCREF + UNERASED_TYPE = OBJECTPTR + def castable(self, TO, var): + return lltype.castable(TO, lltype.typeOf(var)) > 0 + +from pypy.rpython.ootypesystem.ootype import Object + +class TestOOtype(BaseTestRErased, OORtypeMixin): + ERASED_TYPE = Object + UNERASED_TYPE = OBJECT + def castable(self, TO, var): + return ootype.isSubclass(lltype.typeOf(var), TO) + @py.test.mark.xfail + def test_prebuilt_erased(self): + super(TestOOtype, self).test_prebuilt_erased() + +def test_union(): + s_e1 = SomeErased() + s_e1.const = 1 + s_e2 = SomeErased() + s_e2.const = 3 + assert not annmodel.pair(s_e1, s_e2).union().is_constant() + +# ____________________________________________________________ + +def test_erasing_pair(): + erase, unerase = new_erasing_pair("test1") + class X: + pass + x = X() + erased = erase(x) + assert unerase(erased) is x + # + erase2, unerase2 = new_erasing_pair("test2") + py.test.raises(AssertionError, unerase2, erased) diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py --- a/pypy/rpython/llinterp.py +++ b/pypy/rpython/llinterp.py @@ -1225,6 +1225,12 @@ except ValueError: self.make_llexception() + def op_oobox_int(self, i): + return ootype.oobox_int(i) + + def op_oounbox_int(self, x): + return ootype.oounbox_int(x) + class Tracer(object): Counter = 0 file = None 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 @@ -585,6 +585,8 @@ 'classof': LLOp(oo=True, canfold=True), 'subclassof': LLOp(oo=True, canfold=True), 'oostring': LLOp(oo=True, sideeffects=False), + 'oobox_int': LLOp(oo=True, sideeffects=False), + 'oounbox_int': LLOp(oo=True, sideeffects=False), 'ooparse_int': LLOp(oo=True, canraise=(ValueError,)), 'ooparse_float': LLOp(oo=True, canraise=(ValueError,)), 'oounicode': LLOp(oo=True, canraise=(UnicodeDecodeError,)), diff --git a/pypy/rpython/ootypesystem/ooopimpl.py b/pypy/rpython/ootypesystem/ooopimpl.py --- a/pypy/rpython/ootypesystem/ooopimpl.py +++ b/pypy/rpython/ootypesystem/ooopimpl.py @@ -3,7 +3,6 @@ # ____________________________________________________________ # Implementation of the 'canfold' oo operations - def op_ooupcast(INST, inst): return ootype.ooupcast(INST, inst) op_ooupcast.need_result_type = True diff --git a/pypy/rpython/ootypesystem/ootype.py b/pypy/rpython/ootypesystem/ootype.py --- a/pypy/rpython/ootypesystem/ootype.py +++ b/pypy/rpython/ootypesystem/ootype.py @@ -1938,6 +1938,17 @@ assert typeOf(obj) is Object return obj._cast_to(EXPECTED_TYPE) +class Box(_object): + def __init__(self, i): + self._TYPE = Object + self.i = i + +def oobox_int(i): + return Box(i) + +def oounbox_int(x): + return x.i + def oostring(obj, base): """ Convert char, int, float, instances and str to str. diff --git a/pypy/rpython/ootypesystem/rdict.py b/pypy/rpython/ootypesystem/rdict.py --- a/pypy/rpython/ootypesystem/rdict.py +++ b/pypy/rpython/ootypesystem/rdict.py @@ -255,7 +255,7 @@ methodname = None return fn, v_obj, methodname -def rtype_r_dict(hop): +def rtype_r_dict(hop, i_force_non_null=None): from pypy.rlib import jit r_dict = hop.r_result diff --git a/pypy/rpython/test/test_rint.py b/pypy/rpython/test/test_rint.py --- a/pypy/rpython/test/test_rint.py +++ b/pypy/rpython/test/test_rint.py @@ -8,6 +8,9 @@ from pypy.rlib import objectmodel from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem.lloperation import llop class TestSnippet(object): @@ -412,4 +415,8 @@ pass class TestOOtype(BaseTestRint, OORtypeMixin): - pass + def test_oobox_int(self): + def f(): + x = llop.oobox_int(ootype.Object, 42) + return llop.oounbox_int(lltype.Signed, x) + assert self.interpret(f, []) == 42 diff --git a/pypy/translator/cli/metavm.py b/pypy/translator/cli/metavm.py --- a/pypy/translator/cli/metavm.py +++ b/pypy/translator/cli/metavm.py @@ -1,6 +1,6 @@ from pypy.translator.cli import oopspec from pypy.rpython.ootypesystem import ootype -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype, rffi from pypy.translator.oosupport.metavm import Generator, InstructionList, MicroInstruction,\ PushAllArgs, StoreResult, GetField, SetField, DownCast from pypy.translator.oosupport.metavm import _Call as _OOCall @@ -173,6 +173,16 @@ generator.load(v_obj) generator.ilasm.opcode('unbox.any', boxtype) +class _UnboxType(MicroInstruction): + def __init__(self, TO): + self.TO = TO + + def render(self, generator, op): + v_obj, = op.args + boxtype = generator.cts.lltype_to_cts(self.TO) + generator.load(v_obj) + generator.ilasm.opcode('unbox.any', boxtype) + class _NewArray(MicroInstruction): def render(self, generator, op): v_type, v_length = op.args @@ -312,6 +322,7 @@ #CastWeakAdrToPtr = _CastWeakAdrToPtr() Box = _Box() Unbox = _Unbox() +UnboxInt = _UnboxType(lltype.Signed) NewArray = _NewArray() GetArrayElem = _GetArrayElem() SetArrayElem = _SetArrayElem() diff --git a/pypy/translator/cli/opcodes.py b/pypy/translator/cli/opcodes.py --- a/pypy/translator/cli/opcodes.py +++ b/pypy/translator/cli/opcodes.py @@ -2,7 +2,7 @@ IndirectCall, GetField, SetField, DownCast, NewCustomDict,\ MapException, Box, Unbox, NewArray, GetArrayElem, SetArrayElem,\ TypeOf, CastPrimitive, EventHandler, GetStaticField, SetStaticField, \ - DebugPrint + DebugPrint, UnboxInt from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\ New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode, OONewArray from pypy.translator.cli.cts import WEAKREF @@ -48,6 +48,8 @@ 'cast_from_object': [DownCast], 'clibox': [Box], 'cliunbox': [Unbox], + 'oobox_int': [Box], + 'oounbox_int': [UnboxInt], 'cli_newarray': [NewArray], 'cli_getelem': [GetArrayElem], 'cli_setelem': [SetArrayElem], @@ -92,6 +94,7 @@ 'debug_fatalerror': [PushAllArgs, 'call void [pypylib]pypy.runtime.Debug::DEBUG_FATALERROR(string)'], 'keepalive': Ignore, 'jit_marker': Ignore, + 'jit_force_quasi_immutable':Ignore, 'jit_force_virtualizable': Ignore, 'jit_force_virtual': DoNothing, } diff --git a/pypy/translator/cli/test/test_int.py b/pypy/translator/cli/test/test_int.py --- a/pypy/translator/cli/test/test_int.py +++ b/pypy/translator/cli/test/test_int.py @@ -1,8 +1,8 @@ import py from pypy.translator.cli.test.runtest import CliTest -from pypy.rpython.test.test_rint import BaseTestRint +from pypy.rpython.test.test_rint import TestOOtype as _TestOOtype # so py.test won't run the base test -class TestCliInt(CliTest, BaseTestRint): +class TestCliInt(CliTest, _TestOOtype): def test_char_constant(self): def dummyfn(i): return chr(i) diff --git a/pypy/translator/jvm/opcodes.py b/pypy/translator/jvm/opcodes.py --- a/pypy/translator/jvm/opcodes.py +++ b/pypy/translator/jvm/opcodes.py @@ -77,6 +77,8 @@ 'oosend': [JvmCallMethod, StoreResult], 'ooupcast': DoNothing, 'oodowncast': [DownCast, StoreResult], + 'oobox_int': jvm.PYPYBOXINT, + 'oounbox_int': jvm.PYPYUNBOXINT, 'cast_to_object': DoNothing, 'cast_from_object': [DownCast, StoreResult], 'instanceof': [CastTo, StoreResult], diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java --- a/pypy/translator/jvm/src/pypy/PyPy.java +++ b/pypy/translator/jvm/src/pypy/PyPy.java @@ -307,6 +307,14 @@ return result; } + public static Object box_integer(int x) { + return new Integer(x); + } + + public static int unbox_integer(Object o) { + Integer x = (Integer)o; + return x.intValue(); + } // Used in testing the JVM backend: // // A series of methods which serve a similar purpose to repr() in Python: diff --git a/pypy/translator/jvm/test/test_int.py b/pypy/translator/jvm/test/test_int.py --- a/pypy/translator/jvm/test/test_int.py +++ b/pypy/translator/jvm/test/test_int.py @@ -1,10 +1,11 @@ import py from pypy.translator.jvm.test.runtest import JvmTest from pypy.rpython.test.test_rint import BaseTestRint +from pypy.rpython.test.test_rint import TestOOtype as _TestOOtype # so py.test won't run the base test # ====> ../../../rpython/test/test_rint.py -class TestJvmInt(JvmTest, BaseTestRint): +class TestJvmInt(JvmTest, _TestOOtype): def test_char_constant(self): def dummyfn(i): return chr(i) diff --git a/pypy/translator/jvm/typesystem.py b/pypy/translator/jvm/typesystem.py --- a/pypy/translator/jvm/typesystem.py +++ b/pypy/translator/jvm/typesystem.py @@ -963,6 +963,8 @@ PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject) PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray) PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList) +PYPYBOXINT = Method.s(jPyPy, 'box_integer', (jInt,), jObject) +PYPYUNBOXINT = Method.s(jPyPy, 'unbox_integer', (jObject,), jInt) PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble) OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) CLASSGETNAME = Method.v(jClass, 'getName', (), jString) diff --git a/pypy/translator/oosupport/test_template/operations.py b/pypy/translator/oosupport/test_template/operations.py --- a/pypy/translator/oosupport/test_template/operations.py +++ b/pypy/translator/oosupport/test_template/operations.py @@ -1,3 +1,6 @@ +from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong, ovfcheck from pypy.rlib import rstack from pypy.annotation import model as annmodel _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit