[pypy-svn] r57231 - in pypy/branch/oo-jit/pypy: jit/codegen/cli jit/codegen/test translator/cli/src
antocuni at codespeak.net
antocuni at codespeak.net
Wed Aug 13 20:56:27 CEST 2008
Author: antocuni
Date: Wed Aug 13 20:56:25 2008
New Revision: 57231
Modified:
pypy/branch/oo-jit/pypy/jit/codegen/cli/args_manager.py
pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py
pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs
Log:
- add a test that passes "many" (==4) arguments across non-local links
- change completetly the way InputArgs is implemented, by using a chain of
struct Pair<head, tail>. As proven by user/antocuni/cli-bench/inputargs.cs,
this has little impact on performances
Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/args_manager.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/cli/args_manager.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/args_manager.py Wed Aug 13 20:56:25 2008
@@ -4,13 +4,39 @@
Assembly = System.Reflection.Assembly
OpCodes = System.Reflection.Emit.OpCodes
+def new_type_array(types):
+ array = dotnet.new_array(System.Type, len(types))
+ for i in range(len(types)):
+ array[i] = types[i]
+ return array
+
+def MakeGenericType(clitype, paramtypes):
+ array = new_type_array(paramtypes)
+ return clitype.MakeGenericType(array)
+
class ArgsManager:
def __init__(self):
self.type_counter = {}
+ self.type_index = {}
self.clitype = None
- self.fieldtypes = None
- self.slots = None
+ self._init_types()
+
+ def _load_pypylib(self):
+ from pypy.translator.cli.query import pypylib, pypylib2
+ assembly = None
+ for name in [pypylib, pypylib2]:
+ assembly = Assembly.LoadWithPartialName(name)
+ if assembly:
+ break
+ assert assembly is not None
+ return assembly
+
+ def _init_types(self):
+ pypylib = self._load_pypylib()
+ self.clitype_InputArgs = pypylib.GetType('pypy.runtime.InputArgs`1')
+ self.clitype_Void = pypylib.GetType('pypy.runtime.Void')
+ self.clitype_Pair = pypylib.GetType('pypy.runtime.Pair`2')
def is_open(self):
return self.clitype is None
@@ -19,11 +45,10 @@
assert not self.is_open()
return self.clitype
- def register(self, args_gv):
+ def register_types(self, types):
assert self.is_open()
newcounter = {}
- for gv_arg in args_gv:
- clitype = gv_arg.getCliType()
+ for clitype in types:
newcount = newcounter.get(clitype, 0)
newcounter[clitype] = newcount+1
@@ -32,99 +57,86 @@
maxcount = max(oldcount, newcount)
self.type_counter[clitype] = maxcount
+ def register(self, args_gv):
+ types = [gv_arg.getCliType() for gv_arg in args_gv]
+ self.register_types(types)
+
def close(self):
assert self.is_open()
- templates = self._get_templates()
-
- self.fieldtypes = fieldtypes = []
- self.slots = slots = {}
+ fieldtypes = []
for clitype, count in self.type_counter.iteritems():
- start = len(fieldtypes)
- end = start+count
- fieldtypes += [clitype]*count
- slots[clitype] = self._myrange(start, end)
- numfields = len(fieldtypes)
-
- if numfields <= len(templates):
- template = templates[numfields-1]
- array = dotnet.new_array(System.Type, numfields)
- for i in range(numfields):
- array[i] = fieldtypes[i]
- self.clitype = template.MakeGenericType(array)
- else:
- assert False, 'TODO'
+ self.type_index[clitype] = len(fieldtypes)
+ fieldtypes += [clitype] * count
+
+ pairtype = self.clitype_Void
+ # iterate over reversed(fieldtypes)
+ i = len(fieldtypes)-1
+ while True:
+ if i < 0:
+ break
+ fieldtype = fieldtypes[i]
+ pairtype = MakeGenericType(self.clitype_Pair, [fieldtype, pairtype])
+ i-=1
+
+## for fieldtype in fieldtypes[::-1]:
+## pairtype = MakeGenericType(self.clitype_Pair, [fieldtype, pairtype])
+ self.clitype = MakeGenericType(self.clitype_InputArgs, [pairtype])
+
+ def _store_by_index(self, meth, gv_arg, i):
+ head_info = self._load_nth_head(meth, i)
+ gv_arg.load(meth)
+ meth.il.Emit(OpCodes.Stfld, head_info)
+
+ def _load_by_index(self, meth, i):
+ head_info = self._load_nth_head(meth, i)
+ meth.il.Emit(OpCodes.Ldfld, head_info)
+
+ def _load_nth_head(self, meth, n):
+ il = meth.il
+ fields_info = self.clitype.GetField("fields")
+ meth.gv_inputargs.load(meth)
+ il.Emit(OpCodes.Ldflda, fields_info)
+
+ lastfield_info = fields_info
+ for _ in range(n):
+ fieldtype = lastfield_info.get_FieldType()
+ lastfield_info = fieldtype.GetField("tail")
+ il.Emit(OpCodes.Ldflda, lastfield_info)
+ fieldtype = lastfield_info.get_FieldType()
+ return fieldtype.GetField("head")
def copy_to_inputargs(self, meth, args_gv):
"copy args_gv into the appropriate fields of inputargs"
assert not self.is_open()
- il = meth.il
- gv_inputargs = meth.gv_inputargs
- fields = self._get_fields(args_gv)
- assert len(args_gv) == len(fields)
- for i in range(len(args_gv)):
+ fieldtypes = [gv_arg.getCliType() for gv_arg in args_gv]
+ indexes = self._get_indexes(fieldtypes)
+ assert len(indexes) == len(fieldtypes)
+ for i in range(len(indexes)):
+ n = indexes[i]
gv_arg = args_gv[i]
- fieldinfo = fields[i]
- gv_inputargs.load(meth)
- gv_arg.load(meth)
- il.Emit(OpCodes.Stfld, fieldinfo)
+ self._store_by_index(meth, gv_arg, n)
def copy_from_inputargs(self, meth, args_gv):
"copy the appropriate fields of inputargs into args_gv"
assert not self.is_open()
- il = meth.il
- gv_inputargs = meth.gv_inputargs
- fields = self._get_fields(args_gv)
- assert len(args_gv) == len(fields)
- for i in range(len(args_gv)):
+ fieldtypes = [gv_arg.getCliType() for gv_arg in args_gv]
+ indexes = self._get_indexes(fieldtypes)
+ assert len(indexes) == len(fieldtypes)
+ for i in range(len(indexes)):
+ n = indexes[i]
gv_arg = args_gv[i]
- fieldinfo = fields[i]
- gv_inputargs.load(meth)
- il.Emit(OpCodes.Ldfld, fieldinfo)
+ self._load_by_index(meth, n)
gv_arg.store(meth)
- def _myrange(self, start, end):
- length = (end - start)
- res = [0] * length
- for i in range(start, end):
- res[i] = i
- return res
-
- def _load_pypylib(self):
- from pypy.translator.cli.query import pypylib, pypylib2
- assembly = None
- for name in [pypylib, pypylib2]:
- assembly = Assembly.LoadWithPartialName(name)
- if assembly:
- break
- assert assembly is not None
- return assembly
-
- def _get_templates(self):
- pypylib = self._load_pypylib()
- templates = []
- i = 1
- while True:
- typename = 'pypy.runtime.InputArgs`%d' % i
- clitype = pypylib.GetType(typename)
- if not clitype:
- break
- templates.append(clitype)
- i += 1
- return templates
-
- def _copy_slots(self):
- 'Deepcopy self.slots'
- slots = {}
- for key, value in self.slots.iteritems():
- slots[key] = value[:]
- return slots
-
- def _get_fields(self, args_gv):
- slots = self._copy_slots()
- types = [gv_arg.getCliType() for gv_arg in args_gv]
- fields = []
- for clitype in types:
- slot = slots[clitype].pop()
- fieldinfo = self.clitype.GetField('field%d' % slot)
- fields.append(fieldinfo)
- return fields
+ def _get_indexes(self, fieldtypes):
+ indexes = []
+ curtype = None
+ curidx = -1
+ for fieldtype in fieldtypes:
+ if fieldtype != curtype:
+ curidx = self.type_index[fieldtype]
+ curtype = fieldtype
+ else:
+ curidx += 1
+ indexes.append(curidx)
+ return indexes
Modified: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Wed Aug 13 20:56:25 2008
@@ -404,6 +404,53 @@
return res
return switch_runner
+def make_switch_many_args(T, rgenop):
+ """
+ def f(v0, v1, v2, v3, v4):
+ if v0 == 0: # switch
+ return 21*v1
+ elif v0 == 1:
+ return 21+v1+v2+v3+v4
+ else:
+ return v1
+ """
+ sigtoken = rgenop.sigToken(T.FUNC5)
+ builder, gv_switch, [gv0, gv1, gv2, gv3, gv4] = rgenop.newgraph(sigtoken, "switch_many_args")
+ builder.start_writing()
+
+ flexswitch, default_builder = builder.flexswitch(gv0, [gv1, gv2, gv3, gv4])
+ const21 = rgenop.genconst(21)
+
+ # default
+ default_builder.finish_and_return(sigtoken, gv1)
+ # case == 0
+ const0 = rgenop.genconst(0)
+ case_builder = flexswitch.add_case(const0)
+ gv_res_case0 = case_builder.genop2('int_mul', const21, gv1)
+ case_builder.finish_and_return(sigtoken, gv_res_case0)
+ # case == 1
+ const1 = rgenop.genconst(1)
+ case_builder = flexswitch.add_case(const1)
+ gv_tmp1 = case_builder.genop2('int_add', const21, gv1)
+ gv_tmp2 = case_builder.genop2('int_add', gv_tmp1, gv2)
+ gv_tmp3 = case_builder.genop2('int_add', gv_tmp2, gv3)
+ gv_res_case1 = case_builder.genop2('int_add', gv_tmp3, gv3)
+ case_builder.finish_and_return(sigtoken, gv_res_case1)
+
+ builder.end()
+ return gv_switch
+
+def get_switch_many_args_runner(T, RGenOp):
+ def switch_runner(x, y, z, w, k):
+ rgenop = RGenOp()
+ gv_switchfn = make_switch_many_args(T, rgenop)
+ switchfn = gv_switchfn.revealconst(T.Ptr(T.FUNC5))
+ res = switchfn(x, y, z, w, k)
+ keepalive_until_here(rgenop) # to keep the code blocks alive
+ return res
+ return switch_runner
+
+
def make_large_switch(T, rgenop):
"""
def f(v0, v1):
@@ -1101,6 +1148,15 @@
res = fn(42, 18)
assert res == 18
+ def test_switch_many_args_compile(self):
+ fn = self.compile(get_switch_many_args_runner(self.T, self.RGenOp), [int, int, int, int, int])
+ res = fn(0, 2, 3, 4, 5)
+ assert res == 42
+ res = fn(1, 4, 5, 6, 6)
+ assert res == 42
+ res = fn(42, 16, 3, 4, 5)
+ assert res == 16
+
def test_large_switch_compile(self):
fn = self.compile(get_large_switch_runner(self.T, self.RGenOp), [int, int])
res = fn(0, 2)
@@ -1340,6 +1396,17 @@
res = fnptr(42, 16)
assert res == 16
+ def test_switch_many_args_direct(self):
+ rgenop = self.RGenOp()
+ gv_switchfn = make_switch_many_args(self.T, rgenop)
+ fnptr = self.cast(gv_switchfn, 5)
+ res = fnptr(0, 2, 3, 4, 5)
+ assert res == 42
+ res = fnptr(1, 4, 5, 6, 6)
+ assert res == 42
+ res = fnptr(42, 16, 3, 4, 5)
+ assert res == 16
+
def test_large_switch_direct(self):
rgenop = self.RGenOp()
gv_switchfn = make_large_switch(self.T, rgenop)
Modified: pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs
==============================================================================
--- pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs (original)
+++ pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Wed Aug 13 20:56:25 2008
@@ -105,13 +105,20 @@
namespace pypy.runtime
{
- // XXX: these classes should be automatically generated by the JIT backend
- public delegate int FlexSwitchCase(int block, object args);
- public class InputArgs {
- public int Int32_0;
- public int Int32_1;
+ public struct Void {
+ }
+
+ public struct Pair<T0, T1> {
+ public T0 head;
+ public T1 tail;
}
+ public class InputArgs<T> {
+ public T fields;
+ }
+
+ public delegate int FlexSwitchCase(int block, object args);
+
public class LowLevelFlexSwitch
{
public int default_blockid = -1;
More information about the Pypy-commit
mailing list