[pypy-svn] r37681 - in pypy/branch/jit-virtual-world/pypy: annotation interpreter module/pypyjit module/pypyjit/test objspace/flow
arigo at codespeak.net
arigo at codespeak.net
Wed Jan 31 18:36:34 CET 2007
Author: arigo
Date: Wed Jan 31 18:36:27 2007
New Revision: 37681
Added:
pypy/branch/jit-virtual-world/pypy/module/pypyjit/test/ (props changed)
pypy/branch/jit-virtual-world/pypy/module/pypyjit/test/test_jit_setup.py (contents, props changed)
Modified:
pypy/branch/jit-virtual-world/pypy/annotation/binaryop.py
pypy/branch/jit-virtual-world/pypy/interpreter/eval.py
pypy/branch/jit-virtual-world/pypy/interpreter/pyframe.py
pypy/branch/jit-virtual-world/pypy/interpreter/pyopcode.py
pypy/branch/jit-virtual-world/pypy/module/pypyjit/interp_jit.py
pypy/branch/jit-virtual-world/pypy/objspace/flow/flowcontext.py
Log:
Work in progress. Modified the dispatch() header in a JIT-friendly and
overwhelmingly obscure way. Exposes a bug avoid Void fields in
virtualizables.
Modified: pypy/branch/jit-virtual-world/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/annotation/binaryop.py (original)
+++ pypy/branch/jit-virtual-world/pypy/annotation/binaryop.py Wed Jan 31 18:36:27 2007
@@ -266,7 +266,7 @@
def and_((int1, int2)):
knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
- return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
+ return SomeInteger(nonneg=int1.nonneg or int2.nonneg,
knowntype=knowntype)
and_.can_only_throw = []
Modified: pypy/branch/jit-virtual-world/pypy/interpreter/eval.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/interpreter/eval.py (original)
+++ pypy/branch/jit-virtual-world/pypy/interpreter/eval.py Wed Jan 31 18:36:27 2007
@@ -73,6 +73,8 @@
"""A frame is an environment supporting the execution of a code object.
Abstract base class."""
+ _virtualizable_ = True
+
def __init__(self, space, w_globals=None, numlocals=-1):
self.space = space
self.w_globals = w_globals # wrapped dict of globals
Modified: pypy/branch/jit-virtual-world/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/interpreter/pyframe.py (original)
+++ pypy/branch/jit-virtual-world/pypy/interpreter/pyframe.py Wed Jan 31 18:36:27 2007
@@ -88,12 +88,12 @@
executioncontext.enter(self)
try:
executioncontext.call_trace(self)
- code = self.pycode.co_code
# Execution starts just after the last_instr. Initially,
# last_instr is -1. After a generator suspends it points to
# the YIELD_VALUE instruction.
next_instr = self.last_instr + 1
- w_exitvalue = self.dispatch(code, next_instr, executioncontext)
+ w_exitvalue = self.dispatch(self.pycode, next_instr,
+ executioncontext)
rstack.resume_point("execute_frame", self, executioncontext, returns=w_exitvalue)
executioncontext.return_trace(self, w_exitvalue)
# on exit, we try to release self.last_exception -- breaks an
Modified: pypy/branch/jit-virtual-world/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/interpreter/pyopcode.py (original)
+++ pypy/branch/jit-virtual-world/pypy/interpreter/pyopcode.py Wed Jan 31 18:36:27 2007
@@ -4,6 +4,7 @@
pyfastscope.py and pynestedscope.py.
"""
+import sys
from pypy.interpreter.error import OperationError
from pypy.interpreter.baseobjspace import UnpackValueError, Wrappable
from pypy.interpreter import gateway, function, eval
@@ -40,7 +41,7 @@
return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname)
-BYTECODE_TRACE_ENABLED = True # see also pypy.module.pypyjit
+JITTING = False # see also pypy.module.pypyjit
class __extend__(pyframe.PyFrame):
@@ -49,12 +50,49 @@
### opcode dispatch ###
- def dispatch(self, co_code, next_instr, ec):
+ def dispatch(self, pycode, next_instr, ec):
+ if JITTING:
+ hint(None, global_merge_point=True)
+
+ # *loads* of nonsense for now
+ stuff = self.valuestackdepth
+ if len(self.blockstack):
+ stuff |= (-sys.maxint-1)
+
+ stuff = hint(stuff, promote=True)
+ if stuff >= 0:
+ # blockdepth == 0, common case
+ self.blockstack = []
+ depth = stuff & sys.maxint
+
+ pycode = hint(pycode, deepfrozen=True)
+ self.pycode = pycode
+ self.valuestackdepth = depth
+
+ virtualstack_w = [None] * pycode.co_stacksize
+ while depth > 0:
+ depth -= 1
+ hint(depth, concrete=True)
+ virtualstack_w[depth] = self.valuestack_w[depth]
+ self.valuestack_w = virtualstack_w
+
+ # For the sequel, force 'next_instr' to be unsigned for performance
+ next_instr = r_uint(next_instr)
+ co_code = pycode.co_code
+
while True:
+ hint(None, global_merge_point=True)
try:
- w_result = self.dispatch_bytecode(co_code, next_instr, ec)
- rstack.resume_point("dispatch", self, co_code, ec,
- returns=w_result)
+ self.last_instr = intmask(next_instr)
+ if not JITTING:
+ ec.bytecode_trace(self)
+ next_instr = r_uint(self.last_instr)
+ next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
+ #XXX
+ #rstack.resume_point("dispatch", self, co_code, ec,
+ # returns=w_result)
+ except Return:
+ w_result = self.popvalue()
return w_result
except OperationError, operr:
next_instr = self.handle_operation_error(ec, operr)
@@ -78,6 +116,7 @@
next_instr = self.handle_asynchronous_error(ec,
self.space.w_RuntimeError,
self.space.wrap(msg))
+ next_instr = hint(next_instr, promote=True)
def handle_asynchronous_error(self, ec, w_type, w_value=None):
# catch asynchronous exceptions and turn them
@@ -92,8 +131,7 @@
if attach_tb:
pytraceback.record_application_traceback(
self.space, operr, self, self.last_instr)
- if BYTECODE_TRACE_ENABLED:
- ec.exception_trace(self, operr)
+ ec.exception_trace(self, operr)
block = self.unrollstack(SApplicationException.kind)
if block is None:
@@ -111,100 +149,93 @@
return next_instr
def dispatch_bytecode(self, co_code, next_instr, ec):
- hint(None, global_merge_point=True)
- next_instr = hint(r_uint(next_instr), promote=True)
space = self.space
- while True:
- hint(None, global_merge_point=True)
- self.last_instr = intmask(next_instr)
- if BYTECODE_TRACE_ENABLED:
- ec.bytecode_trace(self)
- # For the sequel, force 'next_instr' to be unsigned for performance
- next_instr = r_uint(self.last_instr)
+ opcode = ord(co_code[next_instr])
+ next_instr += 1
+ if space.config.objspace.logbytecodes:
+ space.bytecodecounts[opcode] = space.bytecodecounts.get(opcode, 0) + 1
+
+ if opcode >= HAVE_ARGUMENT:
+ lo = ord(co_code[next_instr])
+ hi = ord(co_code[next_instr+1])
+ next_instr += 2
+ oparg = (hi << 8) | lo
+ else:
+ oparg = 0
+ hint(opcode, concrete=True)
+ hint(oparg, concrete=True)
+
+ while opcode == opcodedesc.EXTENDED_ARG.index:
opcode = ord(co_code[next_instr])
- next_instr += 1
- if space.config.objspace.logbytecodes:
- space.bytecodecounts[opcode] = space.bytecodecounts.get(opcode, 0) + 1
-
- if opcode >= HAVE_ARGUMENT:
- lo = ord(co_code[next_instr])
- hi = ord(co_code[next_instr+1])
- next_instr += 2
- oparg = (hi << 8) | lo
- else:
- oparg = 0
+ if opcode < HAVE_ARGUMENT:
+ raise BytecodeCorruption
+ lo = ord(co_code[next_instr+1])
+ hi = ord(co_code[next_instr+2])
+ next_instr += 3
+ oparg = (oparg << 16) | (hi << 8) | lo
hint(opcode, concrete=True)
hint(oparg, concrete=True)
- while opcode == opcodedesc.EXTENDED_ARG.index:
- opcode = ord(co_code[next_instr])
- if opcode < HAVE_ARGUMENT:
- raise BytecodeCorruption
- lo = ord(co_code[next_instr+1])
- hi = ord(co_code[next_instr+2])
- next_instr += 3
- oparg = (oparg << 16) | (hi << 8) | lo
- hint(opcode, concrete=True)
- hint(oparg, concrete=True)
-
- if opcode == opcodedesc.RETURN_VALUE.index:
- w_returnvalue = self.popvalue()
- block = self.unrollstack(SReturnValue.kind)
+ if opcode == opcodedesc.RETURN_VALUE.index:
+ w_returnvalue = self.popvalue()
+ block = self.unrollstack(SReturnValue.kind)
+ if block is None:
+ self.pushvalue(w_returnvalue) # XXX ping pong
+ raise Return
+ else:
+ unroller = SReturnValue(w_returnvalue)
+ next_instr = block.handle(self, unroller)
+ #next_instr = hint(next_instr, promote=True)
+ return next_instr # now inside a 'finally' block
+
+ if opcode == opcodedesc.YIELD_VALUE.index:
+ #self.last_instr = intmask(next_instr - 1) XXX clean up!
+ raise Return
+
+ if opcode == opcodedesc.END_FINALLY.index:
+ unroller = self.end_finally()
+ if isinstance(unroller, SuspendedUnroller):
+ # go on unrolling the stack
+ block = self.unrollstack(unroller.kind)
if block is None:
- return w_returnvalue
+ w_result = unroller.nomoreblocks()
+ self.pushvalue(w_result)
+ raise Return
else:
- unroller = SReturnValue(w_returnvalue)
next_instr = block.handle(self, unroller)
- next_instr = hint(next_instr, promote=True)
- continue # now inside a 'finally' block
-
- if opcode == opcodedesc.YIELD_VALUE.index:
- #self.last_instr = intmask(next_instr - 1) XXX clean up!
- w_yieldvalue = self.popvalue()
- return w_yieldvalue
-
- if opcode == opcodedesc.END_FINALLY.index:
- unroller = self.end_finally()
- if isinstance(unroller, SuspendedUnroller):
- # go on unrolling the stack
- block = self.unrollstack(unroller.kind)
- if block is None:
- return unroller.nomoreblocks()
- else:
- next_instr = block.handle(self, unroller)
- next_instr = hint(next_instr, promote=True)
- continue
+ #next_instr = hint(next_instr, promote=True)
+ return next_instr
- if we_are_translated():
- for opdesc in unrolling_opcode_descs:
- # static checks to skip this whole case if necessary
- if not opdesc.is_enabled(space):
- continue
- if not hasattr(pyframe.PyFrame, opdesc.methodname):
- continue # e.g. for JUMP_FORWARD, implemented above
-
- if opcode == opdesc.index:
- # dispatch to the opcode method
- meth = getattr(self, opdesc.methodname)
- res = meth(oparg, next_instr)
- if opdesc.index == opcodedesc.CALL_FUNCTION.index:
- rstack.resume_point("dispatch_call", self, co_code, next_instr, ec)
- # !! warning, for the annotator the next line is not
- # comparing an int and None - you can't do that.
- # Instead, it's constant-folded to either True or False
- if res is not None:
- next_instr = res
- next_instr = hint(next_instr, promote=True)
- break
- else:
- self.MISSING_OPCODE(oparg, next_instr)
+ if we_are_translated():
+ for opdesc in unrolling_opcode_descs:
+ # static checks to skip this whole case if necessary
+ if not opdesc.is_enabled(space):
+ continue
+ if not hasattr(pyframe.PyFrame, opdesc.methodname):
+ continue # e.g. for JUMP_FORWARD, implemented above
+
+ if opcode == opdesc.index:
+ # dispatch to the opcode method
+ meth = getattr(self, opdesc.methodname)
+ res = meth(oparg, next_instr)
+ if opdesc.index == opcodedesc.CALL_FUNCTION.index:
+ rstack.resume_point("dispatch_call", self, co_code, next_instr, ec)
+ # !! warning, for the annotator the next line is not
+ # comparing an int and None - you can't do that.
+ # Instead, it's constant-folded to either True or False
+ if res is not None:
+ next_instr = res
+ #next_instr = hint(next_instr, promote=True)
+ break
+ else:
+ self.MISSING_OPCODE(oparg, next_instr)
- else: # when we are not translated, a list lookup is much faster
- methodname = opcode_method_names[opcode]
- res = getattr(self, methodname)(oparg, next_instr)
- if res is not None:
- next_instr = res
- next_instr = hint(next_instr, promote=True)
+ else: # when we are not translated, a list lookup is much faster
+ methodname = opcode_method_names[opcode]
+ res = getattr(self, methodname)(oparg, next_instr)
+ if res is not None:
+ next_instr = res
+ return next_instr
def unrollstack(self, unroller_kind):
while len(self.blockstack) > 0:
@@ -223,17 +254,20 @@
### accessor functions ###
+ def getcode(self):
+ return hint(self.pycode, deepfrozen=True)
+
def getlocalvarname(self, index):
- return self.pycode.co_varnames[index]
+ return self.getcode().co_varnames[index]
def getconstant_w(self, index):
- return self.pycode.co_consts_w[index]
+ return self.getcode().co_consts_w[index]
def getname_u(self, index):
- return self.space.str_w(self.pycode.co_names_w[index])
+ return self.space.str_w(self.getcode().co_names_w[index])
def getname_w(self, index):
- return self.pycode.co_names_w[index]
+ return self.getcode().co_names_w[index]
################################################################
@@ -913,6 +947,9 @@
"""Signal an application-level OperationError that should not grow
a new traceback entry nor trigger the trace hook."""
+class Return(Exception):
+ """Obscure."""
+
class BytecodeCorruption(Exception):
"""Detected bytecode corruption. Never caught; it's an error."""
Modified: pypy/branch/jit-virtual-world/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/module/pypyjit/interp_jit.py (original)
+++ pypy/branch/jit-virtual-world/pypy/module/pypyjit/interp_jit.py Wed Jan 31 18:36:27 2007
@@ -15,78 +15,35 @@
PyCode.jit_enable = False # new default attribute
super_dispatch = PyFrame.dispatch
-super_dispatch_bytecode = PyFrame.dispatch_bytecode
def setup():
- # create dispatch_jit() as a copy of dispatch() in which
- # dispatch_bytecode() has been manually inlined.
- # Do this with py.code.Source manipulations for now.
- src = py.code.Source(super_dispatch)
- CALL_SITE = 'w_result = self.dispatch_bytecode(co_code, next_instr, ec)'
- for i, line in enumerate(src):
- if line.strip() == CALL_SITE:
- break
- else:
- raise Exception("fix me! call to dispatch_bytecode() not found")
-
- indent = line[:line.index(CALL_SITE)]
-
- src2 = py.code.Source(PyFrame.dispatch_bytecode)
- hdr = src2[0].strip()
- assert hdr == 'def dispatch_bytecode(self, co_code, next_instr, ec):'
- src2 = src2[1:].deindent().indent(indent)
- #print src2
-
- src3 = py.code.Source('%s\n%s\n%s\n' % (src[1:i], src2, src[i+1:]))
-
- src3 = src3.putaround(
- "def maker(BYTECODE_TRACE_ENABLED):\n" # no comma here
- " def dispatch_jit(self, co_code, next_instr, ec):\n",
- "#\n" # for indentation :-(
- " return dispatch_jit")
-
- #print src3
- d = {}
- exec src3.compile() in super_dispatch.func_globals, d
- PyFrame.dispatch_jit = d['maker'](BYTECODE_TRACE_ENABLED=False)
-
- class __extend__(PyFrame):
-
- def dispatch(self, co_code, next_instr, ec):
- if self.pycode.jit_enable:
- return self.dispatch_jit(co_code, next_instr, ec)
- else:
- return super_dispatch(self, co_code, next_instr, ec)
-
-def setup2():
- # TEMPORARY: only patches dispatch_bytecode.
- # make a copy of dispatch_bytecode in which BYTECODE_TRACE_ENABLED is False
+ # make a copy of dispatch in which JITTING is True
# (hack hack!)
- src2 = py.code.Source(PyFrame.dispatch_bytecode)
+ src2 = py.code.Source(PyFrame.dispatch)
hdr = src2[0].strip()
- assert hdr == 'def dispatch_bytecode(self, co_code, next_instr, ec):'
+ assert hdr == 'def dispatch(self, pycode, next_instr, ec):'
src2 = src2[1:].deindent()
src2 = src2.putaround(
- "def maker(BYTECODE_TRACE_ENABLED):\n" # no comma here
- " def dispatch_jit(self, co_code, next_instr, ec):\n",
+ "def maker(JITTING):\n"
+ " def dispatch_jit(self, pycode, next_instr, ec):\n",
"#\n" # for indentation :-(
" return dispatch_jit")
- #print src2
+ print src2
d = {}
exec src2.compile() in super_dispatch.func_globals, d
- PyFrame.dispatch_jit = d['maker'](BYTECODE_TRACE_ENABLED=False)
+ PyFrame.dispatch_jit = d['maker'](JITTING=True)
class __extend__(PyFrame):
- def dispatch_bytecode(self, co_code, next_instr, ec):
- if self.pycode.jit_enable:
- return self.dispatch_jit(co_code, next_instr, ec)
+ def dispatch(self, pycode, next_instr, ec):
+ if pycode.jit_enable:
+ return self.dispatch_jit(pycode, next_instr, ec)
else:
- return super_dispatch_bytecode(self, co_code, next_instr, ec)
+ return super_dispatch(self, pycode, next_instr, ec)
-setup2()
+setup()
PORTAL = PyFrame.dispatch_jit
Added: pypy/branch/jit-virtual-world/pypy/module/pypyjit/test/test_jit_setup.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-virtual-world/pypy/module/pypyjit/test/test_jit_setup.py Wed Jan 31 18:36:27 2007
@@ -0,0 +1,18 @@
+from pypy.conftest import gettestobjspace
+
+class AppTestPyPyJIT:
+ def setup_class(cls):
+ space = gettestobjspace(usemodules=('pypyjit',))
+ cls.space = space
+
+ def test_setup(self):
+ # this just checks that setup() is doing its job correctly, and
+ # the resulting code makes sense on top of CPython.
+ import pypyjit
+
+ def f(x, y):
+ return x*y+1
+
+ assert f(6, 7) == 43
+ pypyjit.enable(f.func_code)
+ assert f(6, 7) == 43
Modified: pypy/branch/jit-virtual-world/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/objspace/flow/flowcontext.py (original)
+++ pypy/branch/jit-virtual-world/pypy/objspace/flow/flowcontext.py Wed Jan 31 18:36:27 2007
@@ -262,7 +262,7 @@
self.framestack.push(frame)
self.crnt_frame = frame
try:
- w_result = frame.dispatch(frame.pycode.co_code,
+ w_result = frame.dispatch(frame.pycode,
frame.last_instr,
self)
finally:
More information about the Pypy-commit
mailing list