[pypy-svn] r53330 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator/cli translator/cli/src translator/cli/test translator/js translator/jvm translator/jvm/src/pypy translator/jvm/test translator/oosupport
niko at codespeak.net
niko at codespeak.net
Fri Apr 4 15:10:31 CEST 2008
Author: niko
Date: Fri Apr 4 15:10:29 2008
New Revision: 53330
Added:
pypy/dist/pypy/translator/jvm/src/pypy/VoidArray.java
- copied unchanged from r53329, pypy/branch/fixed-list-ootype-2/pypy/translator/jvm/src/pypy/VoidArray.java
Modified:
pypy/dist/pypy/annotation/builtin.py
pypy/dist/pypy/rpython/llinterp.py
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/rpython/ootypesystem/ootype.py
pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
pypy/dist/pypy/rpython/ootypesystem/rdict.py
pypy/dist/pypy/rpython/ootypesystem/rlist.py
pypy/dist/pypy/rpython/ootypesystem/rstr.py
pypy/dist/pypy/rpython/ootypesystem/rtuple.py
pypy/dist/pypy/rpython/test/test_rlist.py
pypy/dist/pypy/rpython/test/tool.py
pypy/dist/pypy/translator/cli/constant.py
pypy/dist/pypy/translator/cli/cts.py
pypy/dist/pypy/translator/cli/entrypoint.py
pypy/dist/pypy/translator/cli/gencli.py
pypy/dist/pypy/translator/cli/ilgenerator.py
pypy/dist/pypy/translator/cli/metavm.py
pypy/dist/pypy/translator/cli/oopspec.py
pypy/dist/pypy/translator/cli/opcodes.py
pypy/dist/pypy/translator/cli/src/pypylib.cs
pypy/dist/pypy/translator/cli/test/test_list.py
pypy/dist/pypy/translator/js/asmgen.py
pypy/dist/pypy/translator/js/database.py
pypy/dist/pypy/translator/js/function.py
pypy/dist/pypy/translator/js/jsbuiltin.py
pypy/dist/pypy/translator/js/jts.py
pypy/dist/pypy/translator/js/opcodes.py
pypy/dist/pypy/translator/jvm/builtin.py
pypy/dist/pypy/translator/jvm/cmpopcodes.py
pypy/dist/pypy/translator/jvm/constant.py
pypy/dist/pypy/translator/jvm/database.py
pypy/dist/pypy/translator/jvm/generator.py
pypy/dist/pypy/translator/jvm/metavm.py
pypy/dist/pypy/translator/jvm/methods.py
pypy/dist/pypy/translator/jvm/node.py
pypy/dist/pypy/translator/jvm/opcodes.py
pypy/dist/pypy/translator/jvm/prebuiltnodes.py
pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java
pypy/dist/pypy/translator/jvm/test/test_class.py
pypy/dist/pypy/translator/jvm/test/test_list.py
pypy/dist/pypy/translator/jvm/typesystem.py
pypy/dist/pypy/translator/oosupport/constant.py
pypy/dist/pypy/translator/oosupport/genoo.py
pypy/dist/pypy/translator/oosupport/metavm.py
Log:
(niko, arigo and antocuni looking) merge fixed-list-ootype-2 branch to trunk,
introducing a different ootype type for lists that are not resized after
they are created.
Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py (original)
+++ pypy/dist/pypy/annotation/builtin.py Fri Apr 4 15:10:29 2008
@@ -516,6 +516,10 @@
r = SomeOOInstance(ootype.typeOf(i))
return r
+def oonewarray(s_type, length):
+ assert s_type.is_constant()
+ return SomeOOInstance(s_type.const)
+
def null(I_OR_SM):
assert I_OR_SM.is_constant()
null = ootype.null(I_OR_SM.const)
@@ -563,6 +567,7 @@
BUILTIN_ANALYZERS[ootype.instanceof] = instanceof
BUILTIN_ANALYZERS[ootype.new] = new
+BUILTIN_ANALYZERS[ootype.oonewarray] = oonewarray
BUILTIN_ANALYZERS[ootype.null] = null
BUILTIN_ANALYZERS[ootype.runtimenew] = runtimenew
BUILTIN_ANALYZERS[ootype.classof] = classof
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Fri Apr 4 15:10:29 2008
@@ -1035,6 +1035,11 @@
def op_new(self, INST):
assert isinstance(INST, (ootype.Instance, ootype.BuiltinType))
return ootype.new(INST)
+
+ def op_oonewarray(self, ARRAY, length):
+ assert isinstance(ARRAY, ootype.Array)
+ assert isinstance(length, int)
+ return ootype.oonewarray(ARRAY, length)
def op_runtimenew(self, class_):
return ootype.runtimenew(class_)
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Fri Apr 4 15:10:29 2008
@@ -465,6 +465,7 @@
'new': LLOp(oo=True, canraise=(Exception,)),
'runtimenew': LLOp(oo=True, canraise=(Exception,)),
'oonewcustomdict': LLOp(oo=True, canraise=(Exception,)),
+ 'oonewarray': LLOp(oo=True, canraise=(Exception,)),
'oosetfield': LLOp(oo=True),
'oogetfield': LLOp(oo=True, sideeffects=False),
'oosend': LLOp(oo=True, canraise=(Exception,)),
Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Fri Apr 4 15:10:29 2008
@@ -364,7 +364,7 @@
"ll_upper": Meth([], self.SELFTYPE_T),
"ll_lower": Meth([], self.SELFTYPE_T),
"ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count)
- "ll_split_chr": Meth([self.CHAR], List(self.SELFTYPE_T)),
+ "ll_split_chr": Meth([self.CHAR], Array(self.SELFTYPE_T)),
"ll_contains": Meth([self.CHAR], Bool),
"ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T),
})
@@ -464,7 +464,7 @@
ITEMTYPE_T = object()
def __init__(self, ITEMTYPE=None):
- self._ITEMTYPE = ITEMTYPE
+ self.ITEM = ITEMTYPE
self._null = _null_list(self)
if ITEMTYPE is not None:
self._init_methods()
@@ -475,13 +475,9 @@
# 'ITEMTYPE_T' is used as a placeholder for indicating
# arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self'
- # XXX clean-up later! Rename _ITEMTYPE to ITEM. For now they are
- # just synonyms, please use ITEM in new code.
- self.ITEM = self._ITEMTYPE
-
generic_types = {
self.SELFTYPE_T: self,
- self.ITEMTYPE_T: self._ITEMTYPE,
+ self.ITEMTYPE_T: self.ITEM,
}
# the methods are named after the ADT methods of lltypesystem's lists
@@ -514,7 +510,7 @@
return True
if not isinstance(other, List):
return False
- if self._ITEMTYPE is None or other._ITEMTYPE is None:
+ if self.ITEM is None or other.ITEM is None:
raise TypeError("Can't compare uninitialized List type.")
return BuiltinADTType.__eq__(self, other)
@@ -522,28 +518,114 @@
return not (self == other)
def __hash__(self):
- if self._ITEMTYPE is None:
+ if self.ITEM is None:
raise TypeError("Can't hash uninitialized List type.")
return BuiltinADTType.__hash__(self)
def __str__(self):
return '%s(%s)' % (self.__class__.__name__,
- saferecursive(str, "...")(self._ITEMTYPE))
+ saferecursive(str, "...")(self.ITEM))
def _get_interp_class(self):
return _list
def _specialize(self, generic_types):
- ITEMTYPE = self._specialize_type(self._ITEMTYPE, generic_types)
+ ITEMTYPE = self._specialize_type(self.ITEM, generic_types)
return self.__class__(ITEMTYPE)
def _defl(self):
return self._null
def _set_itemtype(self, ITEMTYPE):
- self._ITEMTYPE = ITEMTYPE
+ self.ITEM = ITEMTYPE
self._init_methods()
+ def ll_convert_from_array(self, array):
+ length = array.ll_length()
+ result = self.ll_newlist(length)
+ for n in range(length):
+ result.ll_setitem_fast(n, array.ll_getitem_fast(n))
+ return result
+
+class Array(BuiltinADTType):
+ # placeholders for types
+ # make sure that each derived class has his own SELFTYPE_T
+ # placeholder, because we want backends to distinguish that.
+
+ SELFTYPE_T = object()
+ ITEMTYPE_T = object()
+
+ def __init__(self, ITEMTYPE=None):
+ self.ITEM = ITEMTYPE
+ self._null = _null_array(self)
+ if ITEMTYPE is not None:
+ self._init_methods()
+
+ def _init_methods(self):
+ # This defines the abstract list interface that backends will
+ # have to map to their native list implementations.
+ # 'ITEMTYPE_T' is used as a placeholder for indicating
+ # arguments that should have ITEMTYPE type. 'SELFTYPE_T' indicates 'self'
+
+ generic_types = {
+ self.SELFTYPE_T: self,
+ self.ITEMTYPE_T: self.ITEM,
+ }
+
+ # the methods are named after the ADT methods of lltypesystem's lists
+ self._GENERIC_METHODS = frozendict({
+ # "name": Meth([ARGUMENT1_TYPE, ARGUMENT2_TYPE, ...], RESULT_TYPE)
+ "ll_length": Meth([], Signed),
+ "ll_getitem_fast": Meth([Signed], self.ITEMTYPE_T),
+ "ll_setitem_fast": Meth([Signed, self.ITEMTYPE_T], Void),
+ })
+
+ self._setup_methods(generic_types)
+
+ def __eq__(self, other):
+ if self is other:
+ return True
+ if not isinstance(other, Array):
+ return False
+ if self.ITEM is None or other.ITEM is None:
+ raise TypeError("Can't compare uninitialized List type.")
+ return BuiltinADTType.__eq__(self, other)
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __hash__(self):
+ if self.ITEM is None:
+ raise TypeError("Can't hash uninitialized List type.")
+ return BuiltinADTType.__hash__(self)
+
+ def __str__(self):
+ return '%s(%s)' % (self.__class__.__name__,
+ saferecursive(str, "...")(self.ITEM))
+
+ def _get_interp_class(self):
+ return _array
+
+ def _specialize(self, generic_types):
+ ITEMTYPE = self._specialize_type(self.ITEM, generic_types)
+ return self.__class__(ITEMTYPE)
+
+ def _defl(self):
+ return self._null
+
+ def _example(self):
+ return oonewarray(self, 1)
+
+ def _set_itemtype(self, ITEMTYPE):
+ self.ITEM = ITEMTYPE
+ self._init_methods()
+
+ def ll_newlist(self, length):
+ from pypy.rpython.ootypesystem import rlist
+ return rlist.ll_newarray(self, length)
+
+ def ll_convert_from_array(self, array):
+ return array
class Dict(BuiltinADTType):
# placeholders for types
@@ -1201,8 +1283,9 @@
def ll_split_chr(self, ch):
# NOT_RPYTHON
- res = _list(List(self._TYPE))
- res._list = [self.make_string(s) for s in self._str.split(ch)]
+ l = [self.make_string(s) for s in self._str.split(ch)]
+ res = _array(Array(self._TYPE), len(l))
+ res._array[:] = l
return res
def ll_contains(self, ch):
@@ -1278,6 +1361,8 @@
def __init__(self, WEAK_REFERENCE):
self.__dict__["_TYPE"] = WEAK_REFERENCE
+
+
class _list(_builtin_type):
def __init__(self, LIST):
self._TYPE = LIST
@@ -1295,7 +1380,7 @@
# NOT_RPYTHON
if len(self._list) < length:
diff = length - len(self._list)
- self._list += [self._TYPE._ITEMTYPE._defl()] * diff
+ self._list += [self._TYPE.ITEM._defl()] * diff
assert len(self._list) >= length
def _ll_resize_le(self, length):
@@ -1320,7 +1405,7 @@
def ll_setitem_fast(self, index, item):
# NOT_RPYTHON
- assert self._TYPE._ITEMTYPE is Void or typeOf(item) == self._TYPE._ITEMTYPE
+ assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM
assert typeOf(index) == Signed
assert index >= 0
self._list[index] = item
@@ -1330,6 +1415,33 @@
def __init__(self, LIST):
self.__dict__["_TYPE"] = LIST
+class _array(_builtin_type):
+ def __init__(self, ARRAY, length):
+ self._TYPE = ARRAY
+ self._array = [ARRAY.ITEM._defl()] * length
+
+ def ll_length(self):
+ # NOT_RPYTHON
+ return len(self._array)
+
+ def ll_getitem_fast(self, index):
+ # NOT_RPYTHON
+ assert typeOf(index) == Signed
+ assert index >= 0
+ return self._array[index]
+
+ def ll_setitem_fast(self, index, item):
+ # NOT_RPYTHON
+ assert self._TYPE.ITEM is Void or typeOf(item) == self._TYPE.ITEM
+ assert typeOf(index) == Signed
+ assert index >= 0
+ self._array[index] = item
+
+class _null_array(_null_mixin(_array), _array):
+
+ def __init__(self, ARRAY):
+ self.__dict__["_TYPE"] = ARRAY
+
class _dict(_builtin_type):
def __init__(self, DICT):
self._TYPE = DICT
@@ -1497,10 +1609,15 @@
return TYPE._get_interp_class()(TYPE)
def oonewcustomdict(DICT, ll_eq, ll_hash):
+ """NOT_RPYTHON"""
d = new(DICT)
d.ll_set_functions(ll_eq, ll_hash)
return d
+def oonewarray(ARRAY, length):
+ """NOT_RPYTHON"""
+ return _array(ARRAY, length)
+
def runtimenew(class_):
assert isinstance(class_, _class)
assert class_ is not nullruntimeclass
@@ -1626,7 +1743,7 @@
return LIST._set_itemtype(ITEMTYPE)
def hasItemType(LIST):
- return LIST._ITEMTYPE is not None
+ return LIST.ITEM is not None
def setDictTypes(DICT, KEYTYPE, VALUETYPE):
return DICT._set_types(KEYTYPE, VALUETYPE)
Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py Fri Apr 4 15:10:29 2008
@@ -12,6 +12,13 @@
return hop.genop('new', vlist,
resulttype = hop.r_result.lowleveltype)
+def rtype_oonewarray(hop):
+ assert hop.args_s[0].is_constant()
+ vlist = hop.inputarg(ootype.Void, arg=0)
+ vlength = hop.inputarg(ootype.Signed, arg=1)
+ return hop.genop('oonewarray', [vlist, vlength],
+ resulttype = hop.r_result.lowleveltype)
+
def rtype_null(hop):
assert hop.args_s[0].is_constant()
TYPE = hop.args_s[0].const
@@ -105,6 +112,7 @@
BUILTIN_TYPER = {}
BUILTIN_TYPER[ootype.new] = rtype_new
+BUILTIN_TYPER[ootype.oonewarray] = rtype_oonewarray
BUILTIN_TYPER[ootype.null] = rtype_null
BUILTIN_TYPER[ootype.classof] = rtype_classof
BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof
Modified: pypy/dist/pypy/rpython/ootypesystem/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rdict.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rdict.py Fri Apr 4 15:10:29 2008
@@ -323,7 +323,7 @@
def ll_dict_kvi(d, LIST, func):
length = d.ll_length()
- result = ll_newlist(LIST, length)
+ result = LIST.ll_newlist(length)
it = d.ll_get_items_iterator()
i = 0
while it.ll_go_next():
@@ -332,7 +332,7 @@
elif func is dum_values:
result.ll_setitem_fast(i, it.ll_current_value())
if func is dum_items:
- r = ootype.new(LIST._ITEMTYPE)
+ r = ootype.new(LIST.ITEM)
r.item0 = it.ll_current_key() # TODO: do we need casting?
r.item1 = it.ll_current_value()
result.ll_setitem_fast(i, r)
Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rlist.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rlist.py Fri Apr 4 15:10:29 2008
@@ -1,6 +1,6 @@
from pypy.tool.pairtype import pairtype
from pypy.rpython.rlist import AbstractBaseListRepr, AbstractListRepr, \
- AbstractListIteratorRepr, rtype_newlist, rtype_alloc_and_set
+ AbstractListIteratorRepr, AbstractFixedSizeListRepr, rtype_newlist, rtype_alloc_and_set
from pypy.rpython.rmodel import Repr, IntegerRepr
from pypy.rpython.rmodel import inputconst, externalvsinternal
from pypy.rpython.lltypesystem.lltype import Signed, Void
@@ -21,15 +21,12 @@
else:
self.external_item_repr, self.item_repr = \
externalvsinternal(rtyper, item_repr)
- self.LIST = ootype.List()
+ self.LIST = self._make_empty_type()
self.lowleveltype = self.LIST
self.listitem = listitem
self.list_cache = {}
# setup() needs to be called to finish this initialization
- def _externalvsinternal(self, rtyper, item_repr):
- return item_repr, item_repr
-
def _setup_repr(self):
if 'item_repr' not in self.__dict__:
self.external_item_repr, self.item_repr = \
@@ -37,13 +34,9 @@
if not ootype.hasItemType(self.lowleveltype):
ootype.setItemType(self.lowleveltype, self.item_repr.lowleveltype)
- def null_const(self):
- return self.LIST._null
-
- def prepare_const(self, n):
- result = self.LIST.ll_newlist(n)
- return result
-
+ def _externalvsinternal(self, rtyper, item_repr):
+ return item_repr, item_repr
+
def send_message(self, hop, message, can_raise=False, v_args=None):
if v_args is None:
v_args = hop.inputargs(self, *hop.args_r[1:])
@@ -56,9 +49,6 @@
def get_eqfunc(self):
return inputconst(Void, self.item_repr.get_ll_eq_function())
- def make_iterator_repr(self):
- return ListIteratorRepr(self)
-
def rtype_hint(self, hop):
hints = hop.args_s[-1].const
if 'maxlength' in hints:
@@ -71,10 +61,26 @@
class ListRepr(AbstractListRepr, BaseListRepr):
+ def null_const(self):
+ return self.LIST._null
+
+ def prepare_const(self, n):
+ result = self.LIST.ll_newlist(n)
+ return result
+
+ def make_iterator_repr(self):
+ return ListIteratorRepr(self)
- pass
+ def _make_empty_type(self):
+ return ootype.List()
-FixedSizeListRepr = ListRepr
+ def _generate_newlist(self, llops, items_v, v_sizehint):
+ c_list = inputconst(ootype.Void, self.lowleveltype)
+ v_result = llops.genop("new", [c_list], resulttype=self.lowleveltype)
+ c_resize = inputconst(ootype.Void, "_ll_resize")
+ c_length = inputconst(ootype.Signed, len(items_v))
+ llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void)
+ return v_result
class __extend__(pairtype(BaseListRepr, BaseListRepr)):
@@ -87,11 +93,7 @@
def newlist(llops, r_list, items_v, v_sizehint=None):
# XXX do something about v_sizehint
- c_list = inputconst(ootype.Void, r_list.lowleveltype)
- v_result = llops.genop("new", [c_list], resulttype=r_list.lowleveltype)
- c_resize = inputconst(ootype.Void, "_ll_resize")
- c_length = inputconst(ootype.Signed, len(items_v))
- llops.genop("oosend", [c_resize, v_result, c_length], resulttype=ootype.Void)
+ v_result = r_list._generate_newlist(llops, items_v, v_sizehint)
c_setitem = inputconst(ootype.Void, "ll_setitem_fast")
for i, v_item in enumerate(items_v):
@@ -104,6 +106,31 @@
lst._ll_resize(length)
return lst
+# Fixed-size list
+class FixedSizeListRepr(AbstractFixedSizeListRepr, BaseListRepr):
+ def compact_repr(self):
+ return 'FixedSizeListR %s' % (self.item_repr.compact_repr(),)
+
+ def _make_empty_type(self):
+ return ootype.Array()
+
+ def null_const(self):
+ return self.LIST._null
+
+ def prepare_const(self, n):
+ return ll_newarray(self.LIST, n)
+
+ def make_iterator_repr(self):
+ return ListIteratorRepr(self)
+
+ def _generate_newlist(self, llops, items_v, v_sizehint):
+ c_array = inputconst(ootype.Void, self.lowleveltype)
+ c_length = inputconst(ootype.Signed, len(items_v))
+ v_result = llops.genop("oonewarray", [c_array, c_length], resulttype=self.lowleveltype)
+ return v_result
+
+def ll_newarray(ARRAY, length):
+ return ootype.oonewarray(ARRAY, length)
# ____________________________________________________________
#
Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py Fri Apr 4 15:10:29 2008
@@ -170,7 +170,7 @@
return buf.ll_build()
def ll_join_chars(length_dummy, lst):
- if typeOf(lst)._ITEMTYPE == Char:
+ if typeOf(lst).ITEM == Char:
buf = ootype.new(ootype.StringBuilder)
else:
buf = ootype.new(ootype.UnicodeBuilder)
@@ -183,7 +183,7 @@
return buf.ll_build()
def ll_join_strs(length_dummy, lst):
- if typeOf(lst)._ITEMTYPE == ootype.String:
+ if typeOf(lst).ITEM == ootype.String:
buf = ootype.new(ootype.StringBuilder)
else:
buf = ootype.new(ootype.UnicodeBuilder)
@@ -209,8 +209,8 @@
def ll_stringslice_minusone(s):
return s.ll_substring(0, s.ll_strlen()-1)
- def ll_split_chr(LIST, s, c):
- return s.ll_split_chr(c)
+ def ll_split_chr(RESULT, s, c):
+ return RESULT.ll_convert_from_array(s.ll_split_chr(c))
def ll_int(s, base):
if not 2 <= base <= 36:
Modified: pypy/dist/pypy/rpython/ootypesystem/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rtuple.py (original)
+++ pypy/dist/pypy/rpython/ootypesystem/rtuple.py Fri Apr 4 15:10:29 2008
@@ -36,13 +36,19 @@
def rtype_bltn_list(self, hop):
from pypy.rpython.ootypesystem import rlist
v_tup = hop.inputarg(self, 0)
- LIST = hop.r_result.lowleveltype
- c_list = inputconst(ootype.Void, LIST)
- v_list = hop.genop('new', [c_list], resulttype=LIST)
- c_resize = inputconst(ootype.Void, '_ll_resize')
- c_setitem = inputconst(ootype.Void, 'll_setitem_fast')
+ RESULT = hop.r_result.lowleveltype
+ c_resulttype = inputconst(ootype.Void, RESULT)
c_length = inputconst(ootype.Signed, len(self.items_r))
- hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void)
+ if isinstance(RESULT, ootype.Array):
+ v_list = hop.genop('oonewarray', [c_resulttype, c_length], resulttype=RESULT)
+ else:
+ assert isinstance(RESULT, ootype.List)
+ v_list = hop.genop('new', [c_resulttype], resulttype=RESULT)
+ c_resize = inputconst(ootype.Void, '_ll_resize')
+ hop.genop('oosend', [c_resize, v_list, c_length], resulttype=ootype.Void)
+
+ c_setitem = inputconst(ootype.Void, 'll_setitem_fast')
+
for index in range(len(self.items_r)):
name = self.fieldnames[index]
r_item = self.items_r[index]
@@ -51,6 +57,7 @@
v_item = hop.llops.convertvar(v_item, r_item, hop.r_result.item_repr)
c_index = inputconst(ootype.Signed, index)
hop.genop('oosend', [c_setitem, v_list, c_index, v_item], resulttype=ootype.Void)
+
return v_list
Modified: pypy/dist/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rlist.py (original)
+++ pypy/dist/pypy/rpython/test/test_rlist.py Fri Apr 4 15:10:29 2008
@@ -498,7 +498,6 @@
assert self.class_name(res) == 'A'
#''.join(res.super.typeptr.name) == 'A\00'
-
def test_reverse(self):
def dummyfn():
l = [5, 3, 2]
@@ -517,15 +516,15 @@
assert res == 235
def test_prebuilt_list(self):
- klist = ['a', 'd', 'z', 'k']
+ klist = [6, 7, 8, 9]
def dummyfn(n):
return klist[n]
res = self.interpret(dummyfn, [0])
- assert res == 'a'
+ assert res == 6
res = self.interpret(dummyfn, [3])
- assert res == 'k'
+ assert res == 9
res = self.interpret(dummyfn, [-2])
- assert res == 'z'
+ assert res == 8
klist = ['a', 'd', 'z']
def mkdummyfn():
Modified: pypy/dist/pypy/rpython/test/tool.py
==============================================================================
--- pypy/dist/pypy/rpython/test/tool.py (original)
+++ pypy/dist/pypy/rpython/test/tool.py Fri Apr 4 15:10:29 2008
@@ -107,7 +107,9 @@
return OOSupport.to_runicode(u)
def ll_to_list(self, l):
- return l._list[:]
+ if hasattr(l, '_list'):
+ return l._list[:]
+ return l._array[:]
def ll_unpack_tuple(self, t, length):
return tuple([getattr(t, 'item%d' % i) for i in range(length)])
Modified: pypy/dist/pypy/translator/cli/constant.py
==============================================================================
--- pypy/dist/pypy/translator/cli/constant.py (original)
+++ pypy/dist/pypy/translator/cli/constant.py Fri Apr 4 15:10:29 2008
@@ -28,7 +28,7 @@
from pypy.translator.oosupport.constant import \
push_constant, WeakRefConst, StaticMethodConst, CustomDictConst, \
ListConst, ClassConst, InstanceConst, RecordConst, DictConst, \
- BaseConstantGenerator, AbstractConst
+ BaseConstantGenerator, AbstractConst, ArrayConst
from pypy.translator.cli.ilgenerator import CLIBaseGenerator
from pypy.rpython.ootypesystem import ootype
from pypy.translator.cli.comparer import EqualityComparer
@@ -373,9 +373,25 @@
def create_pointer(self, gen):
self.db.const_count.inc('List')
- self.db.const_count.inc('List', self.value._TYPE._ITEMTYPE)
+ self.db.const_count.inc('List', self.value._TYPE.ITEM)
self.db.const_count.inc('List', len(self.value._list))
- super(CLIListConst, self).create_pointer(gen)
+ super(CLIListConst, self).create_pointer(gen)
+
+
+class CLIArrayConst(CLIBaseConstMixin, ArrayConst):
+
+ def _do_not_initialize(self):
+ # Check if it is an array of all zeroes:
+ try:
+ if self.value._list == [0] * len(self.value._list):
+ return True
+ except:
+ pass
+ return super(CLIArrayConst, self)._do_not_initialize()
+
+ def _setitem(self, SELFTYPE, gen):
+ gen.array_setitem(SELFTYPE)
+
class CLIDictConst(CLIDictMixin, DictConst):
def create_pointer(self, gen):
Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py (original)
+++ pypy/dist/pypy/translator/cli/cts.py Fri Apr 4 15:10:29 2008
@@ -95,6 +95,14 @@
arglist = ', '.join([arg.typename() for arg in self.arg_types])
return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist)
+class CliArrayType(CliType):
+
+ def __init__(self, itemtype):
+ self.itemtype = itemtype
+
+ def typename(self):
+ return '%s[]' % self.itemtype.typename()
+
T = CliPrimitiveType
class types:
@@ -249,8 +257,13 @@
elif isinstance(t, ootype.StaticMethod):
delegate = self.db.record_delegate(t)
return CliClassType(None, delegate)
+ elif isinstance(t, ootype.Array):
+ item_type = self.lltype_to_cts(t.ITEM)
+ if item_type == types.void: # special case: Array of Void
+ return types.list_of_void
+ return CliArrayType(item_type)
elif isinstance(t, ootype.List):
- item_type = self.lltype_to_cts(t._ITEMTYPE)
+ item_type = self.lltype_to_cts(t.ITEM)
if item_type == types.void: # special case: List of Void
return types.list_of_void
return types.list.specialize(item_type)
Modified: pypy/dist/pypy/translator/cli/entrypoint.py
==============================================================================
--- pypy/dist/pypy/translator/cli/entrypoint.py (original)
+++ pypy/dist/pypy/translator/cli/entrypoint.py Fri Apr 4 15:10:29 2008
@@ -9,7 +9,7 @@
ARG0 = graph.getargs()[0].concretetype
except IndexError:
ARG0 = None
- if isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String:
+ if isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String:
return StandaloneEntryPoint(graph)
else:
return TestEntryPoint(graph)
@@ -45,7 +45,7 @@
ARG0 = self.graph.getargs()[0].concretetype
except IndexError:
ARG0 = None
- assert isinstance(ARG0, ootype.List) and ARG0._ITEMTYPE is ootype.String,\
+ assert isinstance(ARG0, ootype.List) and ARG0.ITEM is ootype.String,\
'Wrong entry point signature: List(String) expected'
ilasm.begin_function('main', [('string[]', 'argv')], 'void', True, 'static')
Modified: pypy/dist/pypy/translator/cli/gencli.py
==============================================================================
--- pypy/dist/pypy/translator/cli/gencli.py (original)
+++ pypy/dist/pypy/translator/cli/gencli.py Fri Apr 4 15:10:29 2008
@@ -31,6 +31,7 @@
RecordConst = constant.CLIRecordConst
ClassConst = constant.CLIClassConst
ListConst = constant.CLIListConst
+ ArrayConst = constant.CLIArrayConst
StaticMethodConst = constant.CLIStaticMethodConst
CustomDictConst = constant.CLICustomDictConst
DictConst = constant.CLIDictConst
Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py (original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py Fri Apr 4 15:10:29 2008
@@ -417,3 +417,31 @@
def dup(self, TYPE):
self.ilasm.opcode('dup')
+
+ def oonewarray(self, TYPE, length):
+ if TYPE.ITEM is ootype.Void:
+ self.new(TYPE)
+ self.ilasm.opcode('dup')
+ self.load(length)
+ self.ilasm.call_method('void [pypylib]pypy.runtime.ListOfVoid::_ll_resize(int32)', virtual=False)
+ else:
+ clitype = self.cts.lltype_to_cts(TYPE)
+ self.load(length)
+ self.ilasm.opcode('newarr', clitype.itemtype.typename())
+
+ def _array_suffix(self, ARRAY, erase_unsigned=False):
+ from pypy.translator.cli.metavm import OOTYPE_TO_MNEMONIC
+ suffix = OOTYPE_TO_MNEMONIC.get(ARRAY.ITEM, 'ref')
+ if erase_unsigned:
+ suffix = suffix.replace('u', 'i')
+ return suffix
+
+ def array_setitem(self, ARRAY):
+ suffix = self._array_suffix(ARRAY, erase_unsigned=True)
+ self.ilasm.opcode('stelem.%s' % suffix)
+
+ def array_getitem(self, ARRAY):
+ self.ilasm.opcode('ldelem.%s' % self._array_suffix(ARRAY))
+
+ def array_length(self, ARRAY):
+ self.ilasm.opcode('ldlen')
Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py (original)
+++ pypy/dist/pypy/translator/cli/metavm.py Fri Apr 4 15:10:29 2008
@@ -68,6 +68,17 @@
arg_list = ', '.join(arg_types)
signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list)
generator.call_signature(signature)
+ elif isinstance(this.concretetype, ootype.Array) and this.concretetype.ITEM is not ootype.Void:
+ v_array = args[0]
+ ARRAY = v_array.concretetype
+ if method_name == 'll_setitem_fast':
+ generator.array_setitem(ARRAY)
+ elif method_name == 'll_getitem_fast':
+ generator.array_getitem(ARRAY)
+ elif method_name == 'll_length':
+ generator.array_length(ARRAY)
+ else:
+ assert False
else:
generator.call_method(this.concretetype, method_name)
@@ -251,10 +262,14 @@
OOTYPE_TO_MNEMONIC = {
+ ootype.Bool: 'i1',
+ ootype.Char: 'i2',
+ ootype.UniChar: 'i2',
ootype.Signed: 'i4',
ootype.SignedLongLong: 'i8',
ootype.Unsigned: 'u4',
ootype.UnsignedLongLong: 'u8',
+ ootype.Float: 'r8',
}
class _CastPrimitive(MicroInstruction):
Modified: pypy/dist/pypy/translator/cli/oopspec.py
==============================================================================
--- pypy/dist/pypy/translator/cli/oopspec.py (original)
+++ pypy/dist/pypy/translator/cli/oopspec.py Fri Apr 4 15:10:29 2008
@@ -31,9 +31,9 @@
def get_method(TYPE, name):
try:
- # special case: when having List of Void, look at the concrete
- # methods, not the generic ones
- if isinstance(TYPE, ootype.List) and TYPE._ITEMTYPE is ootype.Void:
+ # special case: when having List of Void, or an Array, look at
+ # the concrete methods, not the generic ones
+ if isinstance(TYPE, ootype.Array) or (isinstance(TYPE, ootype.List) and TYPE.ITEM is ootype.Void):
return TYPE._METHODS[name]
else:
return TYPE._GENERIC_METHODS[name]
Modified: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/cli/opcodes.py (original)
+++ pypy/dist/pypy/translator/cli/opcodes.py Fri Apr 4 15:10:29 2008
@@ -4,7 +4,7 @@
TypeOf, CastPrimitive, EventHandler, GetStaticField, SetStaticField,\
FieldInfoForConst
from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\
- New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode
+ New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode, OONewArray
from pypy.translator.cli.cts import WEAKREF
from pypy.rpython.ootypesystem import ootype
@@ -58,6 +58,7 @@
'ooparse_int': [PushAllArgs, 'call int32 [pypylib]pypy.runtime.Utils::OOParseInt(string, int32)'],
'ooparse_float': [PushAllArgs, 'call float64 [pypylib]pypy.runtime.Utils::OOParseFloat(string)'],
'oonewcustomdict': [NewCustomDict],
+ 'oonewarray': [OONewArray, StoreResult],
'hint': [PushArg(0), StoreResult],
'direct_call': [Call],
Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs
==============================================================================
--- pypy/dist/pypy/translator/cli/src/pypylib.cs (original)
+++ pypy/dist/pypy/translator/cli/src/pypylib.cs Fri Apr 4 15:10:29 2008
@@ -35,10 +35,28 @@
public static string ToPython(object x) {
if (x == null)
return "None";
+ else if (x is Array)
+ return ArrayToPython((Array)x);
else
return x.ToString();
}
+ private static string ArrayToPython(Array array)
+ {
+ string res = "[";
+ foreach(object item in array) {
+ if (item != null && item.GetType() == typeof(string)) {
+ object tmp = (object)item;
+ res += ToPython((string)tmp) + ",";
+ }
+ else
+ res += ToPython(item) + ",";
+
+ }
+ res += "]";
+ return res;
+ }
+
public static string InstanceToPython(object obj)
{
return string.Format("InstanceWrapper('{0}')", obj.GetType().FullName);
@@ -373,11 +391,9 @@
return s.Substring(start, count);
}
- public static List<string> ll_split_chr(string s, char ch)
+ public static string[] ll_split_chr(string s, char ch)
{
- List<string> res = new List<string>();
- res.AddRange(s.Split(ch));
- return res;
+ return s.Split(ch);
}
public static bool ll_contains(string s, char ch)
@@ -417,7 +433,7 @@
res += pypy.test.Result.ToPython((string)tmp) + ",";
}
else
- res += item.ToString() + ","; // XXX: doesn't work for chars
+ res += pypy.test.Result.ToPython(item) + ",";
}
res += "]";
return res;
Modified: pypy/dist/pypy/translator/cli/test/test_list.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_list.py (original)
+++ pypy/dist/pypy/translator/cli/test/test_list.py Fri Apr 4 15:10:29 2008
@@ -1,6 +1,7 @@
import py
from pypy.translator.cli.test.runtest import CliTest
from pypy.rpython.test.test_rlist import BaseTestRlist
+from pypy.rlib.rarithmetic import r_uint
class TestCliList(CliTest, BaseTestRlist):
def test_recursive(self):
@@ -8,3 +9,19 @@
def test_getitem_exc(self):
py.test.skip('fixme!')
+
+ def test_list_unsigned(self):
+ def fn(x):
+ lst = [r_uint(0), r_uint(1)]
+ lst[0] = r_uint(x)
+ return lst[0]
+ res = self.interpret(fn, [42])
+ assert res == 42
+
+ def test_list_bool(self):
+ def fn(x):
+ lst = [True, False]
+ lst[0] = x
+ return lst[0]
+ res = self.interpret(fn, [False])
+ assert res == False
Modified: pypy/dist/pypy/translator/js/asmgen.py
==============================================================================
--- pypy/dist/pypy/translator/js/asmgen.py (original)
+++ pypy/dist/pypy/translator/js/asmgen.py Fri Apr 4 15:10:29 2008
@@ -219,6 +219,9 @@
def runtimenew(self):
self.right_hand.append("new %s()" % self.right_hand.pop())
+ def oonewarray(self, obj, length):
+ self.right_hand.append("new %s(%s)" % (obj, length))
+
def load_self(self):
self.right_hand.append("this")
Modified: pypy/dist/pypy/translator/js/database.py
==============================================================================
--- pypy/dist/pypy/translator/js/database.py (original)
+++ pypy/dist/pypy/translator/js/database.py Fri Apr 4 15:10:29 2008
@@ -227,6 +227,8 @@
return InstanceConst(db, const, static_type)
elif isinstance(const, ootype._list):
return ListConst(db, const)
+ elif isinstance(const, ootype._array):
+ return ListConst(db, const)
elif isinstance(const, ootype._record):
return RecordConst(db, const)
elif isinstance(const, ootype._string):
@@ -355,6 +357,13 @@
class ListConst(AbstractConst):
+ def _get_list(self):
+ if isinstance(self.const, ootype._list):
+ return self.const._list
+ else:
+ return self.const._array
+
+
def get_name(self):
return "const_list"
@@ -368,7 +377,7 @@
if not self.const:
return
- for i in self.const._list:
+ for i in self._get_list():
name = self.db.record_const(i, None, 'const')
if name is not None:
self.depends.add(name)
@@ -381,9 +390,10 @@
if not self.const:
return
- for i in xrange(len(self.const._list)):
+ l = self._get_list()
+ for i in xrange(len(l)):
ilasm.load_str("%s.%s"%(const_var.name, name))
- el = self.const._list[i]
+ el = l[i]
self.db.load_const(typeOf(el), el, ilasm)
self.db.load_const(typeOf(i), i, ilasm)
ilasm.list_setitem()
Modified: pypy/dist/pypy/translator/js/function.py
==============================================================================
--- pypy/dist/pypy/translator/js/function.py (original)
+++ pypy/dist/pypy/translator/js/function.py Fri Apr 4 15:10:29 2008
@@ -73,6 +73,9 @@
def new(self, obj):
self.ilasm.new(self.cts.obj_name(obj))
+ def oonewarray(self, obj, length):
+ self.ilasm.oonewarray(self.cts.obj_name(obj), length)
+
def set_field(self, obj, name):
self.ilasm.set_field(obj, name)
#self.ilasm.set_field(self.field_name(obj,name))
Modified: pypy/dist/pypy/translator/js/jsbuiltin.py
==============================================================================
--- pypy/dist/pypy/translator/js/jsbuiltin.py (original)
+++ pypy/dist/pypy/translator/js/jsbuiltin.py Fri Apr 4 15:10:29 2008
@@ -59,6 +59,11 @@
'_ll_resize_le' : list_resize,
'll_length' : _GetPredefinedField('length'),
},
+ ootype.Array: {
+ 'll_setitem_fast' : ListSetitem,
+ 'll_getitem_fast' : ListGetitem,
+ 'll_length' : _GetPredefinedField('length'),
+ },
ootype.Dict: {
'll_get' : ListGetitem,
'll_set' : ListSetitem,
Modified: pypy/dist/pypy/translator/js/jts.py
==============================================================================
--- pypy/dist/pypy/translator/js/jts.py (original)
+++ pypy/dist/pypy/translator/js/jts.py Fri Apr 4 15:10:29 2008
@@ -43,6 +43,8 @@
return self.escape_name(t._name)
elif isinstance(t, ootype.List):
return "Array"
+ elif isinstance(t, ootype.Array):
+ return "Array"
elif isinstance(t, lltype.Primitive):
return "var"
elif isinstance(t, ootype.Record):
@@ -135,7 +137,7 @@
## elif isinstance(t, ootype.StaticMethod):
## return 'void' # TODO: is it correct to ignore StaticMethod?
## elif isinstance(t, ootype.List):
-## item_type = self.lltype_to_cts(t._ITEMTYPE)
+## item_type = self.lltype_to_cts(t.ITEM)
## return self.__class(PYPY_LIST % item_type, include_class)
## elif isinstance(t, ootype.Dict):
## key_type = self.lltype_to_cts(t._KEYTYPE)
Modified: pypy/dist/pypy/translator/js/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/js/opcodes.py (original)
+++ pypy/dist/pypy/translator/js/opcodes.py Fri Apr 4 15:10:29 2008
@@ -2,7 +2,8 @@
"""
from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult,\
- InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive
+ InstructionList, New, GetField, MicroInstruction, RuntimeNew, PushPrimitive,\
+ OONewArray
from pypy.translator.oosupport.metavm import _GetFieldDispatcher, _SetFieldDispatcher, \
_CallDispatcher, _MethodDispatcher, SetField
@@ -119,6 +120,7 @@
'indirect_call' : [IndirectCall],
'same_as' : CopyName,
'new' : [New],
+ 'oonewarray' : [OONewArray],
'runtimenew' : [RuntimeNew],
'instanceof' : [IsInstance],
#'subclassof' : [IsSubclassOf],
Modified: pypy/dist/pypy/translator/jvm/builtin.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/builtin.py (original)
+++ pypy/dist/pypy/translator/jvm/builtin.py Fri Apr 4 15:10:29 2008
@@ -1,5 +1,4 @@
-from pypy.translator.jvm import typesystem as jvmtype
-from pypy.translator.jvm import generator as jvmgen
+import pypy.translator.jvm.typesystem as jvm
from pypy.rpython.ootypesystem import ootype
from pypy.translator.jvm.typesystem import \
jInt, jVoid, jStringBuilder, jString, jPyPy, jChar, jArrayList, jObject, \
@@ -9,7 +8,7 @@
# ______________________________________________________________________
# Mapping of built-in OOTypes to JVM types
-class JvmBuiltInType(jvmtype.JvmClassType):
+class JvmBuiltInType(jvm.JvmClassType):
"""
Represents built-in types to JVM. May optionally be associated
@@ -18,7 +17,7 @@
"""
def __init__(self, db, classty, OOTYPE):
- jvmtype.JvmClassType.__init__(self, classty.name)
+ jvm.JvmClassType.__init__(self, classty.name)
self.db = db
self.OOTYPE = OOTYPE
self.gen = Generifier(OOTYPE)
@@ -30,14 +29,14 @@
return hash(self.name)
def lookup_field(self, fieldnm):
- """ Given a field name, returns a jvmgen.Field object """
+ """ Given a field name, returns a jvm.Field object """
_, FIELDTY = self.OOTYPE._lookup_field(fieldnm)
jfieldty = self.db.lltype_to_cts(FIELDTY)
- return jvmgen.Field(
+ return jvm.Field(
self.descriptor.class_name(), fieldnm, jfieldty, False)
def lookup_method(self, methodnm):
- """ Given the method name, returns a jvmgen.Method object """
+ """ Given the method name, returns a jvm.Method object """
# Look for a shortcut method in our table of remappings:
try:
@@ -56,14 +55,14 @@
if self.OOTYPE.__class__ in bridged_objects:
# Bridged objects are ones where we have written a java class
# that has methods with the correct names and types already
- return jvmgen.Method.v(self, methodnm, jargtypes, jrettype)
+ return jvm.Method.v(self, methodnm, jargtypes, jrettype)
else:
# By default, we assume it is a static method on the PyPy
# object, that takes an instance of this object as the first
# argument. The other arguments we just convert to java versions,
# except for generics.
jargtypes = [self] + jargtypes
- return jvmgen.Method.s(jPyPy, methodnm, jargtypes, jrettype)
+ return jvm.Method.s(jPyPy, methodnm, jargtypes, jrettype)
# When we lookup a method on a BuiltInClassNode, we first check the
# 'built_in_methods' and 'bridged_objects' tables. This allows us to
@@ -80,73 +79,73 @@
# .__class__ is required
(ootype.StringBuilder.__class__, "ll_allocate"):
- jvmgen.Method.v(jStringBuilder, "ensureCapacity", (jInt,), jVoid),
+ jvm.Method.v(jStringBuilder, "ensureCapacity", (jInt,), jVoid),
(ootype.StringBuilder.__class__, "ll_build"):
- jvmgen.Method.v(jStringBuilder, "toString", (), jString),
+ jvm.Method.v(jStringBuilder, "toString", (), jString),
(ootype.String.__class__, "ll_streq"):
- jvmgen.Method.v(jString, "equals", (jObject,), jBool),
+ jvm.Method.v(jString, "equals", (jObject,), jBool),
(ootype.String.__class__, "ll_strlen"):
- jvmgen.Method.v(jString, "length", (), jInt),
+ jvm.Method.v(jString, "length", (), jInt),
(ootype.String.__class__, "ll_stritem_nonneg"):
- jvmgen.Method.v(jString, "charAt", (jInt,), jChar),
+ jvm.Method.v(jString, "charAt", (jInt,), jChar),
(ootype.String.__class__, "ll_startswith"):
- jvmgen.Method.v(jString, "startsWith", (jString,), jBool),
+ jvm.Method.v(jString, "startsWith", (jString,), jBool),
(ootype.String.__class__, "ll_endswith"):
- jvmgen.Method.v(jString, "endsWith", (jString,), jBool),
+ jvm.Method.v(jString, "endsWith", (jString,), jBool),
(ootype.String.__class__, "ll_strcmp"):
- jvmgen.Method.v(jString, "compareTo", (jString,), jInt),
+ jvm.Method.v(jString, "compareTo", (jString,), jInt),
(ootype.String.__class__, "ll_upper"):
- jvmgen.Method.v(jString, "toUpperCase", (), jString),
+ jvm.Method.v(jString, "toUpperCase", (), jString),
(ootype.String.__class__, "ll_lower"):
- jvmgen.Method.v(jString, "toLowerCase", (), jString),
+ jvm.Method.v(jString, "toLowerCase", (), jString),
(ootype.String.__class__, "ll_replace_chr_chr"):
- jvmgen.Method.v(jString, "replace", (jChar, jChar), jString),
+ jvm.Method.v(jString, "replace", (jChar, jChar), jString),
(ootype.Dict, "ll_set"):
- jvmgen.Method.v(jHashMap, "put", (jObject, jObject), jObject),
+ jvm.Method.v(jHashMap, "put", (jObject, jObject), jObject),
(ootype.Dict, "ll_get"):
- jvmgen.Method.v(jHashMap, "get", (jObject,), jObject),
+ jvm.Method.v(jHashMap, "get", (jObject,), jObject),
(ootype.Dict, "ll_contains"):
- jvmgen.Method.v(jHashMap, "containsKey", (jObject,), jBool),
+ jvm.Method.v(jHashMap, "containsKey", (jObject,), jBool),
(ootype.Dict, "ll_length"):
- jvmgen.Method.v(jHashMap, "size", (), jInt),
+ jvm.Method.v(jHashMap, "size", (), jInt),
(ootype.Dict, "ll_clear"):
- jvmgen.Method.v(jHashMap, "clear", (), jVoid),
+ jvm.Method.v(jHashMap, "clear", (), jVoid),
(ootype.CustomDict, "ll_set"):
- jvmgen.Method.v(jPyPyCustomDict, "put", (jObject, jObject), jObject),
+ jvm.Method.v(jPyPyCustomDict, "put", (jObject, jObject), jObject),
(ootype.CustomDict, "ll_get"):
- jvmgen.Method.v(jPyPyCustomDict, "get", (jObject,), jObject),
+ jvm.Method.v(jPyPyCustomDict, "get", (jObject,), jObject),
(ootype.CustomDict, "ll_contains"):
- jvmgen.Method.v(jPyPyCustomDict, "containsKey", (jObject,), jBool),
+ jvm.Method.v(jPyPyCustomDict, "containsKey", (jObject,), jBool),
(ootype.CustomDict, "ll_length"):
- jvmgen.Method.v(jPyPyCustomDict, "size", (), jInt),
+ jvm.Method.v(jPyPyCustomDict, "size", (), jInt),
(ootype.CustomDict, "ll_clear"):
- jvmgen.Method.v(jPyPyCustomDict, "clear", (), jVoid),
+ jvm.Method.v(jPyPyCustomDict, "clear", (), jVoid),
(ootype.List, "ll_length"):
- jvmgen.Method.v(jArrayList, "size", (), jInt),
+ jvm.Method.v(jArrayList, "size", (), jInt),
(ootype.List, "ll_getitem_fast"):
- jvmgen.Method.v(jArrayList, "get", (jInt,), jObject),
+ jvm.Method.v(jArrayList, "get", (jInt,), jObject),
}
Modified: pypy/dist/pypy/translator/jvm/cmpopcodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/cmpopcodes.py (original)
+++ pypy/dist/pypy/translator/jvm/cmpopcodes.py Fri Apr 4 15:10:29 2008
@@ -1,9 +1,11 @@
-from pypy.translator.jvm.generator import \
+from pypy.translator.jvm.typesystem import \
IFLT, IFLE, IFEQ, IFNE, IFGT, IFGE, \
IFNONNULL, IF_ACMPEQ, GOTO, ICONST, \
DCONST_0, DCMPG, LCONST_0, LCMP, \
IF_ICMPLT, IF_ICMPLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPGT, IF_ICMPGE, \
- PYPYUINTCMP, PYPYULONGCMP, \
+ PYPYUINTCMP, PYPYULONGCMP
+
+from pypy.translator.jvm.generator import \
Label
##### Branch directly as the result of a comparison
Modified: pypy/dist/pypy/translator/jvm/constant.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/constant.py (original)
+++ pypy/dist/pypy/translator/jvm/constant.py Fri Apr 4 15:10:29 2008
@@ -1,15 +1,14 @@
from pypy.rpython.ootypesystem import ootype
from pypy.objspace.flow import model as flowmodel
-from pypy.translator.jvm.generator import \
- Field, Method, CUSTOMDICTMAKE
+import pypy.translator.jvm.typesystem as jvm
+from pypy.translator.jvm.typesystem import \
+ jVoid, Method, Field
from pypy.translator.oosupport.constant import \
BaseConstantGenerator, RecordConst, InstanceConst, ClassConst, \
StaticMethodConst, CustomDictConst, WeakRefConst, push_constant, \
MAX_CONST_PER_STEP
-from pypy.translator.jvm.typesystem import \
- jObject, jVoid, jPyPyWeakRef, JvmClassType
-jPyPyConstantInit = JvmClassType('pypy.ConstantInit')
+jPyPyConstantInit = jvm.JvmClassType('pypy.ConstantInit')
jPyPyConstantInitMethod = Method.s(jPyPyConstantInit, 'init', [], jVoid)
# ___________________________________________________________________________
@@ -51,7 +50,7 @@
# This prevents any one class from getting too big.
if (self.num_constants % MAX_CONST_PER_STEP) == 0:
cc_num = len(self.ccs)
- self.ccs.append(JvmClassType('pypy.Constant_%d' % cc_num))
+ self.ccs.append(jvm.JvmClassType('pypy.Constant_%d' % cc_num))
self.num_constants += 1
const.fieldobj = Field(self.ccs[-1].name, const.name, jfieldty, True)
@@ -99,7 +98,7 @@
except KeyError:
constants_by_cls[const.fieldobj.class_name] = [const]
for cc in self.ccs:
- ilasm.begin_class(cc, jObject)
+ ilasm.begin_class(cc, jvm.jObject)
for const in constants_by_cls[cc.name]:
ilasm.add_field(const.fieldobj)
ilasm.end_class()
@@ -122,8 +121,9 @@
self._push_constant_during_init(gen, const)
def _declare_step(self, gen, stepnum):
- self.step_classes.append(JvmClassType('pypy.ConstantInit_%d' % stepnum))
- gen.begin_class(self.step_classes[-1], jObject)
+ self.step_classes.append(jvm.JvmClassType(
+ 'pypy.ConstantInit_%d' % stepnum))
+ gen.begin_class(self.step_classes[-1], jvm.jObject)
gen.begin_function('constant_init', [], [], jVoid, True)
def _close_step(self, gen, stepnum):
@@ -132,7 +132,7 @@
gen.end_class() # end pypy.ConstantInit_NNN
def _end_gen_constants(self, gen, numsteps):
- gen.begin_class(jPyPyConstantInit, jObject)
+ gen.begin_class(jPyPyConstantInit, jvm.jObject)
gen.begin_j_function(jPyPyConstantInit, jPyPyConstantInitMethod)
for cls in self.step_classes:
m = Method.s(cls, "constant_init", [], jVoid)
@@ -156,7 +156,7 @@
if self.delegate_impl:
gen.new_with_jtype(self.delegate_impl)
else:
- gen.push_null(jObject)
+ gen.push_null(jvm.jObject)
def initialize_data(self, constgen, gen):
return
@@ -180,7 +180,7 @@
def create_pointer(self, gen):
gen.new_with_jtype(self.eq_jcls)
gen.new_with_jtype(self.hash_jcls)
- gen.emit(CUSTOMDICTMAKE)
+ gen.emit(jvm.CUSTOMDICTMAKE)
class JVMWeakRefConst(WeakRefConst):
@@ -188,7 +188,7 @@
PRIORITY = 200
def jtype(self):
- return jPyPyWeakRef
+ return jvm.jPyPyWeakRef
def create_pointer(self, gen):
if not self.value:
Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py (original)
+++ pypy/dist/pypy/translator/jvm/database.py Fri Apr 4 15:10:29 2008
@@ -7,21 +7,15 @@
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype, rclass
from pypy.rpython.ootypesystem.module import ll_os
-from pypy.translator.jvm import typesystem as jvmtype
from pypy.translator.jvm import node, methods
from pypy.translator.jvm.option import getoption
-import pypy.translator.jvm.generator as jvmgen
-from pypy.translator.jvm.generator import Method, Property, Field
-import pypy.translator.jvm.constant as jvmconst
-from pypy.translator.jvm.typesystem import \
- jStringBuilder, jInt, jVoid, jString, jChar, jObject, \
- jThrowable, JvmNativeClass, jPyPy, JvmClassType
from pypy.translator.jvm.builtin import JvmBuiltInType
-
from pypy.translator.oosupport.database import Database as OODatabase
from pypy.rpython.ootypesystem.bltregistry import ExternalType
from pypy.annotation.signature import annotation
from pypy.annotation.model import annotation_to_lltype
+import pypy.translator.jvm.constant as jvmconst
+import pypy.translator.jvm.typesystem as jvm
# ______________________________________________________________________
# Database object
@@ -34,7 +28,7 @@
self._jasmin_files = [] # list of strings --- .j files we made
self._classes = {} # Maps ootype class objects to node.Class objects,
# and JvmType objects as well
- self._functions = {} # graph -> jvmgen.Method
+ self._functions = {} # graph -> jvm.Method
# (jargtypes, jrettype) -> node.StaticMethodInterface
self._delegates = {}
@@ -44,7 +38,7 @@
self._function_names = {} # graph --> function_name
- self._constants = {} # flowmodel.Variable --> jvmgen.Const
+ self._constants = {} # flowmodel.Variable --> jvm.Const
# Special fields for the Object class, see _translate_Object
self._object_interf = None
@@ -65,11 +59,11 @@
#
# These are public attributes that are referenced from
# elsewhere in the code using
- # jvmgen.Generator.push_interlink() and .push_pypy().
- self.jPyPyMain = JvmClassType(self._pkg('Main'))
- self.pypy_field = jvmgen.Field.s(self.jPyPyMain, 'pypy', jPyPy)
- self.interlink_field = jvmgen.Field.s(self.jPyPyMain, 'ilink',
- jvmtype.jPyPyInterlink)
+ # jvm.Generator.push_interlink() and .push_pypy().
+ self.jPyPyMain = jvm.JvmClassType(self._pkg('Main'))
+ self.pypy_field = jvm.Field.s(self.jPyPyMain, 'pypy', jvm.jPyPy)
+ self.interlink_field = jvm.Field.s(self.jPyPyMain, 'ilink',
+ jvm.jPyPyInterlink)
# _________________________________________________________________
# Java String vs Byte Array
@@ -93,7 +87,7 @@
def class_name(self, TYPE):
jtype = self.lltype_to_cts(TYPE)
- assert isinstance(jtype, jvmtype.JvmClassType)
+ assert isinstance(jtype, jvm.JvmClassType)
return jtype.name
def add_jasmin_file(self, jfile):
@@ -120,14 +114,14 @@
like.
The 'methods' argument should be a dictionary whose keys are
- method names and whose entries are jvmgen.Method objects which
+ method names and whose entries are jvm.Method objects which
the corresponding method should invoke. """
nm = self._pkg(self._uniq('InterlinkImplementation'))
- cls = node.Class(nm, supercls=jObject)
+ cls = node.Class(nm, supercls=jvm.jObject)
for method_name, helper in methods.items():
cls.add_method(node.InterlinkFunction(cls, method_name, helper))
- cls.add_interface(jvmtype.jPyPyInterlink)
+ cls.add_interface(jvm.jPyPyInterlink)
self.jInterlinkImplementation = cls
self.pending_node(cls)
@@ -169,7 +163,7 @@
# Create the class object first
clsnm = self._pkg(self._uniq('Record'))
- clsobj = node.Class(clsnm, jObject)
+ clsobj = node.Class(clsnm, jvm.jObject)
self._classes[OOTYPE] = clsobj
# Add fields:
@@ -205,8 +199,8 @@
def gen_name(): return self._pkg(self._uniq(OBJ._name))
internm, implnm, exc_implnm = gen_name(), gen_name(), gen_name()
self._object_interf = node.Interface(internm)
- self._object_impl = node.Class(implnm, supercls=jObject)
- self._object_exc_impl = node.Class(exc_implnm, supercls=jThrowable)
+ self._object_impl = node.Class(implnm, supercls=jvm.jObject)
+ self._object_exc_impl = node.Class(exc_implnm, supercls=jvm.jThrowable)
self._object_impl.add_interface(self._object_interf)
self._object_exc_impl.add_interface(self._object_interf)
@@ -220,12 +214,12 @@
methodnm = "_jvm_"+fieldnm
def getter_method_obj(node):
- return Method.v(node, methodnm+"_g", [], fieldty)
+ return jvm.Method.v(node, methodnm+"_g", [], fieldty)
def putter_method_obj(node):
- return Method.v(node, methodnm+"_p", [fieldty], jVoid)
+ return jvm.Method.v(node, methodnm+"_p", [fieldty], jvm.jVoid)
# Add get/put methods to the interface:
- prop = Property(
+ prop = jvm.Property(
fieldnm,
getter_method_obj(self._object_interf),
putter_method_obj(self._object_interf),
@@ -235,7 +229,7 @@
# Generate implementations:
def generate_impl(clsobj):
clsnm = clsobj.name
- fieldobj = Field(clsnm, fieldnm, fieldty, False, FIELDOOTY)
+ fieldobj = jvm.Field(clsnm, fieldnm, fieldty, False, FIELDOOTY)
clsobj.add_field(fieldobj, fielddef)
clsobj.add_method(node.GetterFunction(
self, clsobj, getter_method_obj(clsobj), fieldobj))
@@ -296,7 +290,7 @@
arglist = [self.lltype_to_cts(ARG) for ARG in METH.ARGS
if ARG is not ootype.Void]
returntype = self.lltype_to_cts(METH.RESULT)
- clsobj.add_abstract_method(jvmgen.Method.v(
+ clsobj.add_abstract_method(jvm.Method.v(
clsobj, mname, arglist, returntype))
else:
# if the first argument's type is not a supertype of
@@ -323,7 +317,7 @@
if FIELDOOTY is ootype.Void: continue
fieldty = self.lltype_to_cts(FIELDOOTY)
clsobj.add_field(
- jvmgen.Field(clsobj.name, fieldnm, fieldty, False, FIELDOOTY),
+ jvm.Field(clsobj.name, fieldnm, fieldty, False, FIELDOOTY),
fielddef)
def pending_class(self, OOTYPE):
@@ -334,7 +328,7 @@
This is invoked when a standalone function is to be compiled.
It creates a class named after the function with a single
method, invoke(). This class is added to the worklist.
- Returns a jvmgen.Method object that allows this function to be
+ Returns a jvm.Method object that allows this function to be
invoked.
"""
if graph in self._functions:
@@ -366,7 +360,7 @@
"""
Like record_delegate, but the signature is in terms of java
types. jargs is a list of JvmTypes, one for each argument,
- and jret is a JvmType. Note that jargs does NOT include an
+ and jret is a Jvm. Note that jargs does NOT include an
entry for the this pointer of the resulting object.
"""
key = (jargs, jret)
@@ -424,17 +418,17 @@
# any type.
_toString_methods = {
- ootype.Signed:jvmgen.INTTOSTRINGI,
- ootype.Unsigned:jvmgen.PYPYSERIALIZEUINT,
- ootype.SignedLongLong:jvmgen.LONGTOSTRINGL,
- ootype.UnsignedLongLong: jvmgen.PYPYSERIALIZEULONG,
- ootype.Float:jvmgen.DOUBLETOSTRINGD,
- ootype.Bool:jvmgen.PYPYSERIALIZEBOOLEAN,
- ootype.Void:jvmgen.PYPYSERIALIZEVOID,
- ootype.Char:jvmgen.PYPYESCAPEDCHAR,
- ootype.UniChar:jvmgen.PYPYESCAPEDUNICHAR,
- ootype.String:jvmgen.PYPYESCAPEDSTRING,
- ootype.Unicode:jvmgen.PYPYESCAPEDUNICODE,
+ ootype.Signed:jvm.INTTOSTRINGI,
+ ootype.Unsigned:jvm.PYPYSERIALIZEUINT,
+ ootype.SignedLongLong:jvm.LONGTOSTRINGL,
+ ootype.UnsignedLongLong: jvm.PYPYSERIALIZEULONG,
+ ootype.Float:jvm.DOUBLETOSTRINGD,
+ ootype.Bool:jvm.PYPYSERIALIZEBOOLEAN,
+ ootype.Void:jvm.PYPYSERIALIZEVOID,
+ ootype.Char:jvm.PYPYESCAPEDCHAR,
+ ootype.UniChar:jvm.PYPYESCAPEDUNICHAR,
+ ootype.String:jvm.PYPYESCAPEDSTRING,
+ ootype.Unicode:jvm.PYPYESCAPEDUNICODE,
}
def toString_method_for_ootype(self, OOTYPE):
@@ -451,7 +445,7 @@
to print the value of 'var'.
"""
- return self._toString_methods.get(OOTYPE, jvmgen.PYPYSERIALIZEOBJECT)
+ return self._toString_methods.get(OOTYPE, jvm.PYPYSERIALIZEOBJECT)
# _________________________________________________________________
# Type translation functions
@@ -471,46 +465,51 @@
# Dictionary for scalar types; in this case, if we see the key, we
# will return the value
ootype_to_scalar = {
- ootype.Void: jvmtype.jVoid,
- ootype.Signed: jvmtype.jInt,
- ootype.Unsigned: jvmtype.jInt,
- ootype.SignedLongLong: jvmtype.jLong,
- ootype.UnsignedLongLong: jvmtype.jLong,
- ootype.Bool: jvmtype.jBool,
- ootype.Float: jvmtype.jDouble,
- ootype.Char: jvmtype.jChar, # byte would be sufficient, but harder
- ootype.UniChar: jvmtype.jChar,
- ootype.Class: jvmtype.jClass,
- ootype.ROOT: jvmtype.jObject, # treat like a scalar
+ ootype.Void: jvm.jVoid,
+ ootype.Signed: jvm.jInt,
+ ootype.Unsigned: jvm.jInt,
+ ootype.SignedLongLong: jvm.jLong,
+ ootype.UnsignedLongLong: jvm.jLong,
+ ootype.Bool: jvm.jBool,
+ ootype.Float: jvm.jDouble,
+ ootype.Char: jvm.jChar, # byte would be sufficient, but harder
+ ootype.UniChar: jvm.jChar,
+ ootype.Class: jvm.jClass,
+ ootype.ROOT: jvm.jObject, # treat like a scalar
}
# Dictionary for non-scalar types; in this case, if we see the key, we
# will return a JvmBuiltInType based on the value
ootype_to_builtin = {
- ootype.String: jvmtype.jString,
- ootype.Unicode: jvmtype.jString,
- ootype.StringBuilder: jvmtype.jStringBuilder,
- ootype.UnicodeBuilder: jvmtype.jStringBuilder,
- ootype.List: jvmtype.jArrayList,
- ootype.Dict: jvmtype.jHashMap,
- ootype.DictItemsIterator:jvmtype.jPyPyDictItemsIterator,
- ootype.CustomDict: jvmtype.jPyPyCustomDict,
- ootype.WeakReference: jvmtype.jPyPyWeakRef,
- ll_os.STAT_RESULT: jvmtype.jPyPyStatResult,
+ ootype.String: jvm.jString,
+ ootype.Unicode: jvm.jString,
+ ootype.StringBuilder: jvm.jStringBuilder,
+ ootype.UnicodeBuilder: jvm.jStringBuilder,
+ ootype.List: jvm.jArrayList,
+ ootype.Dict: jvm.jHashMap,
+ ootype.DictItemsIterator:jvm.jPyPyDictItemsIterator,
+ ootype.CustomDict: jvm.jPyPyCustomDict,
+ ootype.WeakReference: jvm.jPyPyWeakRef,
+ ll_os.STAT_RESULT: jvm.jPyPyStatResult,
# These are some configured records that are generated by Java
# code.
#ootype.Record({"item0": ootype.Signed, "item1": ootype.Signed}):
- #jvmtype.jPyPyRecordSignedSigned,
+ #jvm.jPyPyRecordSignedSigned,
#ootype.Record({"item0": ootype.Float, "item1": ootype.Signed}):
- #jvmtype.jPyPyRecordFloatSigned,
+ #jvm.jPyPyRecordFloatSigned,
#ootype.Record({"item0": ootype.Float, "item1": ootype.Float}):
- #jvmtype.jPyPyRecordFloatFloat,
+ #jvm.jPyPyRecordFloatFloat,
#ootype.Record({"item0": ootype.String, "item1": ootype.String}):
- #jvmtype.jPyPyRecordStringString,
+ #jvm.jPyPyRecordStringString,
}
def lltype_to_cts(self, OOT):
+ import sys
+ res = self._lltype_to_cts(OOT)
+ return res
+
+ def _lltype_to_cts(self, OOT):
""" Returns an instance of JvmType corresponding to
the given OOType """
@@ -519,9 +518,11 @@
return self.ootype_to_scalar[OOT]
if (isinstance(OOT, lltype.Ptr) and
isinstance(OOT.TO, lltype.OpaqueType)):
- return jObject
+ return jvm.jObject
if OOT in self.ootype_to_builtin:
return JvmBuiltInType(self, self.ootype_to_builtin[OOT], OOT)
+ if isinstance(OOT, ootype.Array):
+ return self._array_type(OOT.ITEM)
if OOT.__class__ in self.ootype_to_builtin:
return JvmBuiltInType(
self, self.ootype_to_builtin[OOT.__class__], OOT)
@@ -538,10 +539,26 @@
# handle externals
if isinstance(OOT, ExternalType):
- return JvmNativeClass(self, OOT)
+ return jvm.JvmNativeClass(self, OOT)
assert False, "Untranslatable type %s!" % OOT
+ ooitemtype_to_array = {
+ ootype.Signed : jvm.jIntArray,
+ ootype.Unsigned : jvm.jIntArray,
+ ootype.Char : jvm.jCharArray,
+ ootype.Bool : jvm.jBoolArray,
+ ootype.UniChar : jvm.jCharArray,
+ ootype.String : jvm.jStringArray,
+ ootype.Float : jvm.jDoubleArray,
+ ootype.Void : jvm.jVoidArray,
+ }
+
+ def _array_type(self, ITEM):
+ if ITEM in self.ooitemtype_to_array:
+ return self.ooitemtype_to_array[ITEM]
+ return jvm.jObjectArray
+
def annotation_to_cts(self, _tp):
s_tp = annotation(_tp)
TP = annotation_to_lltype(s_tp)
Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py (original)
+++ pypy/dist/pypy/translator/jvm/generator.py Fri Apr 4 15:10:29 2008
@@ -12,231 +12,11 @@
from pypy.rlib.objectmodel import CDefinedIntSymbolic
from pypy.rlib.rarithmetic import isnan, isinf
from pypy.translator.oosupport.constant import push_constant
-import pypy.translator.jvm.typesystem as jvmtype
-from pypy.translator.jvm.typesystem import \
- JvmType, jString, jInt, jLong, jDouble, jBool, jString, \
- jPyPy, jVoid, jMath, desc_for_method, jPrintStream, jClass, jChar, \
- jObject, jByteArray, jPyPyExcWrap, jIntegerClass, jLongClass, \
- jDoubleClass, jCharClass, jStringBuilder, JvmScalarType, jArrayList, \
- jObjectArray, jPyPyInterlink, jPyPyCustomDict, jPyPyEquals, \
- jPyPyHashCode, jMap, jPyPyWeakRef, jSystem, jll_os, jPyPyInterlink
-
-
-# ___________________________________________________________________________
-# JVM Opcodes:
-#
-# Map from symbolic name to an instance of the Opcode class
-
-class Opcode(object):
- def __init__(self, jvmstr):
- """
- flags is a set of flags (see above) that describe opcode #UPDATE
- jvmstr is the name for jasmin printouts
- """
- self.jvmstr = jvmstr
- self.flags = None #Should flags be added to args?
-
- def __repr__(self):
- return "<Opcode %s:%x>" % (self.jvmstr, self.flags)
-
- def specialize(self, args):
- """ Process the argument list according to the various flags.
- Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing
- the new opcode, and ARGS is a list of arguments or empty tuple.
- Most of these do not do anything. """
- return (self.jvmstr, args)
-
-class IntConstOpcode(Opcode):
- """ The ICONST opcode specializes itself for small integer opcodes. """
- def specialize(self, args):
- assert len(args) == 1
- if args[0] == -1:
- return self.jvmstr + "_m1", ()
- elif args[0] >= 0 and args[0] <= 5:
- return self.jvmstr + "_" + str(args[0]), ()
- # Non obvious: convert ICONST to LDC if the constant is out of
- # range
- return "ldc", args
-
-class VarOpcode(Opcode):
- """ An Opcode which takes a variable index as an argument; specialized
- to small integer indices. """
- def specialize(self, args):
- assert len(args) == 1
- if args[0] >= 0 and args[0] <= 3:
- return self.jvmstr + "_" + str(args[0]), ()
- return Opcode.specialize(self, args)
-
-class IntClassNameOpcode(Opcode):
- """ An opcode which takes an internal class name as its argument;
- the actual argument will be a JvmType instance. """
- def specialize(self, args):
- args = [args[0].descriptor.int_class_name()]
- return self.jvmstr, args
-
-class OpcodeFamily(object):
- """
- Many opcodes in JVM have variants that depend on the type of the
- operands; for example, one must choose the correct ALOAD, ILOAD,
- or DLOAD depending on whether one is loading a reference, integer,
- or double variable respectively. Each instance of this class
- defines one 'family' of opcodes, such as the LOAD family shown
- above, and produces Opcode objects specific to a particular type.
- """
- def __init__(self, opcclass, suffix):
- """
- opcclass is the opcode subclass to use (see above) when
- instantiating a particular opcode
-
- jvmstr is the name for jasmin printouts
- """
- self.opcode_class = opcclass
- self.suffix = suffix
- self.cache = {}
-
- def _o(self, prefix):
- try:
- return self.cache[prefix]
- except KeyError:
- self.cache[prefix] = obj = self.opcode_class(
- prefix+self.suffix)
- return obj
-
- def for_type(self, argtype):
- """ Returns a customized opcode of this family appropriate to
- 'argtype', a JvmType object. """
-
- desc = argtype.descriptor
-
- # These are always true:
- if desc[0] == 'L': return self._o("a") # Objects
- if desc[0] == '[': return self._o("a") # Arrays
- if desc == 'I': return self._o("i") # Integers
- if desc == 'J': return self._o("l") # Integers
- if desc == 'D': return self._o("d") # Doubles
- if desc == 'V': return self._o("") # Void [used by RETURN]
-
- # Chars/Bytes/Booleans are normally represented as ints
- # in the JVM, but some opcodes are different. They use a
- # different OpcodeFamily (see ArrayOpcodeFamily for ex)
- if desc == 'C': return self._o("i") # Characters
- if desc == 'B': return self._o("i") # Bytes
- if desc == 'Z': return self._o("i") # Boolean
+import pypy.translator.jvm.typesystem as jvm
- assert False, "Unknown argtype=%s" % repr(argtype)
- raise NotImplementedError
-
-class ArrayOpcodeFamily(OpcodeFamily):
- """ Opcode family specialized for array access instr """
- def for_type(self, argtype):
- desc = argtype.descriptor
- if desc == 'J': return self._o("l") # Integers
- if desc == 'D': return self._o("d") # Doubles
- if desc == 'C': return self._o("c") # Characters
- if desc == 'B': return self._o("b") # Bytes
- if desc == 'Z': return self._o("b") # Boolean (access as bytes)
- return OpcodeFamily.for_type(self, argtype)
-
-# Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx
-# variants compare a single integer arg against 0, and the IF_ICMPxx
-# variants compare 2 integer arguments against each other.
-for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'):
- ifop = "if%s" % cmpop
- if_icmpop = "if_icmp%s" % cmpop
- globals()[ifop.upper()] = Opcode(ifop)
- globals()[if_icmpop.upper()] = Opcode(if_icmpop)
-
-# Compare references, either against NULL or against each other
-IFNULL = Opcode('ifnull')
-IFNONNULL = Opcode('ifnonnull')
-IF_ACMPEQ = Opcode('if_acmpeq')
-IF_ACMPNE = Opcode('if_acmpne')
-
-# Method invocation
-INVOKESTATIC = Opcode('invokestatic')
-INVOKEVIRTUAL = Opcode('invokevirtual')
-INVOKESPECIAL = Opcode('invokespecial')
-INVOKEINTERFACE = Opcode('invokeinterface')
-
-# Other opcodes
-LDC = Opcode('ldc') # single-word types
-LDC2 = Opcode('ldc2_w') # double-word types: doubles and longs
-GOTO = Opcode('goto')
-ICONST = IntConstOpcode('iconst')
-ICONST_0 = Opcode('iconst_0') # sometimes convenient to refer to this directly
-ACONST_NULL=Opcode('aconst_null')
-DCONST_0 = Opcode('dconst_0')
-DCONST_1 = Opcode('dconst_1')
-LCONST_0 = Opcode('lconst_0')
-LCONST_1 = Opcode('lconst_1')
-GETFIELD = Opcode('getfield')
-PUTFIELD = Opcode('putfield')
-GETSTATIC = Opcode('getstatic')
-PUTSTATIC = Opcode('putstatic')
-CHECKCAST = IntClassNameOpcode('checkcast')
-INEG = Opcode('ineg')
-IXOR = Opcode('ixor')
-IADD = Opcode('iadd')
-ISUB = Opcode('isub')
-IMUL = Opcode('imul')
-IDIV = Opcode('idiv')
-IREM = Opcode('irem')
-IAND = Opcode('iand')
-IOR = Opcode('ior')
-ISHL = Opcode('ishl')
-ISHR = Opcode('ishr')
-IUSHR = Opcode('iushr')
-LCMP = Opcode('lcmp')
-DCMPG = Opcode('dcmpg')
-DCMPL = Opcode('dcmpl')
-NOP = Opcode('nop')
-I2D = Opcode('i2d')
-I2L = Opcode('i2l')
-D2I= Opcode('d2i')
-#D2L= Opcode('d2l') #PAUL
-L2I = Opcode('l2i')
-L2D = Opcode('l2d')
-ATHROW = Opcode('athrow')
-DNEG = Opcode('dneg')
-DADD = Opcode('dadd')
-DSUB = Opcode('dsub')
-DMUL = Opcode('dmul')
-DDIV = Opcode('ddiv')
-DREM = Opcode('drem')
-LNEG = Opcode('lneg')
-LADD = Opcode('ladd')
-LSUB = Opcode('lsub')
-LMUL = Opcode('lmul')
-LDIV = Opcode('ldiv')
-LREM = Opcode('lrem')
-LAND = Opcode('land')
-LOR = Opcode('lor')
-LXOR = Opcode('lxor')
-LSHL = Opcode('lshl')
-LSHR = Opcode('lshr')
-LUSHR = Opcode('lushr')
-NEW = IntClassNameOpcode('new')
-DUP = Opcode('dup')
-DUP2 = Opcode('dup2')
-DUP_X1 = Opcode('dup_x1')
-POP = Opcode('pop')
-POP2 = Opcode('pop2')
-SWAP = Opcode('swap')
-INSTANCEOF= IntClassNameOpcode('instanceof')
-# Loading/storing local variables
-LOAD = OpcodeFamily(VarOpcode, "load")
-STORE = OpcodeFamily(VarOpcode, "store")
-RETURN = OpcodeFamily(Opcode, "return")
-
-# Loading/storing from arrays
-# *NOTE*: This family is characterized by the type of the ELEMENT,
-# not the type of the ARRAY.
-#
-# Also: here I break from convention by naming the objects ARRLOAD
-# rather than ALOAD, even though the suffix is 'aload'. This is to
-# avoid confusion with the ALOAD opcode.
-ARRLOAD = ArrayOpcodeFamily(Opcode, "aload")
-ARRSTORE = ArrayOpcodeFamily(Opcode, "astore")
+# Load a few commonly used names, but prefer to use 'jvm.Name'
+from pypy.translator.jvm.typesystem import \
+ jPyPy, jString, jInt, jVoid
# ___________________________________________________________________________
# Labels
@@ -257,244 +37,6 @@
return self.label
# ___________________________________________________________________________
-# Methods
-#
-# "Method" objects describe all the information needed to invoke a
-# method. We create one for each node.Function object, as well as for
-# various helper methods (defined below). To invoke a method, you
-# push its arguments and then use generator.emit(methobj) where
-# methobj is its Method instance.
-
-class Method(object):
-
- # Create a constructor:
- def c(classty, argtypes):
- return Method(classty.name, "<init>", argtypes, jVoid,
- opcode=INVOKESPECIAL)
- c = staticmethod(c)
-
- # Create a virtual or interface method:
- def v(classty, methnm, argtypes, rettype):
- """
- Shorthand to create a virtual method.
- 'class' - JvmType object for the class
- 'methnm' - name of the method (Python string)
- 'argtypes' - list of JvmType objects, one for each argument but
- not the this ptr
- 'rettype' - JvmType for return type
- """
- assert argtypes is not None
- assert rettype is not None
- classnm = classty.name
- if isinstance(classty, jvmtype.JvmInterfaceType):
- opc = INVOKEINTERFACE
- else:
- assert isinstance(classty, jvmtype.JvmClassType)
- opc = INVOKEVIRTUAL
- return Method(classnm, methnm, argtypes, rettype, opcode=opc)
- v = staticmethod(v)
-
- # Create a static method:
- def s(classty, methnm, argtypes, rettype):
- """
- Shorthand to create a static method.
- 'class' - JvmType object for the class
- 'methnm' - name of the method (Python string)
- 'argtypes' - list of JvmType objects, one for each argument but
- not the this ptr
- 'rettype' - JvmType for return type
- """
- assert isinstance(classty, JvmType)
- classnm = classty.name
- return Method(classnm, methnm, argtypes, rettype)
- s = staticmethod(s)
-
- def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC):
- self.opcode = opcode
- self.class_name = classnm # String, ie. "java.lang.Math"
- self.method_name = methnm # String "abs"
- self.argument_types = argtypes # List of jvmtypes
- self.return_type = rettype # jvmtype
-
- # Compute the method descriptior, which is a string like "()I":
- argtypesdesc = [a.descriptor for a in argtypes]
- rettypedesc = rettype.descriptor
- self.descriptor = desc_for_method(argtypesdesc, rettypedesc)
- def invoke(self, gen):
- gen._instr(self.opcode, self)
- def is_static(self):
- return self.opcode == INVOKESTATIC
- def jasmin_syntax(self):
- res = "%s/%s%s" % (self.class_name.replace('.','/'),
- self.method_name,
- self.descriptor)
- # A weird, inexplicable quirk of Jasmin syntax is that it requires
- # the number of arguments after an invokeinterface call:
- if self.opcode == INVOKEINTERFACE:
- res += " %d" % (len(self.argument_types)+1,)
- return res
-
-OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt)
-OBJTOSTRING = Method.v(jObject, 'toString', (), jString)
-OBJEQUALS = Method.v(jObject, 'equals', (jObject,), jBool)
-SYSTEMGC = Method.s(jSystem, 'gc', (), jVoid)
-INTTOSTRINGI = Method.s(jIntegerClass, 'toString', (jInt,), jString)
-LONGTOSTRINGL = Method.s(jLongClass, 'toString', (jLong,), jString)
-DOUBLETOSTRINGD = Method.s(jDoubleClass, 'toString', (jDouble,), jString)
-CHARTOSTRINGC = Method.s(jCharClass, 'toString', (jChar,), jString)
-MATHIABS = Method.s(jMath, 'abs', (jInt,), jInt)
-IABSOVF = Method.v(jPyPy, 'abs_ovf', (jInt,), jInt)
-MATHLABS = Method.s(jMath, 'abs', (jLong,), jLong)
-LABSOVF = Method.v(jPyPy, 'abs_ovf', (jLong,), jLong)
-MATHDABS = Method.s(jMath, 'abs', (jDouble,), jDouble)
-INEGOVF = Method.v(jPyPy, 'negate_ovf', (jInt,), jInt)
-LNEGOVF = Method.v(jPyPy, 'negate_ovf', (jLong,), jLong)
-IADDOVF = Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt)
-LADDOVF = Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong)
-ISUBOVF = Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt)
-LSUBOVF = Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong)
-IMULOVF = Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt)
-LMULOVF = Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong)
-MATHFLOOR = Method.s(jMath, 'floor', (jDouble,), jDouble)
-IFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt)
-LFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong)
-IFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt)
-LFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong)
-IREMOVF = Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt)
-LREMOVF = Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong)
-ISHLOVF = Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt)
-LSHLOVF = Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong)
-MATHDPOW = Method.s(jMath, 'pow', (jDouble, jDouble), jDouble)
-PRINTSTREAMPRINTSTR = Method.v(jPrintStream, 'print', (jString,), jVoid)
-CLASSFORNAME = Method.s(jClass, 'forName', (jString,), jClass)
-CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool)
-STRINGBUILDERAPPEND = Method.v(jStringBuilder, 'append',
- (jString,), jStringBuilder)
-PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt)
-PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
-PYPYUINTMOD = Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt)
-PYPYUINTMUL = Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt)
-PYPYUINTDIV = Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt)
-PYPYULONGMOD = Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong)
-PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
-PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
-PYPYDOUBLETOLONG = Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
-PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
-PYPYSTRTOINT = Method.v(jPyPy, 'str_to_int', (jString,), jInt)
-PYPYSTRTOUINT = Method.v(jPyPy, 'str_to_uint', (jString,), jInt)
-PYPYSTRTOLONG = Method.v(jPyPy, 'str_to_long', (jString,), jLong)
-PYPYSTRTOULONG = Method.v(jPyPy, 'str_to_ulong', (jString,), jLong)
-PYPYSTRTOBOOL = Method.v(jPyPy, 'str_to_bool', (jString,), jBool)
-PYPYSTRTODOUBLE = Method.v(jPyPy, 'str_to_double', (jString,), jDouble)
-PYPYSTRTOCHAR = Method.v(jPyPy, 'str_to_char', (jString,), jChar)
-PYPYBOOLTODOUBLE = Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble)
-PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid)
-PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid)
-PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString)
-PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString)
-PYPYSERIALIZEULONG = Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString)
-PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString)
-PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString)
-PYPYESCAPEDUNICHAR = Method.s(jPyPy, 'escaped_unichar', (jChar,), jString)
-PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString)
-PYPYESCAPEDUNICODE = Method.s(jPyPy, 'escaped_unicode', (jString,), jString)
-PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString)
-PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject)
-PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray)
-PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList)
-PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble)
-OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass)
-CLASSGETNAME = Method.v(jClass, 'getName', (), jString)
-CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make',
- (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict)
-PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef)
-PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject)
-
-# ___________________________________________________________________________
-# Fields
-#
-# Field objects encode information about fields.
-
-class Field(object):
-
- @staticmethod
- def i(classty, fieldnm, fieldty, OOTYPE=None):
- """
- Shorthand to create an instance field.
- 'class' - JvmType object for the class containing the field
- 'fieldnm' - name of the field (Python string)
- 'fieldty' - JvmType object for the type of the field
- 'OOTYPE' - optional OOTYPE object for the type of the field
- """
- return Field(classty.name, fieldnm, fieldty, False, OOTYPE)
-
- @staticmethod
- def s(classty, fieldnm, fieldty, OOTYPE=None):
- """
- Shorthand to create a static field.
- 'class' - JvmType object for the class containing the field
- 'fieldnm' - name of the field (Python string)
- 'fieldty' - JvmType object for the type of the field
- 'OOTYPE' - optional OOTYPE object for the type of the field
- """
- return Field(classty.name, fieldnm, fieldty, True, OOTYPE)
-
- def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None):
- # All fields are public
- self.class_name = classnm # String, ie. "java.lang.Math"
- self.field_name = fieldnm # String "someField"
- self.OOTYPE = OOTYPE # OOTYPE equivalent of JvmType, may be None
- self.jtype = jtype # JvmType
- self.is_static = static # True or False
- def load(self, gen):
- if self.is_static:
- gen._instr(GETSTATIC, self)
- else:
- gen._instr(GETFIELD, self)
- def store(self, gen):
- if self.is_static:
- gen._instr(PUTSTATIC, self)
- else:
- gen._instr(PUTFIELD, self)
- def jasmin_syntax(self):
- return "%s/%s %s" % (
- self.class_name.replace('.','/'),
- self.field_name,
- self.jtype.descriptor)
-
-class Property(object):
- """
- An object which acts like a Field, but when a value is loaded or
- stored it actually invokes accessor methods.
- """
- def __init__(self, field_name, get_method, put_method, OOTYPE=None):
- self.get_method = get_method
- self.put_method = put_method
- self.field_name = field_name
- self.OOTYPE = OOTYPE
-
- # Synthesize the Field attributes from the get_method/put_method:
- self.class_name = get_method.class_name
- assert put_method.class_name == self.class_name
- self.jtype = get_method.return_type
- self.is_static = get_method.is_static
- def load(self, gen):
- self.get_method.invoke(gen)
- def store(self, gen):
- self.put_method.invoke(gen)
- # jasmin_syntax is not needed, since this object itself never appears
- # as an argument an Opcode
-
-SYSTEMOUT = Field.s(jSystem, 'out', jPrintStream)
-SYSTEMERR = Field.s(jSystem, 'err', jPrintStream)
-DOUBLENAN = Field.s(jDoubleClass, 'NaN', jDouble)
-DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble)
-DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble)
-
-PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink)
-PYPYOS = Field.i(jPyPy, 'os', jll_os)
-
-# ___________________________________________________________________________
# Generator State
class ClassState(object):
@@ -625,8 +167,7 @@
"""
self.begin_function("<init>", [], [self.current_type()], jVoid)
self.load_jvm_var(self.current_type(), 0)
- jmethod = Method(self.curclass.superclass_type.name, "<init>",
- (), jVoid, opcode=INVOKESPECIAL)
+ jmethod = jvm.Method.c(self.curclass.superclass_type, ())
jmethod.invoke(self)
def end_constructor(self):
@@ -700,14 +241,14 @@
def return_val(self, jtype):
""" Returns a value from top of stack of the JvmType 'jtype' """
- self._instr(RETURN.for_type(jtype))
+ self._instr(jvm.RETURN.for_type(jtype))
def load_class_name(self):
""" Loads the name of the *Java* class of the object on the top of
the stack as a Java string. Note that the result for a PyPy
generated class will look something like 'pypy.some.pkg.cls' """
- self.emit(OBJECTGETCLASS)
- self.emit(CLASSGETNAME)
+ self.emit(jvm.OBJECTGETCLASS)
+ self.emit(jvm.CLASSGETNAME)
def load_string(self, str):
""" Pushes a Java version of a Python string onto the stack.
@@ -724,7 +265,7 @@
'"')
# Use LDC to load the Java version:
# XXX --- support byte arrays here? Would be trickier!
- self._instr(LDC, res)
+ self._instr(jvm.LDC, res)
def load_jvm_var(self, jvartype, varidx):
""" Loads from jvm slot #varidx, which is expected to hold a value of
@@ -732,20 +273,20 @@
assert varidx < self.curfunc.next_offset
if jvartype is jVoid:
return
- opc = LOAD.for_type(jvartype)
+ opc = jvm.LOAD.for_type(jvartype)
self._instr(opc, varidx)
def store_jvm_var(self, vartype, varidx):
""" Loads from jvm slot #varidx, which is expected to hold a value of
type vartype """
- self._instr(STORE.for_type(vartype), varidx)
+ self._instr(jvm.STORE.for_type(vartype), varidx)
def load_from_array(self, elemtype):
""" Loads something from an array; the result will be of type 'elemtype'
(and hence the array is of type 'array_of(elemtype)'), where
'elemtype' is a JvmType. Assumes that the array ref and index are
already pushed onto stack (in that order). """
- self._instr(ARRLOAD.for_type(elemtype))
+ self._instr(jvm.ARRLOAD.for_type(elemtype))
def store_to_array(self, elemtype):
""" Stores something into an array; the result will be of type
@@ -753,7 +294,7 @@
'array_of(elemtype)'), where 'elemtype' is a JvmType. Assumes
that the array ref, index, and value are already pushed onto
stack (in that order)."""
- self._instr(ARRLOAD.for_type(elemtype))
+ self._instr(jvm.ARRLOAD.for_type(elemtype))
def unique_label(self, desc, mark=False):
""" Returns an opaque, unique label object that can be passed an
@@ -773,7 +314,7 @@
def load_this_ptr(self):
""" Convenience method. Be sure you only call it from a
virtual method, not static methods. """
- self.load_jvm_var(jObject, 0)
+ self.load_jvm_var(jvm.jObject, 0)
def load_function_argument(self, index):
""" Convenience method. Loads function argument #index; note that
@@ -786,9 +327,9 @@
self.prepare_generic_argument_with_jtype(jty)
def prepare_generic_argument_with_jtype(self, jty):
- if jty is jvmtype.jVoid:
- self.emit(ACONST_NULL)
- elif isinstance(jty, JvmScalarType):
+ if jty is jVoid:
+ self.emit(jvm.ACONST_NULL)
+ elif isinstance(jty, jvm.JvmScalarType):
self.box_value(jty)
def prepare_generic_result(self, ITEMTYPE):
@@ -796,9 +337,9 @@
self.prepare_generic_result_with_jtype(jresty)
def prepare_generic_result_with_jtype(self, jresty):
- if jresty is jvmtype.jVoid:
- self.emit(POP)
- elif isinstance(jresty, JvmScalarType):
+ if jresty is jVoid:
+ self.emit(jvm.POP)
+ elif isinstance(jresty, jvm.JvmScalarType):
# Perform any un-boxing required:
self.downcast_jtype(jresty.box_type)
self.unbox_value(jresty)
@@ -810,20 +351,21 @@
""" Assuming that an value of type jscalartype is on the stack,
boxes it into an Object. """
jclasstype = jscalartype.box_type
- jmethod = Method.s(jclasstype, 'valueOf', (jscalartype,), jclasstype)
+ jmethod = jvm.Method.s(
+ jclasstype, 'valueOf', (jscalartype,), jclasstype)
self.emit(jmethod)
def unbox_value(self, jscalartype):
""" Assuming that a boxed value of type jscalartype is on the stack,
unboxes it. """
jclasstype = jscalartype.box_type
- jmethod = Method.v(
+ jmethod = jvm.Method.v(
jclasstype, jscalartype.unbox_method, (), jscalartype)
self.emit(jmethod)
def swap(self):
""" Swaps the two words highest on the stack. """
- self.emit(SWAP)
+ self.emit(jvm.SWAP)
# __________________________________________________________________
# Exception Handling
@@ -869,14 +411,14 @@
_equals = {
ootype.Void: (None,None),
- ootype.SignedLongLong: (LCMP,IFEQ),
- ootype.UnsignedLongLong: (LCMP,IFEQ),
- ootype.Float: (DCMPG,IFEQ),
- ootype.Signed: (None,IF_ICMPNE),
- ootype.Unsigned: (None,IF_ICMPNE),
- ootype.Bool: (None,IF_ICMPNE),
- ootype.Char: (None,IF_ICMPNE),
- ootype.UniChar: (None,IF_ICMPNE),
+ ootype.SignedLongLong: (jvm.LCMP, jvm.IFEQ),
+ ootype.UnsignedLongLong: (jvm.LCMP, jvm.IFEQ),
+ ootype.Float: (jvm.DCMPG, jvm.IFEQ),
+ ootype.Signed: (None,jvm.IF_ICMPNE),
+ ootype.Unsigned: (None,jvm.IF_ICMPNE),
+ ootype.Bool: (None,jvm.IF_ICMPNE),
+ ootype.Char: (None,jvm.IF_ICMPNE),
+ ootype.UniChar: (None,jvm.IF_ICMPNE),
}
def compare_values(self, OOTYPE, unequal_lbl):
""" Assumes that two instances of OOTYPE are pushed on the stack;
@@ -886,14 +428,14 @@
if i1: self.emit(i1)
if i2: self.emit(i2, unequal_lbl)
return
- self.emit(OBJEQUALS)
- self.emit(IFEQ, unequal_lbl)
+ self.emit(jvm.OBJEQUALS)
+ self.emit(jvm.IFEQ, unequal_lbl)
_hash = {
- ootype.Void: ICONST_0,
- ootype.SignedLongLong: L2I,
- ootype.UnsignedLongLong: L2I,
- ootype.Float: D2I,
+ ootype.Void: jvm.ICONST_0,
+ ootype.SignedLongLong: jvm.L2I,
+ ootype.UnsignedLongLong: jvm.L2I,
+ ootype.Float: jvm.D2I,
ootype.Signed: None,
ootype.Unsigned: None,
ootype.Bool: None,
@@ -907,7 +449,7 @@
i1 = self._hash[OOTYPE]
if i1: self.emit(i1)
return
- self.emit(OBJHASHCODE)
+ self.emit(jvm.OBJHASHCODE)
# __________________________________________________________________
# Generator methods and others that are invoked by MicroInstructions
@@ -919,16 +461,19 @@
it is the name of a method to invoke, or an Opcode/Method
object (defined above)."""
+ if instr is None:
+ return
+
if isinstance(instr, str):
return getattr(self, instr)(*args)
- if isinstance(instr, Opcode):
+ if isinstance(instr, jvm.Opcode):
return self._instr(instr, *args)
- if isinstance(instr, Method):
+ if isinstance(instr, jvm.BaseMethod):
return instr.invoke(self)
- if isinstance(instr, Field) or isinstance(instr, Property):
+ if isinstance(instr, jvm.Field) or isinstance(instr, jvm.Property):
return instr.load(self)
raise Exception("Unknown object in call to emit(): "+repr(instr))
@@ -936,6 +481,7 @@
def _var_data(self, v):
# Determine java type:
jty = self.db.lltype_to_cts(v.concretetype)
+ import sys
# Determine index in stack frame slots:
# note that arguments and locals can be treated the same here
return jty, self.curfunc.var_offset(v, jty)
@@ -989,11 +535,11 @@
self.downcast_jtype(jtype)
def downcast_jtype(self, jtype):
- self._instr(CHECKCAST, jtype)
+ self._instr(jvm.CHECKCAST, jtype)
def instanceof(self, TYPE):
jtype = self.db.lltype_to_cts(TYPE)
- self._instr(INSTANCEOF, jtype)
+ self._instr(jvm.INSTANCEOF, jtype)
# included for compatibility with oosupport, but instanceof_jtype
# follows our naming convention better
@@ -1001,22 +547,22 @@
return self.instanceof_jtype(jtype)
def instanceof_jtype(self, jtype):
- self._instr(INSTANCEOF, jtype)
+ self._instr(jvm.INSTANCEOF, jtype)
def branch_unconditionally(self, target_label):
self.goto(target_label)
def branch_conditionally(self, cond, target_label):
if cond:
- self._instr(IFNE, target_label)
+ self._instr(jvm.IFNE, target_label)
else:
- self._instr(IFEQ, target_label)
+ self._instr(jvm.IFEQ, target_label)
def branch_if_equal(self, target_label):
- self._instr(IF_ICMPEQ, target_label)
+ self._instr(jvm.IF_ICMPEQ, target_label)
def branch_if_not_equal(self, target_label):
- self._instr(IF_ICMPNE, target_label)
+ self._instr(jvm.IF_ICMPNE, target_label)
def call_graph(self, graph):
mthd = self.db.pending_function(graph)
@@ -1028,7 +574,7 @@
mthd.invoke(self)
# Check if we have to convert the result type at all:
- gener = jvmtype.Generifier(OOCLASS)
+ gener = jvm.Generifier(OOCLASS)
RETTYPE = gener.full_types(method_name)[1]
jrettype = self.db.lltype_to_cts(RETTYPE)
if jrettype != mthd.return_type:
@@ -1043,7 +589,7 @@
# If necessary, load the ll_os object pointer instead:
if module == 'll_os':
- PYPYOS.load(self)
+ jvm.PYPYOS.load(self)
def call_primitive(self, op, module, name):
callee = op.args[0].value
@@ -1052,7 +598,7 @@
# Determine what class the primitive is implemented in:
if module == 'll_os':
- jcls = jll_os
+ jcls = jvm.jll_os
else:
jcls = jPyPy
@@ -1062,9 +608,9 @@
# the method cannot directly refer to the Java type in
# .java source, as its name is not yet known.
if jrettype.is_generated():
- mthd = Method.v(jcls, name, jargtypes, jObject)
+ mthd = jvm.Method.v(jcls, name, jargtypes, jvm.jObject)
else:
- mthd = Method.v(jcls, name, jargtypes, jrettype)
+ mthd = jvm.Method.v(jcls, name, jargtypes, jrettype)
# Invoke the method
self.emit(mthd)
@@ -1081,13 +627,13 @@
cts_type = self.db.lltype_to_cts(OOTYPE)
# treat all objects the same:
- if isinstance(cts_type, jvmtype.JvmClassType):
- cts_type = jObject
+ if isinstance(cts_type, jvm.JvmClassType):
+ cts_type = jvm.jObject
- mthd = Method.v(jPyPy, 'oostring', [cts_type, jInt], jString)
+ mthd = jvm.Method.v(jPyPy, 'oostring', [cts_type, jInt], jString)
self.emit(mthd)
if self.db.using_byte_array:
- self.emit(PYPYSTRING2BYTES)
+ self.emit(jvm.PYPYSTRING2BYTES)
def prepare_call_oounicode(self, OOTYPE):
# Load the PyPy object pointer onto the stack:
@@ -1095,10 +641,10 @@
def call_oounicode(self, OOTYPE):
cts_type = self.db.lltype_to_cts(OOTYPE)
- mthd = Method.v(jPyPy, 'oounicode', [cts_type], jString)
+ mthd = jvm.Method.v(jPyPy, 'oounicode', [cts_type], jString)
self.emit(mthd)
if self.db.using_byte_array:
- self.emit(PYPYSTRING2BYTES)
+ self.emit(jvm.PYPYSTRING2BYTES)
def new(self, TYPE):
jtype = self.db.lltype_to_cts(TYPE)
@@ -1106,38 +652,43 @@
def new_with_jtype(self, jtype, ctor=None):
if ctor is None:
- ctor = Method.c(jtype, ())
- self.emit(NEW, jtype)
- self.emit(DUP)
+ ctor = jvm.Method.c(jtype, ())
+ self.emit(jvm.NEW, jtype)
+ self.emit(jvm.DUP)
self.emit(ctor)
+ def oonewarray(self, TYPE, length):
+ jtype = self.db.lltype_to_cts(TYPE)
+ self.load(length)
+ jtype.make(self)
+
def instantiate(self):
- self.emit(PYPYRUNTIMENEW)
+ self.emit(jvm.PYPYRUNTIMENEW)
def getclassobject(self, OOINSTANCE):
- jvmtype = self.db.lltype_to_cts(OOINSTANCE)
- self.load_string(jvmtype.name)
- CLASSFORNAME.invoke(self)
+ jtype = self.db.lltype_to_cts(OOINSTANCE)
+ self.load_string(jtype.name)
+ jvm.CLASSFORNAME.invoke(self)
def dup(self, OOTYPE):
- jvmtype = self.db.lltype_to_cts(OOTYPE)
- self.dup_jtype(jvmtype)
+ jtype = self.db.lltype_to_cts(OOTYPE)
+ self.dup_jtype(jtype)
- def dup_jtype(self, jvmtype):
- if jvmtype.descriptor.type_width() == 1:
- self.emit(DUP)
+ def dup_jtype(self, jtype):
+ if jtype.descriptor.type_width() == 1:
+ self.emit(jvm.DUP)
else:
- self.emit(DUP2)
+ self.emit(jvm.DUP2)
def pop(self, OOTYPE):
- jvmtype = self.db.lltype_to_cts(OOTYPE)
- if jvmtype.descriptor.type_width() == 1:
- self.emit(POP)
+ jtype = self.db.lltype_to_cts(OOTYPE)
+ if jtype.descriptor.type_width() == 1:
+ self.emit(jvm.POP)
else:
- self.emit(POP2)
+ self.emit(jvm.POP2)
def push_null(self, OOTYPE):
- self.emit(ACONST_NULL)
+ self.emit(jvm.ACONST_NULL)
# we can't assume MALLOC_ZERO_FILLED, because for scalar type the
# default item for ArrayList is null, not e.g. Integer(0) or
@@ -1150,16 +701,16 @@
if TYPE is ootype.Void:
return
elif isinstance(value, CDefinedIntSymbolic):
- self.emit(ICONST, self.DEFINED_INT_SYMBOLICS[value.expr])
+ self.emit(jvm.ICONST, self.DEFINED_INT_SYMBOLICS[value.expr])
elif TYPE in (ootype.Bool, ootype.Signed):
- self.emit(ICONST, int(value))
+ self.emit(jvm.ICONST, int(value))
elif TYPE is ootype.Unsigned:
# Converts the unsigned int into its corresponding signed value:
if value > 0x7FFFFFFF:
value = -((int(value) ^ 0xFFFFFFFF)+1)
- self.emit(ICONST, value)
+ self.emit(jvm.ICONST, value)
elif TYPE is ootype.Char or TYPE is ootype.UniChar:
- self.emit(ICONST, ord(value))
+ self.emit(jvm.ICONST, ord(value))
elif TYPE is ootype.SignedLongLong:
self._push_long_constant(long(value))
elif TYPE is ootype.UnsignedLongLong:
@@ -1171,7 +722,7 @@
self._push_double_constant(float(value))
elif TYPE in (ootype.String, ootype.Unicode):
if value == ootype.null(TYPE):
- self.emit(ACONST_NULL)
+ self.emit(jvm.ACONST_NULL)
else:
self.load_string(value._str)
else:
@@ -1179,25 +730,25 @@
def _push_long_constant(self, value):
if value == 0:
- self.emit(LCONST_0)
+ self.emit(jvm.LCONST_0)
elif value == 1:
- self.emit(LCONST_1)
+ self.emit(jvm.LCONST_1)
else:
- self.emit(LDC2, value)
+ self.emit(jvm.LDC2, value)
def _push_double_constant(self, value):
if isnan(value):
- DOUBLENAN.load(self)
+ jvm.DOUBLENAN.load(self)
elif isinf(value):
- if value > 0: DOUBLEPOSINF.load(self)
- else: DOUBLENEGINF.load(self)
+ if value > 0: jvm.DOUBLEPOSINF.load(self)
+ else: jvm.DOUBLENEGINF.load(self)
elif value == 0.0:
- self.emit(DCONST_0)
+ self.emit(jvm.DCONST_0)
elif value == 1.0:
- self.emit(DCONST_1)
+ self.emit(jvm.DCONST_1)
else:
# Big hack to avoid exponential notation:
- self.emit(LDC2, "%22.22f" % value)
+ self.emit(jvm.LDC2, "%22.22f" % value)
def create_weakref(self, OOTYPE):
"""
@@ -1207,7 +758,7 @@
The result will be that at the top of the stack is a weak reference.
"""
self.prepare_generic_argument(OOTYPE)
- self.emit(PYPYWEAKREFCREATE)
+ self.emit(jvm.PYPYWEAKREFCREATE)
def deref_weakref(self, OOTYPE):
"""
@@ -1215,7 +766,7 @@
that this weak ref is a pointer to. OOTYPE is the kind of object
you had a weak reference to.
"""
- self.emit(PYPYWEAKREFGET)
+ self.emit(jvm.PYPYWEAKREFGET)
self.prepare_generic_result(OOTYPE)
# __________________________________________________________________
@@ -1223,30 +774,30 @@
def throw(self):
""" Throw the object from top of the stack as an exception """
- self._instr(ATHROW)
+ self._instr(jvm.ATHROW)
def iabs(self):
- MATHIABS.invoke(self)
+ jvm.MATHIABS.invoke(self)
def dbl_abs(self):
- MATHDABS.invoke(self)
+ jvm.MATHDABS.invoke(self)
def bitwise_negate(self):
""" Invert all the bits in the "int" on the top of the stack """
- self._instr(ICONST, -1)
- self._instr(IXOR)
+ self._instr(jvm.ICONST, -1)
+ self._instr(jvm.IXOR)
def goto(self, label):
""" Jumps unconditionally """
- self._instr(GOTO, label)
+ self._instr(jvm.GOTO, label)
def goto_if_true(self, label):
""" Jumps if the top of stack is true """
- self._instr(IFNE, label)
+ self._instr(jvm.IFNE, label)
def goto_if_false(self, label):
""" Jumps if the top of stack is false """
- self._instr(IFEQ, label)
+ self._instr(jvm.IFEQ, label)
class JasminGenerator(JVMGenerator):
Modified: pypy/dist/pypy/translator/jvm/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/metavm.py (original)
+++ pypy/dist/pypy/translator/jvm/metavm.py Fri Apr 4 15:10:29 2008
@@ -1,8 +1,7 @@
from pypy.rpython.ootypesystem import ootype
from pypy.translator.oosupport.metavm import MicroInstruction
from pypy.translator.jvm.typesystem import JvmScalarType, JvmClassType
-import pypy.translator.jvm.generator as jvmgen
-import pypy.translator.jvm.typesystem as jvmtype
+import pypy.translator.jvm.typesystem as jvm
from pypy.translator.jvm.builtin import JvmBuiltInType
from pypy.translator.jvm import cmpopcodes
@@ -86,13 +85,13 @@
def render(self, generator, op):
self._load_func(generator, *op.args[1:4])
self._load_func(generator, *op.args[4:7])
- generator.emit(jvmgen.CUSTOMDICTMAKE)
+ generator.emit(jvm.CUSTOMDICTMAKE)
NewCustomDict = _NewCustomDict()
CASTS = {
# FROM TO
- (ootype.Signed, ootype.UnsignedLongLong): jvmgen.I2L,
- (ootype.SignedLongLong, ootype.Signed): jvmgen.L2I,
+ (ootype.Signed, ootype.UnsignedLongLong): jvm.I2L,
+ (ootype.SignedLongLong, ootype.Signed): jvm.L2I,
(ootype.UnsignedLongLong, ootype.SignedLongLong): None,
}
@@ -118,9 +117,9 @@
truelbl = generator.unique_label('load_comparision_result_true')
endlbl = generator.unique_label('load_comparision_result_end')
cmpopcodes.branch_if(generator, op.opname, truelbl)
- generator.emit(jvmgen.ICONST, 0)
+ generator.emit(jvm.ICONST, 0)
generator.goto(endlbl)
generator.mark(truelbl)
- generator.emit(jvmgen.ICONST, 1)
+ generator.emit(jvm.ICONST, 1)
generator.mark(endlbl)
PushComparisonResult = _PushComparisonResult()
Modified: pypy/dist/pypy/translator/jvm/methods.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/methods.py (original)
+++ pypy/dist/pypy/translator/jvm/methods.py Fri Apr 4 15:10:29 2008
@@ -7,8 +7,7 @@
"""
-import pypy.translator.jvm.generator as jvmgen
-import pypy.translator.jvm.typesystem as jvmtype
+import pypy.translator.jvm.typesystem as jvm
from pypy.rpython.ootypesystem import ootype, rclass
class BaseDumpMethod(object):
@@ -19,7 +18,7 @@
self.clsobj = clsobj
self.name = "toString"
self.jargtypes = [clsobj]
- self.jrettype = jvmtype.jString
+ self.jrettype = jvm.jString
def _print_field_value(self, fieldnm, FIELDOOTY):
self.gen.load_this_ptr()
@@ -27,21 +26,21 @@
fieldobj.load(self.gen)
dumpmethod = self.db.toString_method_for_ootype(FIELDOOTY)
self.gen.emit(dumpmethod)
- self.gen.emit(jvmgen.STRINGBUILDERAPPEND)
+ self.gen.emit(jvm.STRINGBUILDERAPPEND)
def _print(self, str):
self.gen.load_string(str)
- self.gen.emit(jvmgen.STRINGBUILDERAPPEND)
+ self.gen.emit(jvm.STRINGBUILDERAPPEND)
def render(self, gen):
self.gen = gen
gen.begin_function(
self.name, (), self.jargtypes, self.jrettype, static=False)
- gen.new_with_jtype(jvmtype.jStringBuilder)
+ gen.new_with_jtype(jvm.jStringBuilder)
self._render_guts(gen)
- gen.emit(jvmgen.OBJTOSTRING)
- gen.emit(jvmgen.RETURN.for_type(jvmtype.jString))
+ gen.emit(jvm.OBJTOSTRING)
+ gen.emit(jvm.RETURN.for_type(jvm.jString))
gen.end_function()
self.gen = None
@@ -117,8 +116,8 @@
self.OOCLASS = OOCLASS
self.clsobj = clsobj
self.name = "equals"
- self.jargtypes = [clsobj, jvmtype.jObject]
- self.jrettype = jvmtype.jBool
+ self.jargtypes = [clsobj, jvm.jObject]
+ self.jrettype = jvm.jBool
def render(self, gen):
self.gen = gen
@@ -156,10 +155,10 @@
# Return true or false as appropriate
gen.push_primitive_constant(ootype.Bool, True)
- gen.return_val(jvmtype.jBool)
+ gen.return_val(jvm.jBool)
gen.mark(unequal_lbl)
gen.push_primitive_constant(ootype.Bool, False)
- gen.return_val(jvmtype.jBool)
+ gen.return_val(jvm.jBool)
gen.end_function()
@@ -171,7 +170,7 @@
self.clsobj = clsobj
self.name = "hashCode"
self.jargtypes = [clsobj]
- self.jrettype = jvmtype.jInt
+ self.jrettype = jvm.jInt
def render(self, gen):
self.gen = gen
@@ -194,10 +193,10 @@
gen.hash_value(FIELDOOTY)
# XOR that with the main hash
- gen.emit(jvmgen.IXOR)
+ gen.emit(jvm.IXOR)
# Return the final hash
- gen.return_val(jvmtype.jInt)
+ gen.return_val(jvm.jInt)
gen.end_function()
Modified: pypy/dist/pypy/translator/jvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py (original)
+++ pypy/dist/pypy/translator/jvm/node.py Fri Apr 4 15:10:29 2008
@@ -39,8 +39,7 @@
from pypy.translator.jvm.cmpopcodes import \
can_branch_directly, branch_if
-import py
-import pypy.translator.jvm.generator as jvmgen
+import pypy.translator.jvm.typesystem as jvm
import pypy.translator.jvm.typesystem as jvmtype
from pypy.translator.jvm.log import log
@@ -86,14 +85,14 @@
# XXX --- perhaps this table would be better placed in typesystem.py
# so as to constrain the knowledge of lltype and ootype
_type_conversion_methods = {
- ootype.Signed:jvmgen.PYPYSTRTOINT,
- ootype.Unsigned:jvmgen.PYPYSTRTOUINT,
- lltype.SignedLongLong:jvmgen.PYPYSTRTOLONG,
- lltype.UnsignedLongLong:jvmgen.PYPYSTRTOULONG,
- ootype.Bool:jvmgen.PYPYSTRTOBOOL,
- ootype.Float:jvmgen.PYPYSTRTODOUBLE,
- ootype.Char:jvmgen.PYPYSTRTOCHAR,
- ootype.UniChar:jvmgen.PYPYSTRTOCHAR,
+ ootype.Signed:jvm.PYPYSTRTOINT,
+ ootype.Unsigned:jvm.PYPYSTRTOUINT,
+ lltype.SignedLongLong:jvm.PYPYSTRTOLONG,
+ lltype.UnsignedLongLong:jvm.PYPYSTRTOULONG,
+ ootype.Bool:jvm.PYPYSTRTOBOOL,
+ ootype.Float:jvm.PYPYSTRTODOUBLE,
+ ootype.Char:jvm.PYPYSTRTOCHAR,
+ ootype.UniChar:jvm.PYPYSTRTOCHAR,
ootype.String:None
}
@@ -109,14 +108,13 @@
#
# 2. Run the initialization method for the constant class.
#
- gen.begin_function(
- '<clinit>', (), [], jVoid, static=True)
- gen.emit(jvmgen.NEW, jPyPy)
- gen.emit(jvmgen.DUP)
+ gen.begin_function('<clinit>', (), [], jVoid, static=True)
+ gen.emit(jvm.NEW, jPyPy)
+ gen.emit(jvm.DUP)
gen.new_with_jtype(gen.db.jInterlinkImplementation)
- gen.emit(jvmgen.DUP)
+ gen.emit(jvm.DUP)
gen.db.interlink_field.store(gen)
- gen.emit(jvmgen.Method.c(jPyPy, [jPyPyInterlink]))
+ gen.emit(jvm.Method.c(jPyPy, [jPyPyInterlink]))
gen.db.pypy_field.store(gen)
gen.db.constant_generator.runtime_init(gen)
gen.return_val(jVoid)
@@ -143,7 +141,7 @@
conv = self._type_conversion_methods[arg.concretetype]
if conv: gen.push_pypy()
gen.load_jvm_var(jStringArray, 0)
- gen.emit(jvmgen.ICONST, i)
+ gen.emit(jvm.ICONST, i)
gen.load_from_array(jString)
if conv: gen.emit(conv)
else:
@@ -151,9 +149,9 @@
# python method expects
arg0 = self.graph.getargs()[0]
assert isinstance(arg0.concretetype, ootype.List), str(arg0.concretetype)
- assert arg0.concretetype._ITEMTYPE is ootype.String
+ assert arg0.concretetype.ITEM is ootype.String
gen.load_jvm_var(jStringArray, 0)
- gen.emit(jvmgen.PYPYARRAYTOLIST)
+ gen.emit(jvm.PYPYARRAYTOLIST)
# Generate a call to this method
gen.emit(self.db.pending_function(self.graph))
@@ -171,13 +169,13 @@
gen.add_comment('Invoking dump method for result of type '
+str(RESOOTYPE))
gen.emit(dumpmethod) # generate the string
- gen.emit(jvmgen.PYPYDUMP) # dump to stdout
+ gen.emit(jvm.PYPYDUMP) # dump to stdout
gen.goto(done_printing)
gen.end_try()
jexc = self.db.exception_root_object()
gen.begin_catch(jexc)
- gen.emit(jvmgen.PYPYDUMPEXCWRAPPER) # dumps to stdout
+ gen.emit(jvm.PYPYDUMPEXCWRAPPER) # dumps to stdout
gen.end_catch()
gen.mark(done_printing)
@@ -198,12 +196,12 @@
name = None
def render(self, gen):
- """ Uses the gen argument, a jvmgen.Generator, to create the
+ """ Uses the gen argument, a jvm.Generator, to create the
appropriate JVM assembly for this method. """
raise NotImplementedError
def method(self):
- """ Returns a jvmgen.Method object that would allow this
+ """ Returns a jvm.Method object that would allow this
function to be invoked. """
raise NotImplementedError
@@ -272,12 +270,12 @@
return self.generator.unique_label(prefix)
def method(self):
- """ Returns a jvmgen.Method that can invoke this function """
+ """ Returns a jvm.Method that can invoke this function """
if not self.is_method:
- ctor = jvmgen.Method.s
+ ctor = jvm.Method.s
startidx = 0
else:
- ctor = jvmgen.Method.v
+ ctor = jvm.Method.v
startidx = 1
return ctor(self.classty, self.name,
self.jargtypes[startidx:], self.jrettype)
@@ -359,11 +357,11 @@
# exception to be caught by the normal handlers.
self.ilasm.begin_catch(jexcty)
self.ilasm.push_interlink()
- interlink_method = jvmgen.Method.v(
+ interlink_method = jvm.Method.v(
jPyPyInterlink, "throw"+pyexccls.__name__, [], jVoid)
self.ilasm.emit(interlink_method)
- self.ilasm.emit(jvmgen.ACONST_NULL)
- self.ilasm.emit(jvmgen.ATHROW)
+ self.ilasm.emit(jvm.ACONST_NULL) # "inform" the verifier...
+ self.ilasm.emit(jvm.ATHROW) # ...that we throw here
self.ilasm.end_try()
def begin_catch(self, llexitcase):
@@ -386,7 +384,7 @@
else:
# the exception value is on the stack, store it in the proper place
if isinstance(link.last_exception, flowmodel.Variable):
- self.ilasm.emit(jvmgen.DUP)
+ self.ilasm.emit(jvm.DUP)
self.ilasm.store(link.last_exc_value)
fld = self.db.lltype_to_cts(rclass.OBJECT).lookup_field('meta')
self.ilasm.emit(fld)
@@ -517,9 +515,9 @@
def _trace(self, str, writeline=False):
if writeline:
str += '\n'
- jvmgen.SYSTEMERR.load(self.generator)
+ jvm.SYSTEMERR.load(self.generator)
self.generator.load_string(str)
- jvmgen.PRINTSTREAMPRINTSTR.invoke(self.generator)
+ jvm.PRINTSTREAMPRINTSTR.invoke(self.generator)
def _is_printable(self, res):
@@ -554,10 +552,10 @@
res.concretetype)
self._trace(" "+prompt+": ")
- self.generator.emit(jvmgen.SYSTEMERR)
+ self.generator.emit(jvm.SYSTEMERR)
self.generator.load(res)
self.generator.emit(jmethod)
- self.generator.emit(jvmgen.PRINTSTREAMPRINTSTR)
+ self.generator.emit(jvm.PRINTSTREAMPRINTSTR)
self._trace("\n")
def _trace_enabled(self):
@@ -596,7 +594,7 @@
self.java_return_type = jrettype
self.dump_method = ConstantStringDumpMethod(
self, "StaticMethodInterface")
- self.invoke_method_obj = jvmgen.Method.v(
+ self.invoke_method_obj = jvm.Method.v(
self, 'invoke',
self.java_argument_types[1:], self.java_return_type)
@@ -604,7 +602,7 @@
raise KeyError(fieldnm) # no fields
def lookup_method(self, methodnm):
- """ Given the method name, returns a jvmgen.Method object """
+ """ Given the method name, returns a jvm.Method object """
assert isinstance(self.java_return_type, JvmType)
if methodnm == 'invoke':
return self.invoke_method_obj
@@ -698,9 +696,9 @@
if bound_to_jty:
self.bound_to_jty = bound_to_jty
- self.bound_to_fld = jvmgen.Field(
+ self.bound_to_fld = jvm.Field(
self.name, 'bound_to', bound_to_jty, False)
- self.bind_method = jvmgen.Method.s(
+ self.bind_method = jvm.Method.s(
self, 'bind', (self.bound_to_jty,), self)
else:
self.bound_to_jty = None
@@ -731,7 +729,7 @@
gen.begin_function(
'bind', [], (self.bound_to_jty,), self, static=True)
gen.new_with_jtype(self)
- gen.emit(jvmgen.DUP)
+ gen.emit(jvm.DUP)
gen.load_jvm_var(self.bound_to_jty, 0)
self.bound_to_fld.store(gen)
gen.return_val(self)
@@ -810,10 +808,10 @@
"""
JvmGeneratedClassType.__init__(self, name)
self.rendered = False # has rendering occurred?
- self.fields = {} # maps field name to jvmgen.Field object
+ self.fields = {} # maps field name to jvm.Field object
self.interfaces = [] # list of JvmTypes
self.methods = {} # maps method name to a Function object*
- self.abstract_methods = {} # maps method name to jvmgen.Method object
+ self.abstract_methods = {} # maps method name to jvm.Method object
self.set_super_class(supercls)
# * --- actually maps to an object that defines the
@@ -833,9 +831,9 @@
self.throwable = True
def add_field(self, fieldobj, fielddef):
- """ Creates a new field accessed via the jvmgen.Field
+ """ Creates a new field accessed via the jvm.Field
descriptor 'fieldobj'. Must be called before render()."""
- assert not self.rendered and isinstance(fieldobj, jvmgen.Field)
+ assert not self.rendered and isinstance(fieldobj, jvm.Field)
self.fields[fieldobj.field_name] = (fieldobj, fielddef)
def add_interface(self, inter):
@@ -848,7 +846,7 @@
return self.super_class.lookup_field(fieldnm)
def lookup_method(self, methodnm):
- """ Given the method name, returns a jvmgen.Method object """
+ """ Given the method name, returns a jvm.Method object """
if methodnm in self.methods:
return self.methods[methodnm].method()
if methodnm in self.abstract_methods:
@@ -864,7 +862,7 @@
def add_abstract_method(self, jmethod):
""" Adds an abstract method to our list of methods; jmethod should
- be a jvmgen.Method object """
+ be a jvm.Method object """
assert jmethod.method_name not in self.methods
self.abstract_methods[jmethod.method_name] = jmethod
@@ -912,7 +910,7 @@
"""
interlink: the JvmType of the Interlink implementation
name: the name of the method
- helper: a jvmgen.Method object for the helper func we should invoke
+ helper: a jvm.Method object for the helper func we should invoke
"""
self.interlink = interlink
self.name = name
@@ -926,7 +924,7 @@
else:
self.return_type = self.helper.return_type
- self.method_obj = jvmgen.Method.v(interlink,
+ self.method_obj = jvm.Method.v(interlink,
self.name,
self.helper.argument_types,
self.return_type)
Modified: pypy/dist/pypy/translator/jvm/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/opcodes.py (original)
+++ pypy/dist/pypy/translator/jvm/opcodes.py Fri Apr 4 15:10:29 2008
@@ -6,7 +6,7 @@
"""
from pypy.translator.oosupport.metavm import \
- PushArg, PushAllArgs, StoreResult, InstructionList, New, DoNothing, Call,\
+ PushArg, PushAllArgs, StoreResult, InstructionList, New, OONewArray, DoNothing, Call,\
SetField, GetField, DownCast, RuntimeNew, OOString, OOUnicode, \
CastTo, PushPrimitive
from pypy.translator.jvm.metavm import \
@@ -15,19 +15,18 @@
from pypy.rpython.ootypesystem import ootype
from pypy.translator.jvm.cmpopcodes import cmp_opname
-import pypy.translator.jvm.generator as jvmgen
-import pypy.translator.jvm.typesystem as jvmtype
+import pypy.translator.jvm.typesystem as jvm
def _proc(val):
if isinstance(val, list):
# Lists of instructions we leave alone:
return InstructionList(val)
- elif isinstance(val, jvmgen.Method) and not val.is_static():
+ elif isinstance(val, jvm.Method) and not val.is_static():
# For virtual methods, we first push an instance of the relevant
# class, then the arguments, and then invoke the method. Note
# that we only allow virtual methods of certain pre-designated
# classes to be in the table.
- if val.class_name == jvmtype.jPyPy.name:
+ if val.class_name == jvm.jPyPy.name:
return InstructionList(
(PushPyPy, PushAllArgs, val, StoreResult))
else:
@@ -71,6 +70,7 @@
opcodes = _proc_dict({
# __________ object oriented operations __________
'new': [New, StoreResult],
+ 'oonewarray': [OONewArray, StoreResult],
'runtimenew': [RuntimeNew, StoreResult],
'oosetfield': [SetField],
'oogetfield': [GetField, StoreResult],
@@ -78,19 +78,19 @@
'ooupcast': DoNothing,
'oodowncast': [DownCast, StoreResult],
'instanceof': [CastTo, StoreResult],
- 'subclassof': [PushAllArgs, jvmgen.SWAP, jvmgen.CLASSISASSIGNABLEFROM, StoreResult],
- 'ooidentityhash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult],
- 'oohash': [PushAllArgs, jvmgen.OBJHASHCODE, StoreResult],
+ 'subclassof': [PushAllArgs, jvm.SWAP, jvm.CLASSISASSIGNABLEFROM, StoreResult],
+ 'ooidentityhash': [PushAllArgs, jvm.OBJHASHCODE, StoreResult],
+ 'oohash': [PushAllArgs, jvm.OBJHASHCODE, StoreResult],
'oostring': [OOString, StoreResult],
'oounicode': [OOUnicode, StoreResult],
- 'ooparse_float': jvmgen.PYPYOOPARSEFLOAT,
+ 'ooparse_float': jvm.PYPYOOPARSEFLOAT,
'oonewcustomdict': [NewCustomDict, StoreResult],
'same_as': DoNothing,
'hint': [PushArg(0), StoreResult],
'direct_call': [Call, StoreResult],
'indirect_call': [PushAllArgs, IndirectCall, StoreResult],
- 'gc__collect': jvmgen.SYSTEMGC,
+ 'gc__collect': jvm.SYSTEMGC,
'gc_set_max_heap_size': Ignore,
'resume_point': Ignore,
@@ -100,100 +100,100 @@
'bool_not': 'logical_not',
- 'int_neg': jvmgen.INEG,
- 'int_neg_ovf': jvmgen.INEGOVF,
+ 'int_neg': jvm.INEG,
+ 'int_neg_ovf': jvm.INEGOVF,
'int_abs': 'iabs',
- 'int_abs_ovf': jvmgen.IABSOVF,
+ 'int_abs_ovf': jvm.IABSOVF,
'int_invert': 'bitwise_negate',
- 'int_add': jvmgen.IADD,
- 'int_sub': jvmgen.ISUB,
- 'int_mul': jvmgen.IMUL,
- 'int_floordiv': jvmgen.IDIV,
- 'int_floordiv_zer': _check_zer(jvmgen.IDIV),
- 'int_mod': jvmgen.IREM,
- 'int_and': jvmgen.IAND,
- 'int_or': jvmgen.IOR,
- 'int_lshift': jvmgen.ISHL,
- 'int_rshift': jvmgen.ISHR,
- 'int_xor': jvmgen.IXOR,
- 'int_add_ovf': jvmgen.IADDOVF,
- 'int_add_nonneg_ovf': jvmgen.IADDOVF,
- 'int_sub_ovf': jvmgen.ISUBOVF,
- 'int_mul_ovf': jvmgen.IMULOVF,
- 'int_floordiv_ovf': jvmgen.IDIV, # these can't overflow!
- 'int_mod_zer': _check_zer(jvmgen.IREM),
- 'int_mod_ovf': jvmgen.IREMOVF,
- 'int_and_ovf': jvmgen.IAND,
- 'int_or_ovf': jvmgen.IOR,
-
- 'int_lshift_ovf': jvmgen.ISHLOVF,
- 'int_lshift_ovf_val': jvmgen.ISHLOVF, # VAL... what is val used for??
-
- 'int_rshift_ovf': jvmgen.ISHR, # these can't overflow!
- 'int_xor_ovf': jvmgen.IXOR,
- 'int_floordiv_ovf_zer': _check_zer(jvmgen.IDIV),
- 'int_mod_ovf_zer': _check_zer(jvmgen.IREMOVF),
+ 'int_add': jvm.IADD,
+ 'int_sub': jvm.ISUB,
+ 'int_mul': jvm.IMUL,
+ 'int_floordiv': jvm.IDIV,
+ 'int_floordiv_zer': _check_zer(jvm.IDIV),
+ 'int_mod': jvm.IREM,
+ 'int_and': jvm.IAND,
+ 'int_or': jvm.IOR,
+ 'int_lshift': jvm.ISHL,
+ 'int_rshift': jvm.ISHR,
+ 'int_xor': jvm.IXOR,
+ 'int_add_ovf': jvm.IADDOVF,
+ 'int_add_nonneg_ovf': jvm.IADDOVF,
+ 'int_sub_ovf': jvm.ISUBOVF,
+ 'int_mul_ovf': jvm.IMULOVF,
+ 'int_floordiv_ovf': jvm.IDIV, # these can't overflow!
+ 'int_mod_zer': _check_zer(jvm.IREM),
+ 'int_mod_ovf': jvm.IREMOVF,
+ 'int_and_ovf': jvm.IAND,
+ 'int_or_ovf': jvm.IOR,
+
+ 'int_lshift_ovf': jvm.ISHLOVF,
+ 'int_lshift_ovf_val': jvm.ISHLOVF, # VAL... what is val used for??
+
+ 'int_rshift_ovf': jvm.ISHR, # these can't overflow!
+ 'int_xor_ovf': jvm.IXOR,
+ 'int_floordiv_ovf_zer': _check_zer(jvm.IDIV),
+ 'int_mod_ovf_zer': _check_zer(jvm.IREMOVF),
'uint_invert': 'bitwise_negate',
- 'uint_add': jvmgen.IADD,
- 'uint_sub': jvmgen.ISUB,
- 'uint_mul': jvmgen.PYPYUINTMUL,
- 'uint_div': jvmgen.PYPYUINTDIV,
+ 'uint_add': jvm.IADD,
+ 'uint_sub': jvm.ISUB,
+ 'uint_mul': jvm.PYPYUINTMUL,
+ 'uint_div': jvm.PYPYUINTDIV,
'uint_truediv': None, # TODO
- 'uint_floordiv': jvmgen.PYPYUINTDIV,
- 'uint_mod': jvmgen.PYPYUINTMOD,
- 'uint_and': jvmgen.IAND,
- 'uint_or': jvmgen.IOR,
- 'uint_lshift': jvmgen.ISHL,
- 'uint_rshift': jvmgen.IUSHR,
- 'uint_xor': jvmgen.IXOR,
+ 'uint_floordiv': jvm.PYPYUINTDIV,
+ 'uint_mod': jvm.PYPYUINTMOD,
+ 'uint_and': jvm.IAND,
+ 'uint_or': jvm.IOR,
+ 'uint_lshift': jvm.ISHL,
+ 'uint_rshift': jvm.IUSHR,
+ 'uint_xor': jvm.IXOR,
- 'float_neg': jvmgen.DNEG,
+ 'float_neg': jvm.DNEG,
'float_abs': 'dbl_abs',
- 'float_add': jvmgen.DADD,
- 'float_sub': jvmgen.DSUB,
- 'float_mul': jvmgen.DMUL,
- 'float_truediv': jvmgen.DDIV,
-
- 'llong_neg': jvmgen.LNEG,
- 'llong_neg_ovf': jvmgen.LNEGOVF,
- 'llong_abs': jvmgen.MATHLABS,
- 'llong_abs_ovf': jvmgen.LABSOVF,
- 'llong_invert': jvmgen.PYPYLONGBITWISENEGATE,
-
- 'llong_add': jvmgen.LADD,
- 'llong_sub': jvmgen.LSUB,
- 'llong_mul': jvmgen.LMUL,
- 'llong_div': jvmgen.LDIV,
+ 'float_add': jvm.DADD,
+ 'float_sub': jvm.DSUB,
+ 'float_mul': jvm.DMUL,
+ 'float_truediv': jvm.DDIV,
+
+ 'llong_neg': jvm.LNEG,
+ 'llong_neg_ovf': jvm.LNEGOVF,
+ 'llong_abs': jvm.MATHLABS,
+ 'llong_abs_ovf': jvm.LABSOVF,
+ 'llong_invert': jvm.PYPYLONGBITWISENEGATE,
+
+ 'llong_add': jvm.LADD,
+ 'llong_sub': jvm.LSUB,
+ 'llong_mul': jvm.LMUL,
+ 'llong_div': jvm.LDIV,
'llong_truediv': None, # TODO
- 'llong_floordiv': jvmgen.LDIV,
- 'llong_floordiv_zer': _check_zer(jvmgen.LDIV),
- 'llong_mod': jvmgen.LREM,
- 'llong_mod_zer': _check_zer(jvmgen.LREM),
- 'llong_and': jvmgen.LAND,
- 'llong_or': jvmgen.LOR,
- 'llong_lshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHL, StoreResult], # XXX - do we care about shifts of >(1<<32) bits??
- 'llong_rshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHR, StoreResult],
- 'llong_xor': jvmgen.LXOR,
- 'llong_floordiv_ovf': jvmgen.LDIV, # these can't overflow!
- 'llong_mod_ovf': jvmgen.LREMOVF,
- 'llong_lshift_ovf': jvmgen.LSHLOVF,
-
- 'ullong_invert': jvmgen.PYPYLONGBITWISENEGATE,
-
- 'ullong_add': jvmgen.LADD,
- 'ullong_sub': jvmgen.LSUB,
- 'ullong_mul': jvmgen.LMUL,
- 'ullong_div': jvmgen.LDIV, # valid?
+ 'llong_floordiv': jvm.LDIV,
+ 'llong_floordiv_zer': _check_zer(jvm.LDIV),
+ 'llong_mod': jvm.LREM,
+ 'llong_mod_zer': _check_zer(jvm.LREM),
+ 'llong_and': jvm.LAND,
+ 'llong_or': jvm.LOR,
+ 'llong_lshift': [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult],
+ 'llong_rshift': [PushAllArgs, jvm.L2I, jvm.LSHR, StoreResult],
+ 'llong_xor': jvm.LXOR,
+ 'llong_floordiv_ovf': jvm.LDIV, # these can't overflow!
+ 'llong_mod_ovf': jvm.LREMOVF,
+ 'llong_lshift_ovf': jvm.LSHLOVF,
+
+ 'ullong_invert': jvm.PYPYLONGBITWISENEGATE,
+
+ 'ullong_add': jvm.LADD,
+ 'ullong_sub': jvm.LSUB,
+ 'ullong_mul': jvm.LMUL,
+ 'ullong_div': jvm.LDIV, # valid?
'ullong_truediv': None, # TODO
- 'ullong_floordiv': jvmgen.LDIV, # valid?
- 'ullong_mod': jvmgen.PYPYULONGMOD,
- 'ullong_lshift': [PushAllArgs, jvmgen.L2I, jvmgen.LSHL, StoreResult],
- 'ullong_rshift': [PushAllArgs, jvmgen.L2I, jvmgen.LUSHR, StoreResult],
- 'ullong_mod_zer': jvmgen.PYPYULONGMOD,
+ 'ullong_floordiv': jvm.LDIV, # valid?
+ 'ullong_mod': jvm.PYPYULONGMOD,
+ 'ullong_lshift': [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult],
+ 'ullong_rshift': [PushAllArgs, jvm.L2I, jvm.LUSHR, StoreResult],
+ 'ullong_mod_zer': jvm.PYPYULONGMOD,
# when casting from bool we want that every truth value is casted
# to 1: we can't simply DoNothing, because the CLI stack could
@@ -201,21 +201,21 @@
# trick. #THIS COMMENT NEEDS TO BE VALIDATED AND UPDATED
'cast_bool_to_int': DoNothing,
'cast_bool_to_uint': DoNothing,
- 'cast_bool_to_float': jvmgen.PYPYBOOLTODOUBLE, #PAUL, inefficient
+ 'cast_bool_to_float': jvm.PYPYBOOLTODOUBLE, #PAUL, inefficient
'cast_char_to_int': DoNothing,
'cast_unichar_to_int': DoNothing,
'cast_int_to_char': DoNothing,
'cast_int_to_unichar': DoNothing,
'cast_int_to_uint': DoNothing,
- 'cast_int_to_float': jvmgen.I2D,
- 'cast_int_to_longlong': jvmgen.I2L,
+ 'cast_int_to_float': jvm.I2D,
+ 'cast_int_to_longlong': jvm.I2L,
'cast_uint_to_int': DoNothing,
- 'cast_uint_to_float': jvmgen.PYPYUINTTODOUBLE,
- 'cast_float_to_int': jvmgen.D2I,
- 'cast_float_to_longlong': jvmgen.PYPYDOUBLETOLONG, #PAUL
- 'cast_float_to_uint': jvmgen.PYPYDOUBLETOUINT,
- 'truncate_longlong_to_int': jvmgen.L2I,
- 'cast_longlong_to_float': jvmgen.L2D,
+ 'cast_uint_to_float': jvm.PYPYUINTTODOUBLE,
+ 'cast_float_to_int': jvm.D2I,
+ 'cast_float_to_longlong': jvm.PYPYDOUBLETOLONG, #PAUL
+ 'cast_float_to_uint': jvm.PYPYDOUBLETOUINT,
+ 'truncate_longlong_to_int': jvm.L2I,
+ 'cast_longlong_to_float': jvm.L2D,
'cast_primitive': [PushAllArgs, CastPrimitive, StoreResult],
'is_early_constant': [PushPrimitive(ootype.Bool, False), StoreResult]
Modified: pypy/dist/pypy/translator/jvm/prebuiltnodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/prebuiltnodes.py (original)
+++ pypy/dist/pypy/translator/jvm/prebuiltnodes.py Fri Apr 4 15:10:29 2008
@@ -57,7 +57,7 @@
def create_interlink_node(db):
""" Translates the create_interlink_impl() function and returns
- a jvmgen.Method object that allows it to be called. """
+ a jvm.Method object that allows it to be called. """
translator = db.genoo.translator
for func, type_list in HELPERS.items():
Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java
==============================================================================
--- pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java (original)
+++ pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java Fri Apr 4 15:10:29 2008
@@ -7,6 +7,7 @@
import java.util.Arrays;
import java.util.Map;
import java.text.DecimalFormat;
+import java.lang.reflect.Array;
/**
* Class with a number of utility routines. One instance of this is
@@ -407,7 +408,16 @@
sb.append("]");
return sb.toString();
}
- else if (o instanceof String) {
+ if (o.getClass().isArray()) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[");
+ for (int i = 0; i < Array.getLength(o); i++) {
+ sb.append(serializeObject(Array.get(o, i))).append(",");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+ if (o instanceof String) {
return escaped_string((String)o);
}
return o.toString();
@@ -731,7 +741,7 @@
return str.substring(start, end);
}
- public static ArrayList ll_split_chr(String str, char c) {
+ public static Object[] ll_split_chr(String str, char c) {
ArrayList list = new ArrayList();
int lastidx = 0, idx = 0;
while ((idx = str.indexOf(c, lastidx)) != -1)
@@ -741,7 +751,7 @@
lastidx = idx+1;
}
list.add(str.substring(lastidx));
- return list;
+ return list.toArray(new String[list.size()]);
}
public static String ll_substring(String str, int start, int cnt) {
Modified: pypy/dist/pypy/translator/jvm/test/test_class.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_class.py (original)
+++ pypy/dist/pypy/translator/jvm/test/test_class.py Fri Apr 4 15:10:29 2008
@@ -24,7 +24,8 @@
assert self.interpret(fn, [2]) == 42
-
+ def test_specialize_methods(self):
+ py.test.skip('ABSTRACT METHOD FIX: RE-TEST AFTER MERGE')
class TestJvmSpecialCase(JvmTest, BaseTestSpecialcase):
pass
Modified: pypy/dist/pypy/translator/jvm/test/test_list.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_list.py (original)
+++ pypy/dist/pypy/translator/jvm/test/test_list.py Fri Apr 4 15:10:29 2008
@@ -15,4 +15,17 @@
return lst[0]
res = self.interpret(fn, [])
assert res == 0
+
+ def test_bool_fixed_list(self):
+ """ Tests that we handle boolean fixed lists, which do not require
+ boxing or unboxing """
+ def fn(i):
+ lst = [False, True]
+ if lst[i]:
+ return 22
+ else:
+ return 44
+ for i in range(0,2):
+ res = self.interpret(fn, [i])
+ assert res == fn(i)
Modified: pypy/dist/pypy/translator/jvm/typesystem.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/typesystem.py (original)
+++ pypy/dist/pypy/translator/jvm/typesystem.py Fri Apr 4 15:10:29 2008
@@ -1,33 +1,28 @@
"""
-Definition and some basic translations between PyPy ootypesystem and
-JVM type system.
-
-Here are some tentative non-obvious decisions:
-
-Signed scalar types mostly map as is.
-
-Unsigned scalar types are a problem; the basic idea is to store them
-as signed values, but execute special code when working with them. Another
-option would be to use classes, or to use the "next larger" type and remember to use appropriate modulos. The jury is out on
-this. Another idea would be to add a variant type system that does
-not have unsigned values, and write the required helper and conversion
-methods in RPython --- then it could be used for multiple backends.
-
-Python strings are mapped to byte arrays, not Java Strings, since
-Python strings are really sets of bytes, not unicode code points.
-Jury is out on this as well; this is not the approach taken by cli,
-for example.
-
-Python Unicode strings, on the other hand, map directly to Java Strings.
-
-WeakRefs are mapped to a thin wrapper class, PyPyWeakRef, to allow for
-mutation of the object being referenced (the ll_set method).
-
-Collections can hopefully map to Java collections instances. Note
-that JVM does not have an idea of generic typing at its lowest level
-(well, they do have signature attributes, but those don't really count
-for much).
+Defines the basic structures which are used to represent JVM abstraction,
+such as Java types, fields, methods and opcodes.
+The structures in this file generally two different, but related,
+roles. First, they describe a JVM abstraction. For example, jObject
+describes some of the properties of the built-in class
+java.lang.Object. Second, they can represent the concrete realization
+of an OOTYPE construct. For example, JvmType instances are used to
+represent the translated class which will be generated for some OOTYPE
+class.
+
+This file itself is intended to be imported from a wide variety of
+locations, and thus generally restricts itself to classes and global
+variables that describe intrinsic parts of the JVM. For example,
+there are objects representing different opcodes, type definitions for
+built-in types like java.lang.Object and java.lang.System, and
+method/field declarations for well-known methods and fields on those
+types.
+
+Other files extend this set with objects that represent the JVM
+realization of some OOTYPE construct. For example, the module
+builtin.py describes the JVM types that are used to define the
+built-in OOTYPE types, such as lists or dictionaries. The module
+node.py contains code for representing user-defined classes.
"""
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.ootypesystem import ootype
@@ -69,8 +64,11 @@
def int_class_name(self):
""" Converts a descriptor like Ljava/lang/Object; to
internal class name java/lang/Object """
- assert self[0] == 'L' and self[-1] == ';'
- return self[1:-1]
+ if self[0] == 'L' and self[-1] == ';':
+ return self[1:-1]
+ else:
+ assert self.startswith('[')
+ return self
def type_width(self):
""" Returns number of JVM words this type takes up. JVM words
are a theoretically abstract quantity that basically
@@ -102,6 +100,13 @@
# ______________________________________________________________________
# Basic JVM Types
+#
+# As described above, some of these define well-known types in the JVM
+# or standard Java library. In addition, there are subtypes of
+# JvmType which represent the translated version of some RPython
+# class, such as a list, dictionary, or user-defined class. Those
+# subtypes are generally defined in other modules, as they have
+# dependencies that would cause circular imports.
class JvmType(object):
"""
@@ -116,15 +121,23 @@
# (None for scalars and arrays)
def lookup_field(self, fieldnm):
- """ If the class has a field named 'fieldnm', returns a
- jvmgen.Field or jvmgen.Property object that represents it and can
- be used with the interpreter to load/store it. If no such field
- exists, or this is not a class, then raises KeyError. """
+ """ Returns a Field or Property object that represents the
+ field named 'fieldnm', or raises KeyError if no such field
+ exists. 'fieldnm' generally represents an OOTYPE field, and
+ thus this method is generally not implemenented by the JvmType
+ classes that just represent native Java classes, even if they
+ have fields. Instead, such fields are described as global
+ Field constants, either in this file or elsewhere. """
raise NotImplementedException
+
def lookup_method(self, methodnm):
- """ Returns a jvm.generator.Method object representing the method
- with the given name, or raises KeyError if that field does not
- exist on this type. """
+ """ Returns a BaseMethod object that represents the method
+ named 'methodnm', or raises KeyError if no such field exists.
+ 'methodnm' represents an OOTYPE method, and thus this method
+ is generally not implemenented by the JvmType classes that
+ just represent native Java classes, even if they have methods.
+ Instead, such methods are described as global Method constants
+ in this file, either in this file or elsewhere. """
raise NotImplementedException
def is_generated(self):
@@ -226,22 +239,6 @@
jByte = JvmScalarType('B', jByteClass, 'byteValue')
jChar = JvmScalarType('C', jCharClass, 'charValue')
-class JvmArrayType(JvmType):
- """
- Subclass used for all array instances.
- """
- def __init__(self, elemtype):
- JvmType.__init__(self, desc_for_array_of(elemtype.descriptor))
- self.element_type = elemtype
- def lookup_field(self, fieldnm):
- raise KeyError(fieldnm) # TODO adjust interface to permit opcode here
- def lookup_method(self, methodnm):
- raise KeyError(methodnm) # Arrays have no methods
-
-jByteArray = JvmArrayType(jByte)
-jObjectArray = JvmArrayType(jObject)
-jStringArray = JvmArrayType(jString)
-
class Generifier(object):
"""
@@ -263,7 +260,7 @@
if hasattr(self.OOTYPE, 'SELFTYPE_T'):
self.generics[self.OOTYPE.SELFTYPE_T] = (self.OOTYPE,self.OOTYPE)
- for pname,pval in (('ITEMTYPE_T', '_ITEMTYPE'),
+ for pname,pval in (('ITEMTYPE_T', 'ITEM'),
('KEYTYPE_T', '_KEYTYPE'),
('VALUETYPE_T', '_VALUETYPE')):
if hasattr(self.OOTYPE, pname):
@@ -301,7 +298,7 @@
# Java Callback Interfaces
#
# A list of interfaces which static functions that we generate will
-# automatically implement if application. See the pypy/Callback.java,
+# automatically implement if applicable. See the pypy/Callback.java,
# node.py/StaticMethodInterface for more information.
jCallbackInterfaces = [] # collects all of the defined JvmCallbackInterfaces
@@ -351,10 +348,630 @@
return self.methods[methname]
def _add_methods(self):
- from pypy.translator.jvm.generator import Method
for methname, methspec in self.OOTYPE._class_._methods.items():
argtypes = [self.db.annotation_to_cts(arg._type) for arg in
methspec.args]
restype = self.db.annotation_to_cts(methspec.retval._type)
self.methods[methname] = Method.v(self, methname,
argtypes, restype)
+
+# ______________________________________________________________________
+# The bridge between RPython array and JVM arrays. The main differences
+# are that (a) RPython has arrays of void type, and (b) RPython arrays
+# have methods, whereas Java methods don't. We inline those methods
+# into the appropriate bytecode.
+
+class _JvmVoidArray(JvmClassType):
+ """
+ A special case for void arrays. These are represented by an instance
+ of the VoidArray class, which implements the required methods.
+ """
+
+ method_types = {
+ 'll_length': ([], jInt),
+ 'll_getitem_fast': ([jInt], jVoid),
+ 'll_setitem_fast': ([jInt], jVoid),
+ }
+
+ def __init__(self):
+ JvmClassType.__init__(self, 'pypy.VoidArray')
+
+ def make(self, gen):
+ # Construct a new VoidArray object, assuming the length has
+ # been pushed onto the stack already.
+ gen.emit(PYPYVOIDARRAYMAKE)
+
+ def lookup_field(self, fieldnm):
+ raise KeyError(fieldnm) # no fields
+
+ def lookup_method(self, methodnm):
+ jargtypes, jrettype = self.method_types[methodnm]
+ return Method.v(self, methodnm, jargtypes, jrettype)
+
+class JvmArrayType(JvmType):
+ """
+ Subclass used for all array instances.
+ """
+ def __init__(self, elemtype):
+ JvmType.__init__(self, desc_for_array_of(elemtype.descriptor))
+ self.element_type = elemtype
+ def make(self, gen):
+ # Issues the opcode to build a new array of the appropriate type.
+ # Assumes the length has been pushed onto the stack already.
+ gen.emit(NEWARRAY.for_type(self))
+ def lookup_field(self, fieldnm):
+ raise KeyError(fieldnm)
+ def lookup_method(self, methodnm):
+ # Arrays don't have methods in Java, but they do in the ootype system
+ if methodnm == "ll_length":
+ return OpcodeMethod([], jInt, ARRAYLENGTH)
+ elif methodnm == "ll_getitem_fast":
+ return OpcodeMethod([jInt], self.element_type,
+ ARRLOAD.for_type(self.element_type))
+ elif methodnm == "ll_setitem_fast":
+ return OpcodeMethod([jInt, self.element_type], jVoid,
+ ARRSTORE.for_type(self.element_type))
+ else:
+ raise KeyError(methodnm)
+
+jBoolArray = JvmArrayType(jBool)
+jByteArray = JvmArrayType(jByte)
+jObjectArray = JvmArrayType(jObject)
+jStringArray = JvmArrayType(jString)
+jDoubleArray = JvmArrayType(jDouble)
+jCharArray = JvmArrayType(jChar)
+jIntArray = JvmArrayType(jInt)
+jVoidArray = _JvmVoidArray()
+
+# ______________________________________________________________________
+# Opcodes
+#
+# Objects describing the various opcodes which we use. In some cases,
+# there are also opcode families, which consist of a set of related
+# opcodes that are specialized by the types they operate on (i.e.,
+# IADD, DADD, etc).
+
+class Opcode(object):
+ def __init__(self, jvmstr):
+ """
+ flags is a set of flags (see above) that describe opcode #UPDATE
+ jvmstr is the name for jasmin printouts
+ """
+ self.jvmstr = jvmstr
+ self.flags = None #Should flags be added to args?
+
+ def __repr__(self):
+ return "<Opcode %s:%x>" % (self.jvmstr, self.flags)
+
+ def specialize(self, args):
+ """ Process the argument list according to the various flags.
+ Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing
+ the new opcode, and ARGS is a list of arguments or empty tuple.
+ Most of these do not do anything. """
+ return (self.jvmstr, args)
+
+class IntConstOpcode(Opcode):
+ """ The ICONST opcode specializes itself for small integer opcodes. """
+ def specialize(self, args):
+ assert len(args) == 1
+ if args[0] == -1:
+ return self.jvmstr + "_m1", ()
+ elif args[0] >= 0 and args[0] <= 5:
+ return self.jvmstr + "_" + str(args[0]), ()
+ # Non obvious: convert ICONST to LDC if the constant is out of
+ # range
+ return "ldc", args
+
+class VarOpcode(Opcode):
+ """ An Opcode which takes a variable index as an argument; specialized
+ to small integer indices. """
+ def specialize(self, args):
+ assert len(args) == 1
+ if args[0] >= 0 and args[0] <= 3:
+ return self.jvmstr + "_" + str(args[0]), ()
+ return Opcode.specialize(self, args)
+
+class IntClassNameOpcode(Opcode):
+ """ An opcode which takes an internal class name as its argument;
+ the actual argument will be a JvmType instance. """
+ def specialize(self, args):
+ args = [args[0].descriptor.int_class_name()]
+ return self.jvmstr, args
+
+class OpcodeFamily(object):
+ """
+ Many opcodes in JVM have variants that depend on the type of the
+ operands; for example, one must choose the correct ALOAD, ILOAD,
+ or DLOAD depending on whether one is loading a reference, integer,
+ or double variable respectively. Each instance of this class
+ defines one 'family' of opcodes, such as the LOAD family shown
+ above, and produces Opcode objects specific to a particular type.
+ """
+ def __init__(self, opcclass, suffix):
+ """
+ opcclass is the opcode subclass to use (see above) when
+ instantiating a particular opcode
+
+ jvmstr is the name for jasmin printouts
+ """
+ self.opcode_class = opcclass
+ self.suffix = suffix
+ self.cache = {}
+
+ def _o(self, prefix):
+ try:
+ return self.cache[prefix]
+ except KeyError:
+ self.cache[prefix] = obj = self.opcode_class(
+ prefix+self.suffix)
+ return obj
+
+ def for_type(self, argtype):
+ """ Returns a customized opcode of this family appropriate to
+ 'argtype', a JvmType object. """
+
+ desc = argtype.descriptor
+
+ # These are always true:
+ if desc[0] == 'L': return self._o("a") # Objects
+ if desc[0] == '[': return self._o("a") # Arrays
+ if desc == 'I': return self._o("i") # Integers
+ if desc == 'J': return self._o("l") # Integers
+ if desc == 'D': return self._o("d") # Doubles
+ if desc == 'V': return self._o("") # Void [used by RETURN]
+
+ # Chars/Bytes/Booleans are normally represented as ints
+ # in the JVM, but some opcodes are different. They use a
+ # different OpcodeFamily (see ArrayOpcodeFamily for ex)
+ if desc == 'C': return self._o("i") # Characters
+ if desc == 'B': return self._o("i") # Bytes
+ if desc == 'Z': return self._o("i") # Boolean
+
+ assert False, "Unknown argtype=%s" % repr(argtype)
+ raise NotImplementedError
+
+class ArrayOpcodeFamily(OpcodeFamily):
+ """ Opcode family specialized for array access instr """
+ def for_type(self, argtype):
+ desc = argtype.descriptor
+ if desc == 'J': return self._o("l") # Integers
+ if desc == 'D': return self._o("d") # Doubles
+ if desc == 'C': return self._o("c") # Characters
+ if desc == 'B': return self._o("b") # Bytes
+ if desc == 'Z': return self._o("b") # Boolean (access as bytes)
+ return OpcodeFamily.for_type(self, argtype)
+
+class NewArrayOpcodeFamily(object):
+ def __init__(self):
+ self.cache = {}
+
+ def for_type(self, arraytype):
+ try:
+ return self.cache[arraytype]
+ except KeyError:
+ pass
+ desc = arraytype.descriptor
+ if desc == '[I':
+ s = "newarray int"
+ elif desc == '[D':
+ s = "newarray double"
+ elif desc == '[C':
+ s = "newarray char"
+ elif desc == '[B':
+ s = "newarray byte"
+ elif desc == '[Z':
+ s = "newarray boolean"
+ else:
+ s = "anewarray " + arraytype.element_type.descriptor.int_class_name()
+ self.cache[arraytype] = obj = Opcode(s)
+ return obj
+
+NEWARRAY = NewArrayOpcodeFamily()
+ARRAYLENGTH = Opcode("arraylength")
+
+# Define the opcodes for IFNE, IFEQ, IFLT, IF_ICMPLT, etc. The IFxx
+# variants compare a single integer arg against 0, and the IF_ICMPxx
+# variants compare 2 integer arguments against each other.
+for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'):
+ ifop = "if%s" % cmpop
+ if_icmpop = "if_icmp%s" % cmpop
+ globals()[ifop.upper()] = Opcode(ifop)
+ globals()[if_icmpop.upper()] = Opcode(if_icmpop)
+
+# Compare references, either against NULL or against each other
+IFNULL = Opcode('ifnull')
+IFNONNULL = Opcode('ifnonnull')
+IF_ACMPEQ = Opcode('if_acmpeq')
+IF_ACMPNE = Opcode('if_acmpne')
+
+# Method invocation
+INVOKESTATIC = Opcode('invokestatic')
+INVOKEVIRTUAL = Opcode('invokevirtual')
+INVOKESPECIAL = Opcode('invokespecial')
+INVOKEINTERFACE = Opcode('invokeinterface')
+
+# Other opcodes
+LDC = Opcode('ldc') # single-word types
+LDC2 = Opcode('ldc2_w') # double-word types: doubles and longs
+GOTO = Opcode('goto')
+ICONST = IntConstOpcode('iconst')
+ICONST_0 = Opcode('iconst_0') # sometimes convenient to refer to this directly
+ACONST_NULL=Opcode('aconst_null')
+DCONST_0 = Opcode('dconst_0')
+DCONST_1 = Opcode('dconst_1')
+LCONST_0 = Opcode('lconst_0')
+LCONST_1 = Opcode('lconst_1')
+GETFIELD = Opcode('getfield')
+PUTFIELD = Opcode('putfield')
+GETSTATIC = Opcode('getstatic')
+PUTSTATIC = Opcode('putstatic')
+CHECKCAST = IntClassNameOpcode('checkcast')
+INEG = Opcode('ineg')
+IXOR = Opcode('ixor')
+IADD = Opcode('iadd')
+ISUB = Opcode('isub')
+IMUL = Opcode('imul')
+IDIV = Opcode('idiv')
+IREM = Opcode('irem')
+IAND = Opcode('iand')
+IOR = Opcode('ior')
+ISHL = Opcode('ishl')
+ISHR = Opcode('ishr')
+IUSHR = Opcode('iushr')
+LCMP = Opcode('lcmp')
+DCMPG = Opcode('dcmpg')
+DCMPL = Opcode('dcmpl')
+NOP = Opcode('nop')
+I2D = Opcode('i2d')
+I2L = Opcode('i2l')
+D2I= Opcode('d2i')
+#D2L= Opcode('d2l') #PAUL
+L2I = Opcode('l2i')
+L2D = Opcode('l2d')
+ATHROW = Opcode('athrow')
+DNEG = Opcode('dneg')
+DADD = Opcode('dadd')
+DSUB = Opcode('dsub')
+DMUL = Opcode('dmul')
+DDIV = Opcode('ddiv')
+DREM = Opcode('drem')
+LNEG = Opcode('lneg')
+LADD = Opcode('ladd')
+LSUB = Opcode('lsub')
+LMUL = Opcode('lmul')
+LDIV = Opcode('ldiv')
+LREM = Opcode('lrem')
+LAND = Opcode('land')
+LOR = Opcode('lor')
+LXOR = Opcode('lxor')
+LSHL = Opcode('lshl')
+LSHR = Opcode('lshr')
+LUSHR = Opcode('lushr')
+NEW = IntClassNameOpcode('new')
+DUP = Opcode('dup')
+DUP2 = Opcode('dup2')
+DUP_X1 = Opcode('dup_x1')
+POP = Opcode('pop')
+POP2 = Opcode('pop2')
+SWAP = Opcode('swap')
+INSTANCEOF= IntClassNameOpcode('instanceof')
+# Loading/storing local variables
+LOAD = OpcodeFamily(VarOpcode, "load")
+STORE = OpcodeFamily(VarOpcode, "store")
+RETURN = OpcodeFamily(Opcode, "return")
+
+# Loading/storing from arrays
+# *NOTE*: This family is characterized by the type of the ELEMENT,
+# not the type of the ARRAY.
+#
+# Also: here I break from convention by naming the objects ARRLOAD
+# rather than ALOAD, even though the suffix is 'aload'. This is to
+# avoid confusion with the ALOAD opcode.
+ARRLOAD = ArrayOpcodeFamily(Opcode, "aload")
+ARRSTORE = ArrayOpcodeFamily(Opcode, "astore")
+
+# ______________________________________________________________________
+# Methods and Fields
+#
+# These structures are used throughout the code to refer to JVM
+# methods and fields. Similarly to JvmType instances, they are used
+# both to represent random fields/methods in the JVM, and to represent
+# the translation of an OOTYPE field/method. Therefore, these may not
+# actually generate code corresponding to a real JVM method: for
+# example, arrays use a BaseMethod subclass to generate the
+# appropriate JVM opcodes that correspond to RPython arrays.
+# Likewise, the Property class (see below) allows us to use a pair of
+# JVM methods to represent an OOTYPE field.
+
+class BaseMethod(object):
+ def __init__(self, argtypes, rettype):
+ self.argument_types = argtypes # List of jvmtypes
+ self.return_type = rettype # jvmtype
+
+ def is_static(self):
+ raise NotImplementedError
+
+ def invoke(self, gen):
+ raise NotImplementedError
+
+class OpcodeMethod(BaseMethod):
+ """
+ Represents a "method" that is actually implemented by a single opcode,
+ such as ARRAYLENGTH
+ """
+ def __init__(self, argtypes, rettype, opcode, static=False):
+ """
+ argtypes = an array of jvm types indicating what we expect on stack
+ rettype = the type we will push on the stack (if any)
+ opcode = the opcode to emit
+ static = should we be considered static? if true, then we will
+ not push the receiver onto the stack in metavm
+ """
+ BaseMethod.__init__(self, argtypes, rettype)
+ self.opcode = opcode
+ self.static = static
+
+ def is_static(self):
+ return self.static
+
+ def invoke(self, gen):
+ gen.emit(self.opcode)
+
+class Method(BaseMethod):
+
+ """
+ Represents a method implemented by a genuine JVM method. Unlike
+ OpcodeMethod, when we emit the opcode this class is an argument to
+ it, and contains the extra info about the class/method being
+ invoked that is required.
+ """
+
+ # Create a constructor:
+ def c(classty, argtypes):
+ return Method(classty.name, "<init>", argtypes, jVoid,
+ opcode=INVOKESPECIAL)
+ c = staticmethod(c)
+
+ # Create a virtual or interface method:
+ def v(classty, methnm, argtypes, rettype):
+ """
+ Shorthand to create a virtual method.
+ 'class' - JvmType object for the class
+ 'methnm' - name of the method (Python string)
+ 'argtypes' - list of JvmType objects, one for each argument but
+ not the this ptr
+ 'rettype' - JvmType for return type
+ """
+ assert argtypes is not None
+ assert rettype is not None
+ classnm = classty.name
+ if isinstance(classty, JvmInterfaceType):
+ opc = INVOKEINTERFACE
+ else:
+ assert isinstance(classty, JvmClassType)
+ opc = INVOKEVIRTUAL
+ return Method(classnm, methnm, argtypes, rettype, opcode=opc)
+ v = staticmethod(v)
+
+ # Create a static method:
+ def s(classty, methnm, argtypes, rettype):
+ """
+ Shorthand to create a static method.
+ 'class' - JvmType object for the class
+ 'methnm' - name of the method (Python string)
+ 'argtypes' - list of JvmType objects, one for each argument but
+ not the this ptr
+ 'rettype' - JvmType for return type
+ """
+ assert isinstance(classty, JvmType)
+ classnm = classty.name
+ return Method(classnm, methnm, argtypes, rettype)
+ s = staticmethod(s)
+
+ def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC):
+ BaseMethod.__init__(self, argtypes, rettype)
+ self.opcode = opcode
+ self.class_name = classnm # String, ie. "java.lang.Math"
+ self.method_name = methnm # String "abs"
+
+ # Compute the method descriptior, which is a string like "()I":
+ argtypesdesc = [a.descriptor for a in argtypes]
+ rettypedesc = rettype.descriptor
+ self.descriptor = desc_for_method(argtypesdesc, rettypedesc)
+ def invoke(self, gen):
+ gen._instr(self.opcode, self)
+ def is_static(self):
+ return self.opcode == INVOKESTATIC
+ def jasmin_syntax(self):
+ res = "%s/%s%s" % (self.class_name.replace('.','/'),
+ self.method_name,
+ self.descriptor)
+ # A weird, inexplicable quirk of Jasmin syntax is that it requires
+ # the number of arguments after an invokeinterface call:
+ if self.opcode == INVOKEINTERFACE:
+ res += " %d" % (len(self.argument_types)+1,)
+ return res
+
+class Field(object):
+
+ """
+ Represents an actual JVM field. Use the methods
+ fld.load(gen) / gen.emit(fld)
+ or
+ fld.store(gen)
+ to load the field's value onto the stack, or store into the field.
+ If this is not a static field, you must have pushed the object
+ containing the field and the field's value first.
+
+ See also Property.
+ """
+
+ @staticmethod
+ def i(classty, fieldnm, fieldty, OOTYPE=None):
+ """
+ Shorthand to create an instance field.
+ 'class' - JvmType object for the class containing the field
+ 'fieldnm' - name of the field (Python string)
+ 'fieldty' - JvmType object for the type of the field
+ 'OOTYPE' - optional OOTYPE object for the type of the field
+ """
+ return Field(classty.name, fieldnm, fieldty, False, OOTYPE)
+
+ @staticmethod
+ def s(classty, fieldnm, fieldty, OOTYPE=None):
+ """
+ Shorthand to create a static field.
+ 'class' - JvmType object for the class containing the field
+ 'fieldnm' - name of the field (Python string)
+ 'fieldty' - JvmType object for the type of the field
+ 'OOTYPE' - optional OOTYPE object for the type of the field
+ """
+ return Field(classty.name, fieldnm, fieldty, True, OOTYPE)
+
+ def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None):
+ # All fields are public
+ self.class_name = classnm # String, ie. "java.lang.Math"
+ self.field_name = fieldnm # String "someField"
+ self.OOTYPE = OOTYPE # OOTYPE equivalent of JvmType, may be None
+ self.jtype = jtype # JvmType
+ self.is_static = static # True or False
+ def load(self, gen):
+ if self.is_static:
+ gen._instr(GETSTATIC, self)
+ else:
+ gen._instr(GETFIELD, self)
+ def store(self, gen):
+ if self.is_static:
+ gen._instr(PUTSTATIC, self)
+ else:
+ gen._instr(PUTFIELD, self)
+ def jasmin_syntax(self):
+ return "%s/%s %s" % (
+ self.class_name.replace('.','/'),
+ self.field_name,
+ self.jtype.descriptor)
+
+class Property(object):
+ """
+ An object which acts like a Field, but when a value is loaded or
+ stored it actually invokes accessor methods. Use like a field
+ (prop.load(gen), prop.store(gen), etc).
+ """
+ def __init__(self, field_name, get_method, put_method, OOTYPE=None):
+ self.get_method = get_method
+ self.put_method = put_method
+ self.field_name = field_name
+ self.OOTYPE = OOTYPE
+
+ # Synthesize the Field attributes from the get_method/put_method:
+ self.class_name = get_method.class_name
+ assert put_method.class_name == self.class_name
+ self.jtype = get_method.return_type
+ self.is_static = get_method.is_static
+ def load(self, gen):
+ self.get_method.invoke(gen)
+ def store(self, gen):
+ self.put_method.invoke(gen)
+ # jasmin_syntax is not needed, since this object itself never appears
+ # as an argument an Opcode
+
+# ___________________________________________________________________________
+# Methods
+#
+# "Method" objects describe all the information needed to invoke a
+# method. We create one for each node.Function object, as well as for
+# various helper methods (defined below). To invoke a method, you
+# push its arguments and then use generator.emit(methobj) where
+# methobj is its Method instance.
+
+OBJHASHCODE = Method.v(jObject, 'hashCode', (), jInt)
+OBJTOSTRING = Method.v(jObject, 'toString', (), jString)
+OBJEQUALS = Method.v(jObject, 'equals', (jObject,), jBool)
+SYSTEMGC = Method.s(jSystem, 'gc', (), jVoid)
+INTTOSTRINGI = Method.s(jIntegerClass, 'toString', (jInt,), jString)
+LONGTOSTRINGL = Method.s(jLongClass, 'toString', (jLong,), jString)
+DOUBLETOSTRINGD = Method.s(jDoubleClass, 'toString', (jDouble,), jString)
+CHARTOSTRINGC = Method.s(jCharClass, 'toString', (jChar,), jString)
+MATHIABS = Method.s(jMath, 'abs', (jInt,), jInt)
+IABSOVF = Method.v(jPyPy, 'abs_ovf', (jInt,), jInt)
+MATHLABS = Method.s(jMath, 'abs', (jLong,), jLong)
+LABSOVF = Method.v(jPyPy, 'abs_ovf', (jLong,), jLong)
+MATHDABS = Method.s(jMath, 'abs', (jDouble,), jDouble)
+INEGOVF = Method.v(jPyPy, 'negate_ovf', (jInt,), jInt)
+LNEGOVF = Method.v(jPyPy, 'negate_ovf', (jLong,), jLong)
+IADDOVF = Method.v(jPyPy, 'add_ovf', (jInt, jInt), jInt)
+LADDOVF = Method.v(jPyPy, 'add_ovf', (jLong, jLong), jLong)
+ISUBOVF = Method.v(jPyPy, 'subtract_ovf', (jInt, jInt), jInt)
+LSUBOVF = Method.v(jPyPy, 'subtract_ovf', (jLong, jLong), jLong)
+IMULOVF = Method.v(jPyPy, 'multiply_ovf', (jInt, jInt), jInt)
+LMULOVF = Method.v(jPyPy, 'multiply_ovf', (jLong, jLong), jLong)
+MATHFLOOR = Method.s(jMath, 'floor', (jDouble,), jDouble)
+IFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt)
+LFLOORDIVOVF = Method.v(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong)
+IFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt)
+LFLOORDIVZEROVF = Method.v(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong)
+IREMOVF = Method.v(jPyPy, 'mod_ovf', (jInt, jInt), jInt)
+LREMOVF = Method.v(jPyPy, 'mod_ovf', (jLong, jLong), jLong)
+ISHLOVF = Method.v(jPyPy, 'lshift_ovf', (jInt, jInt), jInt)
+LSHLOVF = Method.v(jPyPy, 'lshift_ovf', (jLong, jLong), jLong)
+MATHDPOW = Method.s(jMath, 'pow', (jDouble, jDouble), jDouble)
+PRINTSTREAMPRINTSTR = Method.v(jPrintStream, 'print', (jString,), jVoid)
+CLASSFORNAME = Method.s(jClass, 'forName', (jString,), jClass)
+CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool)
+STRINGBUILDERAPPEND = Method.v(jStringBuilder, 'append',
+ (jString,), jStringBuilder)
+PYPYUINTCMP = Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt)
+PYPYULONGCMP = Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
+PYPYUINTMOD = Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt)
+PYPYUINTMUL = Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt)
+PYPYUINTDIV = Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt)
+PYPYULONGMOD = Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong)
+PYPYUINTTODOUBLE = Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
+PYPYDOUBLETOUINT = Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
+PYPYDOUBLETOLONG = Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
+PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
+PYPYSTRTOINT = Method.v(jPyPy, 'str_to_int', (jString,), jInt)
+PYPYSTRTOUINT = Method.v(jPyPy, 'str_to_uint', (jString,), jInt)
+PYPYSTRTOLONG = Method.v(jPyPy, 'str_to_long', (jString,), jLong)
+PYPYSTRTOULONG = Method.v(jPyPy, 'str_to_ulong', (jString,), jLong)
+PYPYSTRTOBOOL = Method.v(jPyPy, 'str_to_bool', (jString,), jBool)
+PYPYSTRTODOUBLE = Method.v(jPyPy, 'str_to_double', (jString,), jDouble)
+PYPYSTRTOCHAR = Method.v(jPyPy, 'str_to_char', (jString,), jChar)
+PYPYBOOLTODOUBLE = Method.v(jPyPy, 'bool_to_double', (jBool,), jDouble)
+PYPYDUMP = Method.s(jPyPy, 'dump', (jString,), jVoid)
+PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid)
+PYPYSERIALIZEBOOLEAN = Method.s(jPyPy, 'serialize_boolean', (jBool,), jString)
+PYPYSERIALIZEUINT = Method.s(jPyPy, 'serialize_uint', (jInt,), jString)
+PYPYSERIALIZEULONG = Method.s(jPyPy, 'serialize_ulonglong', (jLong,),jString)
+PYPYSERIALIZEVOID = Method.s(jPyPy, 'serialize_void', (), jString)
+PYPYESCAPEDCHAR = Method.s(jPyPy, 'escaped_char', (jChar,), jString)
+PYPYESCAPEDUNICHAR = Method.s(jPyPy, 'escaped_unichar', (jChar,), jString)
+PYPYESCAPEDSTRING = Method.s(jPyPy, 'escaped_string', (jString,), jString)
+PYPYESCAPEDUNICODE = Method.s(jPyPy, 'escaped_unicode', (jString,), jString)
+PYPYSERIALIZEOBJECT = Method.s(jPyPy, 'serializeObject', (jObject,), jString)
+PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject)
+PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray)
+PYPYARRAYTOLIST = Method.s(jPyPy, 'array_to_list', (jObjectArray,), jArrayList)
+PYPYOOPARSEFLOAT = Method.v(jPyPy, 'ooparse_float', (jString,), jDouble)
+OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass)
+CLASSGETNAME = Method.v(jClass, 'getName', (), jString)
+CUSTOMDICTMAKE = Method.s(jPyPyCustomDict, 'make',
+ (jPyPyEquals, jPyPyHashCode), jPyPyCustomDict)
+PYPYWEAKREFCREATE = Method.s(jPyPyWeakRef, 'create', (jObject,), jPyPyWeakRef)
+PYPYWEAKREFGET = Method.s(jPyPyWeakRef, 'll_get', (), jObject)
+PYPYVOIDARRAYMAKE = Method.s(jVoidArray, 'make', (jInt,), jVoidArray)
+
+# ___________________________________________________________________________
+# Fields
+#
+# Field objects encode information about fields.
+
+SYSTEMOUT = Field.s(jSystem, 'out', jPrintStream)
+SYSTEMERR = Field.s(jSystem, 'err', jPrintStream)
+DOUBLENAN = Field.s(jDoubleClass, 'NaN', jDouble)
+DOUBLEPOSINF = Field.s(jDoubleClass, 'POSITIVE_INFINITY', jDouble)
+DOUBLENEGINF = Field.s(jDoubleClass, 'NEGATIVE_INFINITY', jDouble)
+
+PYPYINTERLINK= Field.i(jPyPy, 'interlink', jPyPyInterlink)
+PYPYOS = Field.i(jPyPy, 'os', jll_os)
+
Modified: pypy/dist/pypy/translator/oosupport/constant.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/constant.py (original)
+++ pypy/dist/pypy/translator/oosupport/constant.py Fri Apr 4 15:10:29 2008
@@ -207,6 +207,8 @@
return genoo.ClassConst(self.db, value, uniq)
elif isinstance(value, ootype._list):
return genoo.ListConst(self.db, value, uniq)
+ elif isinstance(value, ootype._array):
+ return genoo.ArrayConst(self.db, value, uniq)
elif isinstance(value, ootype._static_meth):
return genoo.StaticMethodConst(self.db, value, uniq)
elif isinstance(value, ootype._custom_dict):
@@ -582,7 +584,7 @@
if not self.value:
return
for item in self.value._list:
- self._record_const_if_complex(self.value._TYPE._ITEMTYPE, item)
+ self._record_const_if_complex(self.value._TYPE.ITEM, item)
def create_pointer(self, gen):
assert not self.is_null()
@@ -607,16 +609,12 @@
can be overloaded by the backend if your conditions are wider.
The default is not to initialize if the list is a list of
Void. """
- return self.value._TYPE._ITEMTYPE is ootype.Void
- try:
- return self.value._list == [0] * len(self.value._list)
- except:
- return False
+ return self.value._TYPE.ITEM is ootype.Void
def initialize_data(self, constgen, gen):
assert not self.is_null()
SELFTYPE = self.value._TYPE
- ITEMTYPE = self.value._TYPE._ITEMTYPE
+ ITEM = self.value._TYPE.ITEM
# check for special cases and avoid initialization
if self._do_not_initialize():
@@ -627,11 +625,61 @@
constgen._consider_split_current_function(gen)
gen.dup(SELFTYPE)
push_constant(self.db, ootype.Signed, idx, gen)
- push_constant(self.db, ITEMTYPE, item, gen)
- gen.prepare_generic_argument(ITEMTYPE)
+ push_constant(self.db, ITEM, item, gen)
+ gen.prepare_generic_argument(ITEM)
gen.call_method(SELFTYPE, 'll_setitem_fast')
# ______________________________________________________________________
+# Array constants
+
+class ArrayConst(AbstractConst):
+ def __init__(self, db, list, count):
+ AbstractConst.__init__(self, db, list, count)
+ self.name = 'ARRAY__%d' % count
+
+ def record_dependencies(self):
+ if not self.value:
+ return
+ for item in self.value._array:
+ self._record_const_if_complex(self.value._TYPE.ITEM, item)
+
+ def create_pointer(self, gen):
+ from pypy.objspace.flow.model import Constant
+ assert not self.is_null()
+ SELFTYPE = self.value._TYPE
+
+ # Create the array
+ length = Constant(len(self.value._array), ootype.Signed)
+ gen.oonewarray(SELFTYPE, length)
+
+ def _do_not_initialize(self):
+ """ Returns True if the array should not be initialized; this
+ can be overloaded by the backend if your conditions are wider.
+ The default is not to initialize if the array is a array of
+ Void. """
+ return self.value._TYPE.ITEM is ootype.Void
+
+ def initialize_data(self, constgen, gen):
+ assert not self.is_null()
+ SELFTYPE = self.value._TYPE
+ ITEM = self.value._TYPE.ITEM
+
+ # check for special cases and avoid initialization
+ if self._do_not_initialize():
+ return
+
+ # set each item in the list using the OOTYPE methods
+ for idx, item in enumerate(self.value._array):
+ constgen._consider_split_current_function(gen)
+ gen.dup(SELFTYPE)
+ push_constant(self.db, ootype.Signed, idx, gen)
+ push_constant(self.db, ITEM, item, gen)
+ self._setitem(SELFTYPE, gen)
+
+ def _setitem(self, SELFTYPE, gen):
+ gen.call_method(SELFTYPE, 'll_setitem_fast')
+
+# ______________________________________________________________________
# Dictionary constants
class DictConst(AbstractConst):
Modified: pypy/dist/pypy/translator/oosupport/genoo.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/genoo.py (original)
+++ pypy/dist/pypy/translator/oosupport/genoo.py Fri Apr 4 15:10:29 2008
@@ -22,6 +22,7 @@
RecordConst = ooconst.RecordConst
ClassConst = ooconst.ClassConst
ListConst = ooconst.ListConst
+ ArrayConst = ooconst.ArrayConst
StaticMethodConst = ooconst.StaticMethodConst
CustomDictConst = ooconst.CustomDictConst
DictConst = ooconst.DictConst
Modified: pypy/dist/pypy/translator/oosupport/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/metavm.py (original)
+++ pypy/dist/pypy/translator/oosupport/metavm.py Fri Apr 4 15:10:29 2008
@@ -214,6 +214,13 @@
Stack: ... -> newobj, ... """
raise NotImplementedError
+ def oonewarray(self, TYPE, length):
+ """ Creates a new array of the given type with the given length.
+
+ Stack: ... -> newobj, ... """
+ raise NotImplementedError
+
+
def push_null(self, TYPE):
""" Push a NULL value onto the stack (the NULL value represents
a pointer to an instance of OOType TYPE, if it matters to you). """
@@ -413,6 +420,14 @@
return
generator.new(op.args[0].value)
+
+class _OONewArray(MicroInstruction):
+ def render(self, generator, op):
+ if op.args[0].value is ootype.Void:
+ return
+ generator.oonewarray(op.args[0].value, op.args[1])
+
+
class BranchUnconditionally(MicroInstruction):
def __init__(self, label):
self.label = label
@@ -497,6 +512,7 @@
generator.isinstance(class_name)
New = _New()
+OONewArray = _OONewArray()
PushAllArgs = _PushAllArgs()
StoreResult = _StoreResult()
More information about the Pypy-commit
mailing list