[pypy-svn] r73394 - in pypy/branch/decouple-host-opcodes/pypy: . interpreter objspace/flow objspace/flow/test objspace/std tool
antoine at codespeak.net
antoine at codespeak.net
Mon Apr 5 02:16:11 CEST 2010
Author: antoine
Date: Mon Apr 5 02:16:09 2010
New Revision: 73394
Modified:
pypy/branch/decouple-host-opcodes/pypy/ (props changed)
pypy/branch/decouple-host-opcodes/pypy/interpreter/baseobjspace.py
pypy/branch/decouple-host-opcodes/pypy/interpreter/function.py
pypy/branch/decouple-host-opcodes/pypy/interpreter/pyframe.py
pypy/branch/decouple-host-opcodes/pypy/interpreter/pyopcode.py
pypy/branch/decouple-host-opcodes/pypy/objspace/flow/flowcontext.py
pypy/branch/decouple-host-opcodes/pypy/objspace/flow/test/test_objspace.py
pypy/branch/decouple-host-opcodes/pypy/objspace/std/frame.py
pypy/branch/decouple-host-opcodes/pypy/objspace/std/objspace.py
pypy/branch/decouple-host-opcodes/pypy/tool/stdlib_opcode.py
Log:
Initial draft, using separate subclasses for pypy bytecode frames
and host bytecode frames.
Not sure it translates properly, although I've already fixed a
couple of issues.
Modified: pypy/branch/decouple-host-opcodes/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/interpreter/baseobjspace.py Mon Apr 5 02:16:09 2010
@@ -257,8 +257,13 @@
self.actionflag.register_action(self.user_del_action)
self.actionflag.register_action(self.frame_trace_action)
- from pypy.interpreter.pyframe import PyFrame
- self.FrameClass = PyFrame # can be overridden to a subclass
+ from pypy.interpreter.pycode import cpython_magic, default_magic
+ from pypy.interpreter.pyframe import PyPyFrame, HostPyFrame
+ self.our_magic = default_magic
+ self.host_magic = cpython_magic
+ # can be overridden to a subclass
+ self.FrameClass = PyPyFrame
+ self.HostFrameClass = HostPyFrame
if self.config.objspace.logbytecodes:
self.bytecodecounts = [0] * 256
@@ -589,7 +594,12 @@
def createframe(self, code, w_globals, closure=None):
"Create an empty PyFrame suitable for this code object."
- return self.FrameClass(self, code, w_globals, closure)
+ magic = code.magic
+ if magic == self.host_magic:
+ return self.HostFrameClass(self, code, w_globals, closure)
+ elif magic == self.our_magic:
+ return self.FrameClass(self, code, w_globals, closure)
+ raise ValueError("bad magic %s" % magic)
def allocate_lock(self):
"""Return an interp-level Lock object if threads are enabled,
Modified: pypy/branch/decouple-host-opcodes/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/interpreter/function.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/interpreter/function.py Mon Apr 5 02:16:09 2010
@@ -236,9 +236,9 @@
from pypy.interpreter.gateway import BuiltinCode
if isinstance(self.code, BuiltinCode):
identifier = self.code.identifier
- if Function._all.get(identifier, self) is not self:
- print "builtin code identifier %s used twice: %s and %s" % (
- identifier, self, Function._all[identifier])
+ #if Function._all.get(identifier, self) is not self:
+ #print "builtin code identifier %s used twice: %s and %s" % (
+ #identifier, self, Function._all[identifier])
# we have been seen by other means so rtyping should not choke
# on us
Function._all[identifier] = self
Modified: pypy/branch/decouple-host-opcodes/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/interpreter/pyframe.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/interpreter/pyframe.py Mon Apr 5 02:16:09 2010
@@ -135,8 +135,9 @@
from pypy.rlib import rstack
# the following 'assert' is an annotation hint: it hides from
# the annotator all methods that are defined in PyFrame but
- # overridden in the FrameClass subclass of PyFrame.
- assert isinstance(self, self.space.FrameClass)
+ # overridden in the {,Host}FrameClass subclasses of PyFrame.
+ assert (isinstance(self, self.space.FrameClass)
+ or isinstance(self, self.space.HostFrameClass))
executioncontext = self.space.getexecutioncontext()
executioncontext.enter(self)
try:
@@ -628,6 +629,13 @@
return space.wrap(self.builtin is not space.builtin)
return space.w_False
+
+class PyPyFrame(PyFrame):
+ pass
+
+class HostPyFrame(PyFrame):
+ pass
+
# ____________________________________________________________
def get_block_class(opname):
Modified: pypy/branch/decouple-host-opcodes/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/interpreter/pyopcode.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/interpreter/pyopcode.py Mon Apr 5 02:16:09 2010
@@ -14,9 +14,9 @@
from pypy.rlib import jit, rstackovf
from pypy.rlib.rarithmetic import r_uint, intmask
from pypy.rlib.unroll import unrolling_iterable
-from pypy.tool.stdlib_opcode import (opcodedesc, HAVE_ARGUMENT,
- unrolling_opcode_descs,
- opcode_method_names)
+from pypy.tool.stdlib_opcode import (unrolling_opcode_descs,
+ HAVE_ARGUMENT, host_HAVE_ARGUMENT, opcodedesc, host_opcodedesc,
+ opcode_method_names, host_opcode_method_names, )
def unaryoperation(operationname):
"""NOT_RPYTHON"""
@@ -180,7 +180,7 @@
probs[opcode] = probs.get(opcode, 0) + 1
self.last_opcode = opcode
- if opcode >= HAVE_ARGUMENT:
+ if opcode >= self.HAVE_ARGUMENT:
lo = ord(co_code[next_instr])
hi = ord(co_code[next_instr+1])
next_instr += 2
@@ -188,16 +188,16 @@
else:
oparg = 0
- while opcode == opcodedesc.EXTENDED_ARG.index:
+ while opcode == self.opcodedesc.EXTENDED_ARG.index:
opcode = ord(co_code[next_instr])
- if opcode < HAVE_ARGUMENT:
+ if opcode < self.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
- if opcode == opcodedesc.RETURN_VALUE.index:
+ if opcode == self.opcodedesc.RETURN_VALUE.index:
w_returnvalue = self.popvalue()
block = self.unrollstack(SReturnValue.kind)
if block is None:
@@ -208,11 +208,11 @@
next_instr = block.handle(self, unroller)
return next_instr # now inside a 'finally' block
- if opcode == opcodedesc.YIELD_VALUE.index:
+ if opcode == self.opcodedesc.YIELD_VALUE.index:
#self.last_instr = intmask(next_instr - 1) XXX clean up!
raise Yield
- if opcode == opcodedesc.END_FINALLY.index:
+ if opcode == self.opcodedesc.END_FINALLY.index:
unroller = self.end_finally()
if isinstance(unroller, SuspendedUnroller):
# go on unrolling the stack
@@ -225,7 +225,7 @@
next_instr = block.handle(self, unroller)
return next_instr
- if opcode == opcodedesc.JUMP_ABSOLUTE.index:
+ if opcode == self.opcodedesc.JUMP_ABSOLUTE.index:
return self.jump_absolute(oparg, next_instr, ec)
if we_are_translated():
@@ -242,7 +242,7 @@
# dispatch to the opcode method
meth = getattr(self, opdesc.methodname)
res = meth(oparg, next_instr)
- if opdesc.index == opcodedesc.CALL_FUNCTION.index:
+ if opdesc.index == self.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.
@@ -254,7 +254,7 @@
self.MISSING_OPCODE(oparg, next_instr)
else: # when we are not translated, a list lookup is much faster
- methodname = opcode_method_names[opcode]
+ methodname = self.opcode_method_names[opcode]
res = getattr(self, methodname)(oparg, next_instr)
if res is not None:
next_instr = res
@@ -690,26 +690,6 @@
w_list = self.space.newlist(items)
self.pushvalue(w_list)
- def BUILD_MAP(self, itemcount, next_instr):
- if not we_are_translated() and sys.version_info >= (2, 6):
- # We could pre-allocate a dict here
- # but for the moment this code is not translated.
- pass
- else:
- if itemcount != 0:
- raise BytecodeCorruption
- w_dict = self.space.newdict()
- self.pushvalue(w_dict)
-
- def STORE_MAP(self, zero, next_instr):
- if not we_are_translated() and sys.version_info >= (2, 6):
- w_key = self.popvalue()
- w_value = self.popvalue()
- w_dict = self.peekvalue()
- self.space.setitem(w_dict, w_key, w_value)
- else:
- raise BytecodeCorruption
-
def LOAD_ATTR(self, nameindex, next_instr):
"obj.attributename"
w_attributename = self.getname_w(nameindex)
@@ -1020,6 +1000,48 @@
STOP_CODE = MISSING_OPCODE
+class __extend__(pyframe.PyPyFrame):
+ opcode_method_names = opcode_method_names
+ opcodedesc = opcodedesc
+ HAVE_ARGUMENT = HAVE_ARGUMENT
+
+ def BUILD_MAP(self, itemcount, next_instr):
+ if itemcount != 0:
+ raise BytecodeCorruption
+ w_dict = self.space.newdict()
+ self.pushvalue(w_dict)
+
+ def STORE_MAP(self, zero, next_instr):
+ raise BytecodeCorruption
+
+host_version_info = sys.version_info
+
+class __extend__(pyframe.HostPyFrame):
+ opcode_method_names = host_opcode_method_names
+ opcodedesc = host_opcodedesc
+ HAVE_ARGUMENT = host_HAVE_ARGUMENT
+
+ def BUILD_MAP(self, itemcount, next_instr):
+ if host_version_info >= (2, 6):
+ # We could pre-allocate a dict here
+ # but for the moment this code is not translated.
+ pass
+ else:
+ if itemcount != 0:
+ raise BytecodeCorruption
+ w_dict = self.space.newdict()
+ self.pushvalue(w_dict)
+
+ def STORE_MAP(self, zero, next_instr):
+ if host_version_info >= (2, 6):
+ w_key = self.popvalue()
+ w_value = self.popvalue()
+ w_dict = self.peekvalue()
+ self.space.setitem(w_dict, w_key, w_value)
+ else:
+ raise BytecodeCorruption
+
+
### ____________________________________________________________ ###
class ExitFrame(Exception):
Modified: pypy/branch/decouple-host-opcodes/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/objspace/flow/flowcontext.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/objspace/flow/flowcontext.py Mon Apr 5 02:16:09 2010
@@ -1,7 +1,7 @@
import collections
from pypy.interpreter.executioncontext import ExecutionContext
from pypy.interpreter.error import OperationError
-from pypy.interpreter import pyframe
+from pypy.interpreter import pyframe, pycode
from pypy.interpreter.argument import ArgumentsForTranslation
from pypy.objspace.flow.model import *
from pypy.objspace.flow.framestate import FrameState
@@ -219,8 +219,12 @@
# create an empty frame suitable for the code object
# while ignoring any operation like the creation of the locals dict
self.recorder = []
- frame = FlowSpaceFrame(self.space, self.code,
- self.w_globals, self.closure)
+ if self.code.magic == pycode.cpython_magic:
+ frame = FlowSpaceHostPyFrame(self.space, self.code,
+ self.w_globals, self.closure)
+ else:
+ frame = FlowSpacePyPyFrame(self.space, self.code,
+ self.w_globals, self.closure)
frame.last_instr = 0
return frame
@@ -398,7 +402,7 @@
if w_v.value is oldvalue:
stack_items_w[i] = w_new
-class FlowSpaceFrame(pyframe.PyFrame):
+class FlowSpaceFrameBase(object):
def make_arguments(self, nargs):
return ArgumentsForTranslation(self.space, self.peekvalues(nargs))
def argument_factory(self, *args):
@@ -410,3 +414,10 @@
raise operr
return pyframe.PyFrame.handle_operation_error(self, ec, operr,
*args, **kwds)
+
+class FlowSpacePyPyFrame(FlowSpaceFrameBase, pyframe.PyPyFrame):
+ pass
+
+class FlowSpaceHostPyFrame(FlowSpaceFrameBase, pyframe.HostPyFrame):
+ pass
+
Modified: pypy/branch/decouple-host-opcodes/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/objspace/flow/test/test_objspace.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/objspace/flow/test/test_objspace.py Mon Apr 5 02:16:09 2010
@@ -826,23 +826,34 @@
""" Tests code generated by pypy-c compiled with CALL_METHOD
bytecode
"""
- class X:
- def m(self):
- return 3
-
- def f():
- x = X()
- return x.m()
-
- # this code is generated by pypy-c when compiling above f
- pypy_code = 't\x00\x00\x83\x00\x00}\x00\x00|\x00\x00\x91\x02\x00\x92\x00\x00Sd\x00\x00S'
- new_c = self.monkey_patch_code(f.func_code, 3, 3, pypy_code, ('X', 'x', 'm'), ('x',))
- f2 = new.function(new_c, locals(), 'f')
-
- graph = self.codetest(f2)
- all_ops = self.all_operations(graph)
- assert all_ops['simple_call'] == 2
- assert all_ops['getattr'] == 1
+ from pypy.objspace.flow import flowcontext
+ old_class = flowcontext.FlowSpaceHostPyFrame
+ try:
+ # HACK: we will replace a host-generated code object with a
+ # pypy-generated code object, but it will carry the host's
+ # magic number (since it's generated with the host's code.new).
+ flowcontext.FlowSpaceHostPyFrame = flowcontext.FlowSpacePyPyFrame
+ class X:
+ def m(self):
+ return 3
+
+ def f():
+ x = X()
+ return x.m()
+
+ # this code is generated by pypy-c when compiling above f
+ pypy_code = 't\x00\x00\x83\x00\x00}\x00\x00|\x00\x00\x91\x02\x00\x92\x00\x00Sd\x00\x00S'
+ new_c = self.monkey_patch_code(f.func_code, 3, 3, pypy_code, ('X', 'x', 'm'), ('x',))
+ f2 = new.function(new_c, locals(), 'f')
+ import dis
+ dis.dis(f2)
+
+ graph = self.codetest(f2)
+ all_ops = self.all_operations(graph)
+ assert all_ops['simple_call'] == 2
+ assert all_ops['getattr'] == 1
+ finally:
+ flowcontext.FlowSpaceHostPyFrame = old_class
def test_generator(self):
def f():
Modified: pypy/branch/decouple-host-opcodes/pypy/objspace/std/frame.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/objspace/std/frame.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/objspace/std/frame.py Mon Apr 5 02:16:09 2010
@@ -3,14 +3,16 @@
import operator
from pypy.rlib.unroll import unrolling_iterable
-from pypy.interpreter import pyframe, pyopcode, function
+from pypy.interpreter import pyopcode, function
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module
from pypy.objspace.std.multimethod import FailedToImplement
-class BaseFrame(pyframe.PyFrame):
+
+class BaseFrame(object):
"""These opcodes are always overridden."""
+ _mixin_ = True
def LIST_APPEND(f, oparg, next_instr):
from pypy.objspace.std.listobject import W_ListObject
@@ -135,9 +137,9 @@
f.pushvalue(w_result)
-def build_frame(space):
+def build_frame(space, baseclass):
"""Consider the objspace config and return a patched frame object."""
- class StdObjSpaceFrame(BaseFrame):
+ class StdObjSpaceFrame(baseclass, BaseFrame):
pass
if space.config.objspace.std.optimized_int_add:
if space.config.objspace.std.withsmallint:
Modified: pypy/branch/decouple-host-opcodes/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/objspace/std/objspace.py Mon Apr 5 02:16:09 2010
@@ -47,7 +47,9 @@
# setup all the object types and implementations
self.model = model.StdTypeModel(self.config)
- self.FrameClass = frame.build_frame(self)
+ from pypy.interpreter.pyframe import PyPyFrame, HostPyFrame
+ self.FrameClass = frame.build_frame(self, PyPyFrame)
+ self.HostFrameClass = frame.build_frame(self, HostPyFrame)
if self.config.objspace.std.withrope:
self.StringObjectCls = W_RopeObject
@@ -133,7 +135,7 @@
if not we_are_translated() and isinstance(code, CPythonFakeCode):
return CPythonFakeFrame(self, code, w_globals)
else:
- return self.FrameClass(self, code, w_globals, closure)
+ return ObjSpace.createframe(self, code, w_globals, closure)
def gettypefor(self, cls):
return self.gettypeobject(cls.typedef)
Modified: pypy/branch/decouple-host-opcodes/pypy/tool/stdlib_opcode.py
==============================================================================
--- pypy/branch/decouple-host-opcodes/pypy/tool/stdlib_opcode.py (original)
+++ pypy/branch/decouple-host-opcodes/pypy/tool/stdlib_opcode.py Mon Apr 5 02:16:09 2010
@@ -4,6 +4,9 @@
'hasconst', 'hasname', 'hasjrel', 'hasjabs',
'haslocal', 'hascompare', 'hasfree', 'cmp_op']
+from opcode import (
+ opmap as host_opmap, HAVE_ARGUMENT as host_HAVE_ARGUMENT)
+
def load_opcode():
import py
opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/modified-2.5.2/opcode.py')
@@ -23,65 +26,83 @@
STORE_SLICE = opmap["STORE_SLICE+0"]
DELETE_SLICE = opmap["DELETE_SLICE+0"]
-opcode_method_names = ['MISSING_OPCODE'] * 256
-for name, index in opmap.items():
- opcode_method_names[index] = name.replace('+', '_')
+def make_method_names(opmap):
+ tbl = ['MISSING_OPCODE'] * 256
+ for name, index in opmap.items():
+ tbl[index] = name.replace('+', '_')
+ return tbl
+
+opcode_method_names = make_method_names(opmap)
+host_opcode_method_names = make_method_names(host_opmap)
+#print (
+ #set(enumerate(opcode_method_names)) ^ set(enumerate(host_opcode_method_names))
+#)
+del make_method_names
# ____________________________________________________________
# RPython-friendly helpers and structures
from pypy.rlib.unroll import unrolling_iterable
+def make_opcode_desc(HAVE_ARGUMENT):
+ class OpcodeDesc(object):
+ def __init__(self, name, index):
+ self.name = name
+ self.methodname = opcode_method_names[index]
+ self.index = index
+ self.hasarg = index >= HAVE_ARGUMENT
+
+ def _freeze_(self):
+ return True
+
+ def is_enabled(self, space):
+ """Check if the opcode should be enabled in the space's configuration.
+ (Returns True for all standard opcodes.)"""
+ opt = space.config.objspace.opcodes
+ return getattr(opt, self.name, True)
+ is_enabled._annspecialcase_ = 'specialize:memo'
+
+ # for predictable results, we try to order opcodes most-used-first
+ opcodeorder = [124, 125, 100, 105, 1, 131, 116, 111, 106, 83, 23, 93, 113, 25, 95, 64, 112, 66, 102, 110, 60, 92, 62, 120, 68, 87, 32, 136, 4, 103, 24, 63, 18, 65, 15, 55, 121, 3, 101, 22, 12, 80, 86, 135, 126, 90, 140, 104, 2, 33, 20, 108, 107, 31, 134, 132, 88, 30, 133, 130, 137, 141, 61, 122, 11, 40, 74, 73, 51, 96, 21, 42, 56, 85, 82, 89, 142, 77, 78, 79, 91, 76, 97, 57, 19, 43, 84, 50, 41, 99, 53, 26]
+
+ def sortkey(self):
+ try:
+ i = self.opcodeorder.index(self.index)
+ except ValueError:
+ i = 1000000
+ return i, self.index
+
+ def __cmp__(self, other):
+ return (cmp(self.__class__, other.__class__) or
+ cmp(self.sortkey(), other.sortkey()))
-class OpcodeDesc(object):
- def __init__(self, name, index):
- self.name = name
- self.methodname = opcode_method_names[index]
- self.index = index
- self.hasarg = index >= HAVE_ARGUMENT
-
- def _freeze_(self):
- return True
-
- def is_enabled(self, space):
- """Check if the opcode should be enabled in the space's configuration.
- (Returns True for all standard opcodes.)"""
- opt = space.config.objspace.opcodes
- return getattr(opt, self.name, True)
- is_enabled._annspecialcase_ = 'specialize:memo'
-
- # for predictable results, we try to order opcodes most-used-first
- opcodeorder = [124, 125, 100, 105, 1, 131, 116, 111, 106, 83, 23, 93, 113, 25, 95, 64, 112, 66, 102, 110, 60, 92, 62, 120, 68, 87, 32, 136, 4, 103, 24, 63, 18, 65, 15, 55, 121, 3, 101, 22, 12, 80, 86, 135, 126, 90, 140, 104, 2, 33, 20, 108, 107, 31, 134, 132, 88, 30, 133, 130, 137, 141, 61, 122, 11, 40, 74, 73, 51, 96, 21, 42, 56, 85, 82, 89, 142, 77, 78, 79, 91, 76, 97, 57, 19, 43, 84, 50, 41, 99, 53, 26]
-
- def sortkey(self):
- try:
- i = self.opcodeorder.index(self.index)
- except ValueError:
- i = 1000000
- return i, self.index
-
- def __cmp__(self, other):
- return (cmp(self.__class__, other.__class__) or
- cmp(self.sortkey(), other.sortkey()))
+ return OpcodeDesc
+
+OpcodeDesc = make_opcode_desc(HAVE_ARGUMENT)
+HostOpcodeDesc = make_opcode_desc(host_HAVE_ARGUMENT)
opdescmap = {}
-class opcodedesc:
+class _baseopcodedesc:
+ pass
+
+class opcodedesc(_baseopcodedesc):
"""A namespace mapping OPCODE_NAME to OpcodeDescs."""
+class host_opcodedesc(_baseopcodedesc):
+ """A namespace mapping OPCODE_NAME to HostOpcodeDescs."""
+
for name, index in opmap.items():
desc = OpcodeDesc(name, index)
setattr(opcodedesc, name, desc)
opdescmap[index] = desc
+for name, index in host_opmap.items():
+ desc = HostOpcodeDesc(name, index)
+ setattr(host_opcodedesc, name, desc)
+
lst = opdescmap.values()
lst.sort()
unrolling_opcode_descs = unrolling_iterable(lst)
-# Allow non-translated code to interpret the new 2.6 bytecodes
-import sys
-if sys.version_info >= (2, 6):
- import opcode
- opcode_method_names[opcode.opmap['STORE_MAP']] = 'STORE_MAP'
-
del name, index, desc, lst
More information about the Pypy-commit
mailing list