[pypy-svn] r74460 - in pypy/branch/blackhole-improvement/pypy/jit: codewriter codewriter/test metainterp
arigo at codespeak.net
arigo at codespeak.net
Mon May 10 14:35:27 CEST 2010
Author: arigo
Date: Mon May 10 14:35:25 2010
New Revision: 74460
Modified:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
Log:
Support 'inline_call' in the blackhole and the pyjitpl interpreters.
Start simplifying the handling of pc in pyjitpl.
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py Mon May 10 14:35:25 2010
@@ -43,6 +43,7 @@
self.switchdictdescrs = []
self.count_regs = dict.fromkeys(KINDS, 0)
self.liveness = {}
+ self.nextlive = None
self.startpoints = set()
def emit_reg(self, reg):
@@ -88,7 +89,8 @@
self.label_positions[insn[0].name] = len(self.code)
return
if insn[0] == '-live-':
- self.liveness[len(self.code)] = (
+ assert self.nextlive is None
+ self.nextlive = (
self.get_liveness_info(insn, 'int'),
self.get_liveness_info(insn, 'ref'),
self.get_liveness_info(insn, 'float'))
@@ -149,6 +151,10 @@
num = self.insns.setdefault(key, len(self.insns))
self.code[startposition] = chr(num)
self.startpoints.add(startposition)
+ #
+ if self.nextlive is not None:
+ self.liveness[len(self.code)] = self.nextlive
+ self.nextlive = None
def get_liveness_info(self, insn, kind):
lives = [chr(reg.index) for reg in insn[1:] if reg.kind == kind]
@@ -184,5 +190,4 @@
self.count_regs['ref'],
self.count_regs['float'],
liveness=self.liveness,
- assembler=self,
startpoints=self.startpoints)
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jitcode.py Mon May 10 14:35:25 2010
@@ -16,7 +16,7 @@
def setup(self, code='', constants_i=[], constants_r=[], constants_f=[],
num_regs_i=256, num_regs_r=256, num_regs_f=256,
- liveness=None, assembler=None, startpoints=None):
+ liveness=None, startpoints=None):
self.code = code
# if the following lists are empty, use a single shared empty list
self.constants_i = constants_i or self._empty_i
@@ -24,10 +24,9 @@
self.constants_f = constants_f or self._empty_f
# encode the three num_regs into a single integer
self.num_regs_encoded = ((num_regs_i << 18) |
- (num_regs_r << 9) |
- (num_regs_f << 0))
+ (num_regs_f << 9) |
+ (num_regs_r << 0))
self.liveness = liveness
- self._assembler = assembler # debugging
self._startpoints = startpoints # debugging
def get_fnaddr_as_int(self):
@@ -36,10 +35,10 @@
def num_regs_i(self):
return self.num_regs_encoded >> 18
- def num_regs_r(self):
+ def num_regs_f(self):
return (self.num_regs_encoded >> 9) & 0x1FF
- def num_regs_f(self):
+ def num_regs_r(self):
return self.num_regs_encoded & 0x1FF
def has_liveness_info(self, pc):
@@ -49,7 +48,7 @@
registers_i, registers_r, registers_f):
# 'pc' gives a position in this bytecode. This invokes
# 'callback' for each variable that is live across the
- # instruction which starts at 'pc'. (It excludes the arguments
+ # instruction which ends at 'pc'. (It excludes the arguments
# of that instruction which are no longer used afterwards, and
# excludes the return value of that instruction.) More precisely,
# this invokes 'callback(arg, box, index)' where 'box' comes from one
@@ -93,14 +92,7 @@
return ' '.join(lst)
def _missing_liveness(self, pc):
- opcode = ord(self.code[pc])
- insn = 'insn %d' % opcode
- if self._assembler is not None:
- for name, code in self._assembler.insns.items():
- if code == opcode:
- insn = name
- raise KeyError("missing liveness[%d], corresponding to %r" % (
- pc, insn))
+ raise KeyError("missing liveness[%d]" % (pc,))
def __repr__(self):
return '<JitCode %r>' % self.name
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py Mon May 10 14:35:25 2010
@@ -174,20 +174,21 @@
]
assembler = Assembler()
jitcode = assembler.assemble(ssarepr)
- assert jitcode.code == ("\x00\x00\x0A\x01"
- "\x00\x00\x03\x02"
- "\x01\x01\x02\x03"
- "\x00\x00\x06\x04"
- "\x01\x03\x04\x05"
- "\x02\x05")
+ assert jitcode.code == ("\x00\x00\x0A\x01" # ends at 4
+ "\x00\x00\x03\x02" # ends at 8
+ "\x01\x01\x02\x03" # ends at 12
+ "\x00\x00\x06\x04" # ends at 16
+ "\x01\x03\x04\x05" # ends at 20
+ "\x02\x05")
assert assembler.insns == {'int_add/ici': 0,
'int_mul/iii': 1,
'int_return/i': 2}
- py.test.raises(KeyError, jitcode._live_vars, 1)
+ py.test.raises(KeyError, jitcode._live_vars, 0)
py.test.raises(KeyError, jitcode._live_vars, 3)
- py.test.raises(KeyError, jitcode._live_vars, 20)
- assert jitcode._live_vars(0) == '%i0'
- assert jitcode._live_vars(4) == '%i0 %i1'
- assert jitcode._live_vars(8) == '%i0'
- assert jitcode._live_vars(12) == '%i3'
- assert jitcode._live_vars(16) == ''
+ py.test.raises(KeyError, jitcode._live_vars, 5)
+ py.test.raises(KeyError, jitcode._live_vars, 24)
+ assert jitcode._live_vars(4) == '%i0'
+ assert jitcode._live_vars(8) == '%i0 %i1'
+ assert jitcode._live_vars(12) == '%i0'
+ assert jitcode._live_vars(16) == '%i3'
+ assert jitcode._live_vars(20) == ''
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py Mon May 10 14:35:25 2010
@@ -30,7 +30,7 @@
return b
cw = CodeWriter()
jitcode = cw.transform_func_to_jitcode(f, [5, 6])
- assert jitcode.code == ("\x00\x10\x00\x00\x00"
+ assert jitcode.code == ("\x00\x10\x00\x00\x00" # ends at 5
"\x01\x01\x00\x01"
"\x02\x00\x01\x00"
"\x03\x00\x00"
@@ -43,9 +43,10 @@
assert jitcode.num_regs_i() == 2
assert jitcode.num_regs_r() == 0
assert jitcode.num_regs_f() == 0
- assert jitcode._live_vars(0) == '%i0 %i1'
- for i in range(1, len(jitcode.code)):
- py.test.raises(KeyError, jitcode._live_vars, i)
+ assert jitcode._live_vars(5) == '%i0 %i1'
+ for i in range(len(jitcode.code)+1):
+ if i != 5:
+ py.test.raises(KeyError, jitcode._live_vars, i)
def test_call():
def ggg(x):
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py Mon May 10 14:35:25 2010
@@ -763,11 +763,52 @@
def bhimpl_inline_call_r_i(cpu, jitcode, args_r):
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
None, args_r, None)
+ @arguments("cpu", "j", "R", returns="r")
+ def bhimpl_inline_call_r_r(cpu, jitcode, args_r):
+ return cpu.bh_call_r(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ None, args_r, None)
+ @arguments("cpu", "j", "R", returns="f")
+ def bhimpl_inline_call_r_f(cpu, jitcode, args_r):
+ return cpu.bh_call_f(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ None, args_r, None)
+ @arguments("cpu", "j", "R")
+ def bhimpl_inline_call_r_v(cpu, jitcode, args_r):
+ return cpu.bh_call_v(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ None, args_r, None)
@arguments("cpu", "j", "I", "R", returns="i")
def bhimpl_inline_call_ir_i(cpu, jitcode, args_i, args_r):
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
args_i, args_r, None)
+ @arguments("cpu", "j", "I", "R", returns="r")
+ def bhimpl_inline_call_ir_r(cpu, jitcode, args_i, args_r):
+ return cpu.bh_call_r(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ args_i, args_r, None)
+ @arguments("cpu", "j", "I", "R", returns="f")
+ def bhimpl_inline_call_ir_f(cpu, jitcode, args_i, args_r):
+ return cpu.bh_call_f(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ args_i, args_r, None)
+ @arguments("cpu", "j", "I", "R")
+ def bhimpl_inline_call_ir_v(cpu, jitcode, args_i, args_r):
+ return cpu.bh_call_v(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ args_i, args_r, None)
+
+ @arguments("cpu", "j", "I", "R", "F", returns="i")
+ def bhimpl_inline_call_irf_i(cpu, jitcode, args_i, args_r, args_f):
+ return cpu.bh_call_i(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ args_i, args_r, args_f)
+ @arguments("cpu", "j", "I", "R", "F", returns="r")
+ def bhimpl_inline_call_irf_r(cpu, jitcode, args_i, args_r, args_f):
+ return cpu.bh_call_r(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ args_i, args_r, args_f)
+ @arguments("cpu", "j", "I", "R", "F", returns="f")
+ def bhimpl_inline_call_irf_f(cpu, jitcode, args_i, args_r, args_f):
+ return cpu.bh_call_f(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ args_i, args_r, args_f)
+ @arguments("cpu", "j", "I", "R", "F")
+ def bhimpl_inline_call_irf_v(cpu, jitcode, args_i, args_r, args_f):
+ return cpu.bh_call_v(jitcode.get_fnaddr_as_int(), jitcode.calldescr,
+ args_i, args_r, args_f)
@arguments("cpu", "d", "i", returns="r")
def bhimpl_new_array(cpu, arraydescr, length):
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py Mon May 10 14:35:25 2010
@@ -50,6 +50,8 @@
parent_resumedata_snapshot = None
parent_resumedata_frame_info_list = None
+ env = property(lambda: xxx, lambda x: xxx) # no read/write!
+
def __init__(self, metainterp):
self.metainterp = metainterp
self.registers_i = [None] * 256
@@ -133,6 +135,17 @@
if not we_are_translated():
assert oldbox not in registers[count:]
+ def make_result_of_lastop(self, resultbox):
+ target_index = ord(self.bytecode[self.pc-1])
+ if resultbox.type == history.INT:
+ self.registers_i[target_index] = resultbox
+ elif resultbox.type == history.REF:
+ self.registers_r[target_index] = resultbox
+ elif resultbox.type == history.FLOAT:
+ self.registers_f[target_index] = resultbox
+ else:
+ raise AssertionError("bad result box type")
+
# ------------------------------
for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
@@ -222,23 +235,24 @@
def opimpl_goto(self, target):
self.pc = target
- @arguments("orgpc", "label", "box")
- def opimpl_goto_if_not(self, pc, target, box):
+ @arguments("label", "box")
+ def opimpl_goto_if_not(self, target, box):
switchcase = box.getint()
if switchcase:
opnum = rop.GUARD_TRUE
else:
- self.pc = target
opnum = rop.GUARD_FALSE
- self.generate_guard(pc, opnum, box)
+ self.generate_guard(opnum, box)
+ if not switchcase:
+ self.pc = target
for _opimpl in ['int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge',
]:
exec py.code.Source('''
- @arguments("orgpc", "label", "box", "box")
- def opimpl_goto_if_not_%s(self, pc, target, b1, b2):
+ @arguments("label", "box", "box")
+ def opimpl_goto_if_not_%s(self, target, b1, b2):
condbox = self.execute(rop.%s, b1, b2)
- self.opimpl_goto_if_not(pc, target, condbox)
+ self.opimpl_goto_if_not(target, condbox)
''' % (_opimpl, _opimpl.upper())).compile()
def follow_jump(self):
@@ -606,25 +620,38 @@
result = vinfo.get_array_length(virtualizable, arrayindex)
self.make_result_box(ConstInt(result))
- def perform_call(self, jitcode, varargs, greenkey=None):
- # when tracing, this bytecode causes the subfunction to be entered
- f = self.metainterp.newframe(jitcode, greenkey)
- f.setup_call(varargs)
- return True
-
- @XXX #arguments("bytecode", "varargs")
- def opimpl_call(self, callee, varargs):
- return self.perform_call(callee, varargs)
-
- @arguments("orgpc", "box", "descr", "boxes")
- def _opimpl_residual_call1(self, pc, funcbox, calldescr, argboxes):
- return self.do_residual_call(funcbox, calldescr, argboxes, exc_at=pc)
- @arguments("orgpc", "box", "descr", "boxes2")
- def _opimpl_residual_call2(self, pc, funcbox, calldescr, argboxes):
- return self.do_residual_call(funcbox, calldescr, argboxes, exc_at=pc)
- @arguments("orgpc", "box", "descr", "boxes3")
- def _opimpl_residual_call3(self, pc, funcbox, calldescr, argboxes):
- return self.do_residual_call(funcbox, calldescr, argboxes, exc_at=pc)
+ @arguments("jitcode", "boxes")
+ def _opimpl_inline_call1(self, jitcode, argboxes):
+ self.metainterp.perform_call(jitcode, argboxes)
+ @arguments("jitcode", "boxes2")
+ def _opimpl_inline_call2(self, jitcode, argboxes):
+ self.metainterp.perform_call(jitcode, argboxes)
+ @arguments("jitcode", "boxes3")
+ def _opimpl_inline_call3(self, jitcode, argboxes):
+ self.metainterp.perform_call(jitcode, argboxes)
+
+ opimpl_inline_call_r_i = _opimpl_inline_call1
+ opimpl_inline_call_r_r = _opimpl_inline_call1
+ opimpl_inline_call_r_f = _opimpl_inline_call1
+ opimpl_inline_call_r_v = _opimpl_inline_call1
+ opimpl_inline_call_ir_i = _opimpl_inline_call2
+ opimpl_inline_call_ir_r = _opimpl_inline_call2
+ opimpl_inline_call_ir_f = _opimpl_inline_call2
+ opimpl_inline_call_ir_v = _opimpl_inline_call2
+ opimpl_inline_call_irf_i = _opimpl_inline_call3
+ opimpl_inline_call_irf_r = _opimpl_inline_call3
+ opimpl_inline_call_irf_f = _opimpl_inline_call3
+ opimpl_inline_call_irf_v = _opimpl_inline_call3
+
+ @arguments("box", "descr", "boxes")
+ def _opimpl_residual_call1(self, funcbox, calldescr, argboxes):
+ return self.do_residual_call(funcbox, calldescr, argboxes, exc=True)
+ @arguments("box", "descr", "boxes2")
+ def _opimpl_residual_call2(self, funcbox, calldescr, argboxes):
+ return self.do_residual_call(funcbox, calldescr, argboxes, exc=True)
+ @arguments("box", "descr", "boxes3")
+ def _opimpl_residual_call3(self, funcbox, calldescr, argboxes):
+ return self.do_residual_call(funcbox, calldescr, argboxes, exc=True)
opimpl_residual_call_r_i = _opimpl_residual_call1
opimpl_residual_call_r_r = _opimpl_residual_call1
@@ -931,10 +958,20 @@
# ------------------------------
def setup_call(self, argboxes):
- if not we_are_translated():
- check_args(*argboxes)
self.pc = 0
- self.env = argboxes
+ count_i = count_r = count_f = 0
+ for box in argboxes:
+ if box.type == history.INT:
+ self.registers_i[count_i] = box
+ count_i += 1
+ elif box.type == history.REF:
+ self.registers_r[count_r] = box
+ count_r += 1
+ elif box.type == history.FLOAT:
+ self.registers_f[count_f] = box
+ count_f += 1
+ else:
+ raise AssertionError(box.type)
def setup_resume_at_op(self, pc, env):
if not we_are_translated():
@@ -962,14 +999,12 @@
except ChangeFrame:
pass
- def generate_guard(self, pc, opnum, box=None, extraargs=[]):
+ def generate_guard(self, opnum, box=None, extraargs=[]):
if isinstance(box, Const): # no need for a guard
return
metainterp = self.metainterp
if metainterp.is_blackholing():
return
- saved_pc = self.pc
- self.pc = pc
if box is not None:
moreargs = [box] + extraargs
else:
@@ -992,7 +1027,6 @@
self.metainterp.staticdata.profiler.count_ops(opnum, GUARDS)
# count
metainterp.attach_debug_info(guard_op)
- self.pc = saved_pc
return guard_op
def implement_guard_value(self, pc, box):
@@ -1019,16 +1053,16 @@
return self.metainterp.execute_and_record(opnum, descr, *argboxes)
@specialize.arg(1)
- def execute_varargs(self, opnum, argboxes, descr, exc_at):
+ def execute_varargs(self, opnum, argboxes, descr, exc):
resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes,
descr=descr)
- if exc_at >= 0:
- self.metainterp.handle_possible_exception(exc_at)
+ if exc:
+ self.metainterp.handle_possible_exception(self.pc)
else:
self.metainterp.assert_no_exception()
return resbox
- def do_residual_call(self, funcbox, descr, argboxes, exc_at):
+ def do_residual_call(self, funcbox, descr, argboxes, exc):
allboxes = [funcbox] + argboxes
effectinfo = descr.get_extra_info()
if 0:# XXX effectinfo is None or effectinfo.forces_virtual_or_virtualizable:
@@ -1046,7 +1080,7 @@
else:
return self.metainterp.assert_no_exception()
else:
- return self.execute_varargs(rop.CALL, allboxes, descr, exc_at)
+ return self.execute_varargs(rop.CALL, allboxes, descr, exc)
# ____________________________________________________________
@@ -1238,6 +1272,12 @@
def is_blackholing(self):
return False # XXX get rid of this method
+ def perform_call(self, jitcode, boxes, greenkey=None):
+ # when tracing, this bytecode causes the subfunction to be entered
+ f = self.newframe(jitcode, greenkey)
+ f.setup_call(boxes)
+ raise ChangeFrame
+
def newframe(self, jitcode, greenkey=None):
if jitcode is self.staticdata.portal_code:
self.in_recursion += 1
@@ -1268,7 +1308,7 @@
self.popframe()
if self.framestack:
if resultbox is not None:
- self.framestack[-1].make_result_box(resultbox)
+ self.framestack[-1].make_result_of_lastop(resultbox)
raise ChangeFrame
else:
if not self.is_blackholing():
@@ -1715,20 +1755,7 @@
# ----- make a new frame -----
self.framestack = []
f = self.newframe(self.staticdata.portal_code)
- f.pc = 0
- count_i = count_r = count_f = 0
- for box in original_boxes:
- if box.type == history.INT:
- f.registers_i[count_i] = box
- count_i += 1
- elif box.type == history.REF:
- f.registers_r[count_r] = box
- count_r += 1
- elif box.type == history.FLOAT:
- f.registers_f[count_f] = box
- count_f += 1
- else:
- raise AssertionError(box.type)
+ f.setup_call(original_boxes)
self.virtualref_boxes = []
self.initialize_virtualizable(original_boxes)
return original_boxes
@@ -2056,11 +2083,13 @@
else:
raise AssertionError("bad argcode")
position += 1
- elif argtype == "descr":
+ elif argtype == "descr" or argtype == "jitcode":
assert argcodes[next_argcode] == 'd'
next_argcode = next_argcode + 1
index = ord(code[position]) | (ord(code[position+1])<<8)
value = self.metainterp.staticdata.opcode_descrs[index]
+ if argtype == "jitcode":
+ assert isinstance(value, JitCode)
position += 2
elif argtype == "label":
assert argcodes[next_argcode] == 'L'
@@ -2110,25 +2139,27 @@
assert num_return_args == 0 or num_return_args == 1
self.pc = position + num_return_args
#
- resultbox = unboundmethod(self, *args)
- #
- if num_return_args == 0:
- assert resultbox is None
- else:
- assert resultbox is not None
- result_argcode = argcodes[next_argcode]
- target_index = ord(code[position])
- if result_argcode == 'i':
- assert resultbox.type == history.INT
- self.registers_i[target_index] = resultbox
- elif result_argcode == 'r':
- assert resultbox.type == history.REF
- self.registers_r[target_index] = resultbox
- elif result_argcode == 'f':
- assert resultbox.type == history.FLOAT
- self.registers_f[target_index] = resultbox
+ if not we_are_translated():
+ print '\tjitcode:', name, list(args),
+ try:
+ resultbox = unboundmethod(self, *args)
+ except Exception, e:
+ print '-> %s!' % e.__class__.__name__
+ raise
+ if num_return_args == 0:
+ print
+ assert resultbox is None
else:
- raise AssertionError("bad result argcode")
+ print '->', resultbox
+ result_argcode = argcodes[next_argcode]
+ assert resultbox.type == {'i': history.INT,
+ 'r': history.REF,
+ 'f': history.FLOAT}[result_argcode]
+ else:
+ resultbox = unboundmethod(self, *args)
+ #
+ if resultbox is not None:
+ self.make_result_of_lastop(resultbox)
#
unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func
argtypes = unrolling_iterable(unboundmethod.argtypes)
More information about the Pypy-commit
mailing list