[pypy-svn] r74187 - in pypy/branch/blackhole-improvement/pypy/jit: codewriter metainterp metainterp/test
arigo at codespeak.net
arigo at codespeak.net
Wed Apr 28 18:33:31 CEST 2010
Author: arigo
Date: Wed Apr 28 18:33:30 2010
New Revision: 74187
Modified:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py
Log:
Enhance the tests to also run on top of pyjitpl.
Start fixing pyjitpl. Three tests pass so far.
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py Wed Apr 28 18:33:30 2010
@@ -52,6 +52,7 @@
return jitcode
def make_jitcodes(self, maingraph, verbose=False):
+ self.portal_graph = maingraph
return self.transform_graph_to_jitcode(maingraph, verbose)
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 Wed Apr 28 18:33:30 2010
@@ -4,9 +4,11 @@
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.unroll import unrolling_iterable
from pypy.rlib.debug import debug_start, debug_stop, debug_print
+from pypy.tool.sourcetools import func_with_new_name
from pypy.jit.metainterp import history, compile, resume
-from pypy.jit.metainterp.history import Const, ConstInt, Box
+from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat
+from pypy.jit.metainterp.history import Box
from pypy.jit.metainterp.resoperation import rop
from pypy.jit.metainterp import executor
from pypy.jit.metainterp.logger import Logger
@@ -17,6 +19,7 @@
from pypy.rlib.objectmodel import specialize
from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED
from pypy.jit.metainterp.compile import GiveUp
+from pypy.jit.codewriter.assembler import JitCode
# ____________________________________________________________
@@ -24,66 +27,11 @@
for arg in args:
assert isinstance(arg, (Box, Const))
-class arguments(object):
- def __init__(self, *argtypes):
- self.argtypes = argtypes
-
- def __eq__(self, other):
- if not isinstance(other, arguments):
- return NotImplemented
- return self.argtypes == other.argtypes
-
- def __ne__(self, other):
- if not isinstance(other, arguments):
- return NotImplemented
- return self.argtypes != other.argtypes
-
- def __call__(self, func):
- argtypes = unrolling_iterable(self.argtypes)
- def wrapped(self, orgpc):
- args = (self, )
- for argspec in argtypes:
- if argspec == "box":
- box = self.load_arg()
- args += (box, )
- elif argspec == "constbox":
- args += (self.load_const_arg(), )
- elif argspec == "int":
- args += (self.load_int(), )
- elif argspec == "jumptarget":
- args += (self.load_3byte(), )
- elif argspec == "jumptargets":
- num = self.load_int()
- args += ([self.load_3byte() for i in range(num)], )
- elif argspec == "varargs":
- args += (self.load_varargs(), )
- elif argspec == "constargs":
- args += (self.load_constargs(), )
- elif argspec == "descr":
- descr = self.load_const_arg()
- assert isinstance(descr, history.AbstractDescr)
- args += (descr, )
- elif argspec == "bytecode":
- bytecode = self.load_const_arg()
- assert isinstance(bytecode, codewriter.JitCode)
- args += (bytecode, )
- elif argspec == "orgpc":
- args += (orgpc, )
- elif argspec == "methdescr":
- methdescr = self.load_const_arg()
- assert isinstance(methdescr,
- history.AbstractMethDescr)
- args += (methdescr, )
- else:
- assert 0, "unknown argtype declaration: %r" % (argspec,)
- val = func(*args)
- if val is None:
- val = False
- return val
- name = func.func_name
- wrapped.func_name = "wrap_" + name
- wrapped.argspec = self
- return wrapped
+def arguments(*args):
+ def decorate(func):
+ func.argtypes = args
+ return func
+ return decorate
# ____________________________________________________________
@@ -95,16 +43,35 @@
parent_resumedata_snapshot = None
parent_resumedata_frame_info_list = None
- def __init__(self, metainterp, jitcode, greenkey=None):
- assert isinstance(jitcode, codewriter.JitCode)
+ def __init__(self, metainterp):
self.metainterp = metainterp
+ self.boxes_i = [None] * 256
+ self.boxes_r = [None] * 256
+ self.boxes_f = [None] * 256
+
+ def setup(self, jitcode, greenkey=None):
+ assert isinstance(jitcode, JitCode)
self.jitcode = jitcode
self.bytecode = jitcode.code
- self.constants = jitcode.constants
- self.exception_target = -1
self.name = jitcode.name # purely for having name attribute
# this is not None for frames that are recursive portal calls
self.greenkey = greenkey
+ # copy the constants in place
+ self.copy_constants(self.boxes_i, jitcode.constants_i, ConstInt)
+ self.copy_constants(self.boxes_r, jitcode.constants_r, ConstPtr)
+ self.copy_constants(self.boxes_f, jitcode.constants_f, ConstFloat)
+
+ def copy_constants(self, boxes, constants, ConstClass):
+ """Copy jitcode.constants[0] to boxes[255],
+ jitcode.constants[1] to boxes[254],
+ jitcode.constants[2] to boxes[253], etc."""
+ i = len(constants) - 1
+ while i >= 0:
+ j = 255 - i
+ assert j >= 0
+ boxes[j] = ConstClass(constants[i])
+ i -= 1
+ copy_constants._annspecialcase_ = 'specialize:arg(3)'
# ------------------------------
# Decoding of the JitCode
@@ -197,7 +164,7 @@
exec py.code.Source('''
@arguments("box", "box")
def opimpl_%s(self, b1, b2):
- self.execute(rop.%s, b1, b2)
+ return self.execute(rop.%s, b1, b2)
''' % (_opimpl, _opimpl.upper())).compile()
for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']:
@@ -219,14 +186,16 @@
self.execute(rop.%s, b)
''' % (_opimpl, _opimpl.upper())).compile()
- @arguments()
- def opimpl_return(self):
- assert len(self.env) == 1
- return self.metainterp.finishframe(self.env[0])
+ @arguments("box")
+ def opimpl_any_return(self, box):
+ return self.metainterp.finishframe(box)
+
+ opimpl_int_return = opimpl_any_return
+ opimpl_ref_return = opimpl_any_return
+ opimpl_float_return = opimpl_any_return
@arguments()
def opimpl_void_return(self):
- assert len(self.env) == 0
return self.metainterp.finishframe(None)
@arguments("jumptarget")
@@ -962,16 +931,15 @@
# whenever the 'opcode_implementations' (which is one of the 'opimpl_'
# methods) returns True. This is the case when the current frame
# changes, due to a call or a return.
- while True:
- pc = self.pc
- op = ord(self.bytecode[pc])
- #print self.metainterp.opcode_names[op]
- self.pc = pc + 1
+ try:
staticdata = self.metainterp.staticdata
- stop = staticdata.opcode_implementations[op](self, pc)
- #self.metainterp.most_recent_mp = None
- if stop:
- break
+ while True:
+ pc = self.pc
+ op = ord(self.bytecode[pc])
+ #print staticdata.opcode_names[op]
+ staticdata.opcode_implementations[op](self, pc)
+ except ChangeFrame:
+ pass
def generate_guard(self, pc, opnum, box, extraargs=[]):
if isinstance(box, Const): # no need for a guard
@@ -1023,13 +991,11 @@
@specialize.arg(1)
def execute(self, opnum, *argboxes):
- self.execute_with_descr(opnum, None, *argboxes)
+ return self.metainterp.execute_and_record(opnum, None, *argboxes)
@specialize.arg(1)
def execute_with_descr(self, opnum, descr, *argboxes):
- resbox = self.metainterp.execute_and_record(opnum, descr, *argboxes)
- if resbox is not None:
- self.make_result_box(resbox)
+ return self.metainterp.execute_and_record(opnum, descr, *argboxes)
@specialize.arg(1)
def execute_varargs(self, opnum, argboxes, descr, exc):
@@ -1068,20 +1034,19 @@
logger_noopt = None
logger_ops = None
- def __init__(self, portal_graph, cpu, stats, options,
+ def __init__(self, codewriter, options,
ProfilerClass=EmptyProfiler, warmrunnerdesc=None):
- self.cpu = cpu
- self.stats = stats
+ self.cpu = codewriter.cpu
+ self.stats = self.cpu.stats
self.options = options
self.logger_noopt = Logger(self)
self.logger_ops = Logger(self, guard_number=True)
- RESULT = portal_graph.getreturnvar().concretetype
+ RESULT = codewriter.portal_graph.getreturnvar().concretetype
self.result_type = history.getkind(RESULT)
- self.opcode_implementations = []
- self.opcode_names = []
- self.opname_to_index = {}
+ self.setup_insns(codewriter.assembler.insns)
+ self.setup_descrs(codewriter.assembler.descrs)
self.profiler = ProfilerClass()
@@ -1089,16 +1054,15 @@
self.indirectcall_values = []
self.warmrunnerdesc = warmrunnerdesc
- self._op_goto_if_not = self.find_opcode('goto_if_not')
- self._op_ooisnull = self.find_opcode('ooisnull')
- self._op_oononnull = self.find_opcode('oononnull')
+ #self._op_goto_if_not = self.find_opcode('goto_if_not')
+ #self._op_ooisnull = self.find_opcode('ooisnull')
+ #self._op_oononnull = self.find_opcode('oononnull')
backendmodule = self.cpu.__module__
backendmodule = backendmodule.split('.')[-2]
self.jit_starting_line = 'JIT starting (%s)' % backendmodule
self.portal_code = None
- self._class_sizes = None
self._addr2name_keys = []
self._addr2name_values = []
@@ -1110,13 +1074,18 @@
def _freeze_(self):
return True
- def info_from_codewriter(self, portal_code, class_sizes,
- list_of_addr2name, portal_runner_ptr):
- self.portal_code = portal_code
- self._class_sizes = class_sizes
- self._addr2name_keys = [key for key, value in list_of_addr2name]
- self._addr2name_values = [value for key, value in list_of_addr2name]
- self._portal_runner_ptr = portal_runner_ptr
+ def setup_insns(self, insns):
+ self.opcode_names = ['?'] * len(insns)
+ self.opcode_implementations = [None] * len(insns)
+ for key, value in insns.items():
+ assert self.opcode_implementations[value] is None
+ self.opcode_names[value] = key
+ name, argcodes = key.split('/')
+ opimpl = _get_opimpl_method(name, argcodes)
+ self.opcode_implementations[value] = opimpl
+
+ def setup_descrs(self, descrs):
+ self.opcode_descrs = descrs
def finish_setup(self, optimizer=None):
warmrunnerdesc = self.warmrunnerdesc
@@ -1134,20 +1103,12 @@
"""Runtime setup needed by the various components of the JIT."""
if not self.globaldata.initialized:
debug_print(self.jit_starting_line)
- self._setup_class_sizes()
self.cpu.setup_once()
if not self.profiler.initialized:
self.profiler.start()
self.profiler.initialized = True
self.globaldata.initialized = True
- def _setup_class_sizes(self):
- class_sizes = {}
- for vtable, sizedescr in self._class_sizes:
- vtable = self.cpu.ts.cast_vtable_to_hashable(self.cpu, vtable)
- class_sizes[vtable] = sizedescr
- self.cpu.set_class_sizes(class_sizes)
-
def get_name_from_address(self, addr):
# for debugging only
if we_are_translated():
@@ -1196,21 +1157,6 @@
self.indirectcall_keys.append(fnaddress)
self.indirectcall_values.append(jitcode)
- def find_opcode(self, name):
- try:
- return self.opname_to_index[name]
- except KeyError:
- self._register_opcode(name)
- return self.opname_to_index[name]
-
- def _register_opcode(self, opname):
- assert len(self.opcode_implementations) < 256, \
- "too many implementations of opcodes!"
- name = "opimpl_" + opname
- self.opname_to_index[opname] = len(self.opcode_implementations)
- self.opcode_names.append(opname)
- self.opcode_implementations.append(getattr(MIFrame, name).im_func)
-
# ---------------- logging ------------------------
def log(self, msg):
@@ -1268,6 +1214,7 @@
self.cpu = staticdata.cpu
self.portal_trace_positions = []
self.greenkey_of_huge_function = None
+ self.free_frames_list = []
def is_blackholing(self):
return self.history is None
@@ -1278,7 +1225,11 @@
if greenkey is not None and not self.is_blackholing():
self.portal_trace_positions.append(
(greenkey, len(self.history.operations)))
- f = MIFrame(self, jitcode, greenkey)
+ if len(self.free_frames_list) > 0:
+ f = self.free_frames_list.pop()
+ else:
+ f = MIFrame(self)
+ f.setup(jitcode, greenkey)
self.framestack.append(f)
return f
@@ -1289,10 +1240,13 @@
if frame.greenkey is not None and not self.is_blackholing():
self.portal_trace_positions.append(
(None, len(self.history.operations)))
- return frame
+ # we save the freed MIFrames to avoid needing to re-create new
+ # MIFrame objects all the time; they are a bit big, with their
+ # 3*256 register entries.
+ self.free_frames_list.append(frame)
def finishframe(self, resultbox):
- frame = self.popframe()
+ self.popframe()
if self.framestack:
if resultbox is not None:
self.framestack[-1].make_result_box(resultbox)
@@ -1501,7 +1455,7 @@
except:
import sys
if sys.exc_info()[0] is not None:
- codewriter.log.info(sys.exc_info()[0].__name__)
+ self.staticdata.log(sys.exc_info()[0].__name__)
raise
def compile_and_run_once(self, *args):
@@ -1739,7 +1693,19 @@
self.framestack = []
f = self.newframe(self.staticdata.portal_code)
f.pc = 0
- f.env = original_boxes[:]
+ count_i = count_r = count_f = 0
+ for box in original_boxes:
+ if box.type == history.INT:
+ f.boxes_i[count_i] = box
+ count_i += 1
+ elif box.type == history.REF:
+ f.boxes_r[count_r] = box
+ count_r += 1
+ elif box.type == history.FLOAT:
+ f.boxes_f[count_f] = box
+ count_f += 1
+ else:
+ raise AssertionError(box.type)
self.virtualref_boxes = []
self.initialize_virtualizable(original_boxes)
return original_boxes
@@ -2045,3 +2011,64 @@
assert target_loop_token is not None
self.argboxes = args
self.target_loop_token = target_loop_token
+
+# ____________________________________________________________
+
+class ChangeFrame(Exception):
+ pass
+
+def _get_opimpl_method(name, argcodes):
+ from pypy.jit.metainterp.blackhole import signedord
+ #
+ def handler(self, position):
+ args = ()
+ next_argcode = 0
+ code = self.bytecode
+ position += 1
+ for argtype in argtypes:
+ if argtype == "box":
+ argcode = argcodes[next_argcode]
+ next_argcode = next_argcode + 1
+ if argcode == 'i':
+ value = self.boxes_i[ord(code[position])]
+ elif argcode == 'c':
+ value = ConstInt(signedord(code[position]))
+ elif argcode == 'r':
+ value = self.boxes_r[ord(code[position])]
+ elif argcode == 'f':
+ value = self.boxes_f[ord(code[position])]
+ else:
+ raise AssertionError("bad argcode")
+ position += 1
+ else:
+ raise AssertionError("bad argtype: %r" % (argtype,))
+ args += (value,)
+ #
+ num_return_args = len(argcodes) - next_argcode
+ 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.boxes_i[target_index] = resultbox
+ elif result_argcode == 'r':
+ assert resultbox.type == history.REF
+ self.boxes_r[target_index] = resultbox
+ elif result_argcode == 'f':
+ assert resultbox.type == history.FLOAT
+ self.boxes_f[target_index] = resultbox
+ else:
+ raise AssertionError("bad result argcode")
+ #
+ unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func
+ argtypes = unrolling_iterable(unboundmethod.argtypes)
+ handler = func_with_new_name(handler, 'handler_' + name)
+ return handler
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_basic.py Wed Apr 28 18:33:30 2010
@@ -15,6 +15,7 @@
def _get_jitcodes(CPUClass, func, values, type_system):
from pypy.jit.codewriter import support, codewriter
+ func._jit_unroll_safe_ = True
rtyper = support.annotate(func, values, type_system=type_system)
graphs = rtyper.annotator.translator.graphs
stats = history.Stats()
@@ -44,21 +45,51 @@
blackholeinterp.run(mainjitcode, 0)
return blackholeinterp.result_i
-def _get_bare_metainterp(func, values, CPUClass, type_system):
- from pypy.annotation.policy import AnnotatorPolicy
- from pypy.annotation.model import lltype_to_annotation
- from pypy.rpython.test.test_llinterp import gengraph
+def _run_with_pyjitpl(cw, mainjitcode, args, testself):
+ from pypy.jit.metainterp import simple_optimize
- rtyper = support.annotate(func, values, type_system=type_system)
+ class DoneWithThisFrame(Exception):
+ pass
- stats = history.Stats()
- cpu = CPUClass(rtyper, stats, None, False)
- graphs = rtyper.annotator.translator.graphs
- opt = history.Options(listops=listops)
- metainterp_sd = pyjitpl.MetaInterpStaticData(graphs[0], cpu, stats, opt)
+ class DoneWithThisFrameRef(DoneWithThisFrame):
+ def __init__(self, cpu, *args):
+ DoneWithThisFrame.__init__(self, *args)
+
+ class FakeWarmRunnerState:
+ def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
+ pass
+
+ # pick the optimizer this way
+ optimize_loop = staticmethod(simple_optimize.optimize_loop)
+ optimize_bridge = staticmethod(simple_optimize.optimize_bridge)
+
+ trace_limit = sys.maxint
+ debug_level = 2
+
+ opt = history.Options(listops=True)
+ cpu = cw.cpu
+ metainterp_sd = pyjitpl.MetaInterpStaticData(cw, opt)
metainterp_sd.finish_setup(optimizer="bogus")
+ metainterp_sd.state = FakeWarmRunnerState()
+ metainterp_sd.state.cpu = metainterp_sd.cpu
metainterp = pyjitpl.MetaInterp(metainterp_sd)
- return metainterp, rtyper
+ if hasattr(testself, 'finish_metainterp_for_interp_operations'):
+ testself.finish_metainterp_for_interp_operations(metainterp)
+
+ metainterp_sd.portal_code = mainjitcode
+ metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
+ metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
+ metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
+ testself.metainterp = metainterp
+ try:
+ metainterp.compile_and_run_once(*args)
+ except DoneWithThisFrame, e:
+ #if conftest.option.view:
+ # metainterp.stats.view()
+ return e.args[0]
+ else:
+ raise Exception("FAILED")
+
class JitMixin:
basic = True
@@ -99,61 +130,11 @@
cw, mainjitcode = _get_jitcodes(self.CPUClass, f, args,
self.type_system)
# try to run it with blackhole.py
- result = _run_with_blackhole(cw, mainjitcode, args)
+ result1 = _run_with_blackhole(cw, mainjitcode, args)
# try to run it with pyjitpl.py
- # -- XXX --- missing
- return result
-
- from pypy.jit.metainterp import simple_optimize
-
- class DoneWithThisFrame(Exception):
- pass
-
- class DoneWithThisFrameRef(DoneWithThisFrame):
- def __init__(self, cpu, *args):
- DoneWithThisFrame.__init__(self, *args)
-
- class FakeWarmRunnerState:
- def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
- pass
-
- # pick the optimizer this way
- optimize_loop = staticmethod(simple_optimize.optimize_loop)
- optimize_bridge = staticmethod(simple_optimize.optimize_bridge)
-
- trace_limit = sys.maxint
- debug_level = 2
-
- metainterp, rtyper = _get_bare_metainterp(f, args, self.CPUClass,
- self.type_system,
- **kwds)
- metainterp.staticdata.state = FakeWarmRunnerState()
- metainterp.staticdata.state.cpu = metainterp.staticdata.cpu
- if hasattr(self, 'finish_metainterp_for_interp_operations'):
- self.finish_metainterp_for_interp_operations(metainterp)
- portal_graph = rtyper.annotator.translator.graphs[0]
- cw = codewriter.CodeWriter(rtyper)
-
- graphs = cw.find_all_graphs(portal_graph, JitPolicy(),
- self.CPUClass.supports_floats)
- cw._start(metainterp.staticdata, None)
- portal_graph.func._jit_unroll_safe_ = True
- maingraph = cw.make_one_bytecode((portal_graph, None), False)
- cw.finish_making_bytecodes()
- metainterp.staticdata.portal_code = maingraph
- metainterp.staticdata._class_sizes = cw.class_sizes
- metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame
- metainterp.staticdata.DoneWithThisFrameRef = DoneWithThisFrameRef
- metainterp.staticdata.DoneWithThisFrameFloat = DoneWithThisFrame
- self.metainterp = metainterp
- try:
- metainterp.compile_and_run_once(*args)
- except DoneWithThisFrame, e:
- #if conftest.option.view:
- # metainterp.stats.view()
- return e.args[0]
- else:
- raise Exception("FAILED")
+ result2 = _run_with_pyjitpl(cw, mainjitcode, args, self)
+ assert result1 == result2
+ return result1
def check_history(self, expected=None, **isns):
# this can be used after calling meta_interp
More information about the Pypy-commit
mailing list