[pypy-svn] r64662 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph backend/minimal backend/x86 metainterp
benjamin at codespeak.net
benjamin at codespeak.net
Sat Apr 25 02:55:49 CEST 2009
Author: benjamin
Date: Sat Apr 25 02:55:49 2009
New Revision: 64662
Modified:
pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
Log:
implement serialization of prebuilt AbstractValues for space in the binary
At the moment, only simple ConstInt can be serialized
I refactored out jitcode decoding from MIFrame
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Sat Apr 25 02:55:49 2009
@@ -234,6 +234,9 @@
def cast_int_to_adr(self, int):
return llimpl.cast_int_to_adr(self.memo_cast, int)
+ def unserialize_prebuilt(self, const_type, decoder):
+ pass
+
class LLtypeCPU(BaseCPU):
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/minimal/runner.py Sat Apr 25 02:55:49 2009
@@ -39,6 +39,9 @@
def compile_operations(self, loop):
pass
+ def unserialize_prebuilt(self, const_type, decoder):
+ pass
+
def execute_operations(self, loop, valueboxes):
if DEBUG:
print "execute_operations: starting", loop
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sat Apr 25 02:55:49 2009
@@ -609,6 +609,9 @@
counter += 1
return counter, basesize, ptr
+ def unserialize_prebuilt(self, const_type, decoder):
+ pass
+
def calldescrof(self, functype, argtypes, resulttype):
if resulttype is lltype.Void:
size = 0
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sat Apr 25 02:55:49 2009
@@ -6,7 +6,7 @@
from pypy.rlib import objectmodel
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.jit import _we_are_jitted
-from pypy.jit.metainterp.history import Const, getkind
+from pypy.rlib.rarithmetic import intmask
from pypy.jit.metainterp import heaptracker, support, history
from pypy.tool.udir import udir
from pypy.translator.simplify import get_funcobj, get_functype
@@ -30,18 +30,82 @@
self.called_from = called_from
self.graph = graph
- def setup(self, code, constants):
+ def setup(self, code, constant_code, unserialized):
self.code = code
- self.constants = constants
+ self.serialized_constants = constant_code
+ self.unserialized_constants = unserialized
+ self.constants = None
+
+ def ensure_constants(self, cpu):
+ if self.constants is None:
+ self.constants = []
+ decoder = JitCodeDecoder(self.serialized_constants)
+ const_code_len = len(self.serialized_constants)
+ unserialized_index = 0
+ while decoder.pc < const_code_len:
+ const_type = decoder.load_int()
+ if const_type == history.CONST_NOT_SERIALIZED:
+ const = self.unserialized_constants[unserialized_index]
+ unserialized_index += 1
+ else:
+ const = history.unserialize_prebuilt(const_type, decoder, cpu)
+ self.constants.append(const)
+ return self.constants
def __repr__(self):
return '<JitCode %r>' % (getattr(self, 'name', '?'),)
- def dump(self, file=None):
+ def dump(self, cpu, file=None):
+ self.ensure_constants(cpu)
import dump
dump.dump_bytecode(self, file=file)
print >> file
+
+class JitCodeDecoder(object):
+
+ def __init__(self, bytecode):
+ self.bytecode = bytecode
+ self.pc = 0
+
+ def load_int(self):
+ pc = self.pc
+ result = ord(self.bytecode[pc])
+ self.pc = pc + 1
+ if result > 0x7F:
+ result = self._load_larger_int(result)
+ return result
+
+ def _load_larger_int(self, result): # slow path
+ result = result & 0x7F
+ shift = 7
+ pc = self.pc
+ while 1:
+ byte = ord(self.bytecode[pc])
+ pc += 1
+ result += (byte & 0x7F) << shift
+ shift += 7
+ if not byte & 0x80:
+ break
+ self.pc = pc
+ return intmask(result)
+ _load_larger_int._dont_inline_ = True
+
+ def load_3byte(self):
+ pc = self.pc
+ result = (((ord(self.bytecode[pc + 0])) << 16) |
+ ((ord(self.bytecode[pc + 1])) << 8) |
+ ((ord(self.bytecode[pc + 2])) << 0))
+ self.pc = pc + 3
+ return result
+
+ def load_bool(self):
+ pc = self.pc
+ result = ord(self.bytecode[pc])
+ self.pc = pc + 1
+ return bool(result)
+
+
class IndirectCallset(history.AbstractValue):
def __init__(self, codewriter, graphs):
keys = []
@@ -228,7 +292,7 @@
## [TP], OF)
## insert_func, _ = support.builtin_func_for_spec(rtyper,
## 'list.insert', [TP, lltype.Signed, OF], lltype.Void)
- tp = getkind(OF)
+ tp = history.getkind(OF)
## if isinstance(TP.TO, lltype.GcStruct):
## ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu),
## history.ConstAddr(setfunc.value, self.cpu),
@@ -282,24 +346,40 @@
code = assemble(labelpos, self.codewriter.metainterp_sd,
self.assembler)
self.resolve_switch_targets(labelpos)
- self.bytecode.setup(code, self.constants)
+ const_code, consts = self.serialize_constants()
+ self.bytecode.setup(code, const_code, consts)
self.bytecode._source = self.assembler
self.bytecode._metainterp_sd = self.codewriter.metainterp_sd
self.bytecode._labelpos = labelpos
if self.debug:
- self.bytecode.dump()
+ self.bytecode.dump(self.cpu)
else:
print repr(self.bytecode)
dir = udir.ensure("jitcodes", dir=1)
- self.bytecode.dump(open(str(dir.join(self.bytecode.name)), "w"))
+ self.bytecode.dump(self.cpu,
+ open(str(dir.join(self.bytecode.name)), "w"))
+
+ def serialize_constants(self):
+ code = []
+ unserialized = []
+ for const in self.constants:
+ try:
+ as_bytecode = const.serialize()
+ except history.Unserializable:
+ code.append(history.CONST_NOT_SERIALIZED)
+ unserialized.append(const)
+ else:
+ code.extend(as_bytecode)
+ bytecode = assemble_constant_code(code)
+ return bytecode, unserialized
def const_position(self, constvalue):
"""Generate a constant of the given value.
Returns its index in the list self.positions[].
"""
if constvalue is _we_are_jitted: constvalue = True
- const = Const._new(constvalue, self.cpu)
+ const = history.Const._new(constvalue, self.cpu)
return self.get_position(const)
def get_position(self, x):
@@ -1158,6 +1238,17 @@
break
return result
+def assemble_constant_code(assembler):
+ result = []
+ for arg in assembler:
+ if isinstance(arg, bool):
+ result.append(chr(int(arg)))
+ elif isinstance(arg, int):
+ result.extend(encode_int(arg))
+ else:
+ raise AssertionError("not simple enough %s" % arg)
+ return "".join(result)
+
def assemble(labelpos, metainterp_sd, assembler):
result = []
for arg in assembler:
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Sat Apr 25 02:55:49 2009
@@ -101,6 +101,9 @@
def sort_key(self):
raise NotImplementedError
+ def serialize(self):
+ raise Unserializable
+
class AbstractDescr(AbstractValue):
def handle_fail_op(self, metainterp, fail_op):
raise NotImplementedError
@@ -116,6 +119,18 @@
def get_jitcode_for_class(self, oocls):
return self.jitcodes[oocls]
+class Unserializable(Exception):
+ pass
+
+CONST_TYPE_INT = 1
+CONST_TYPE_ADDR = 2
+CONST_NOT_SERIALIZED = 100
+
+def unserialize_prebuilt(const_type, decoder, cpu):
+ if const_type == CONST_TYPE_INT:
+ return ConstInt(decoder.load_int())
+ return cpu.unserialize_prebuilt(const_type, decoder)
+
class Const(AbstractValue):
__slots__ = ()
@@ -148,6 +163,17 @@
def constbox(self):
return self
+ def serialize(self):
+ """
+ NOT_RPYTHON
+ Convert this constant into a list of strings for JIT bytecode.
+ """
+ # A useful generic implementation.
+ try:
+ return (self.const_type, self.value)
+ except AttributeError:
+ raise Unserializable
+
def __repr__(self):
return 'Const(%s)' % self._getrepr_()
@@ -178,6 +204,7 @@
class ConstInt(Const):
type = INT
+ const_type = CONST_TYPE_INT
_attrs_ = ('value',)
def __init__(self, value):
@@ -196,6 +223,11 @@
def getint(self):
return self.value
+ def serialize(self):
+ if isinstance(self.value, Symbolic):
+ raise Unserializable
+ return super(ConstInt, self).serialize()
+
def getaddr(self, cpu):
return cpu.cast_int_to_adr(self.value)
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sat Apr 25 02:55:49 2009
@@ -119,57 +119,17 @@
# ____________________________________________________________
-class MIFrame(object):
+class MIFrame(codewriter.JitCodeDecoder):
def __init__(self, metainterp, jitcode):
assert isinstance(jitcode, codewriter.JitCode)
self.metainterp = metainterp
self.jitcode = jitcode
- self.bytecode = jitcode.code
- self.constants = jitcode.constants
+ codewriter.JitCodeDecoder.__init__(self, jitcode.code)
+ self.constants = jitcode.ensure_constants(self.metainterp.cpu)
self.exception_target = -1
self.name = jitcode.name # purely for having name attribute
- # ------------------------------
- # Decoding of the JitCode
-
- def load_int(self):
- pc = self.pc
- result = ord(self.bytecode[pc])
- self.pc = pc + 1
- if result > 0x7F:
- result = self._load_larger_int(result)
- return result
-
- def _load_larger_int(self, result): # slow path
- result = result & 0x7F
- shift = 7
- pc = self.pc
- while 1:
- byte = ord(self.bytecode[pc])
- pc += 1
- result += (byte & 0x7F) << shift
- shift += 7
- if not byte & 0x80:
- break
- self.pc = pc
- return intmask(result)
- _load_larger_int._dont_inline_ = True
-
- def load_3byte(self):
- pc = self.pc
- result = (((ord(self.bytecode[pc + 0])) << 16) |
- ((ord(self.bytecode[pc + 1])) << 8) |
- ((ord(self.bytecode[pc + 2])) << 0))
- self.pc = pc + 3
- return result
-
- def load_bool(self):
- pc = self.pc
- result = ord(self.bytecode[pc])
- self.pc = pc + 1
- return bool(result)
-
def getenv(self, i):
assert i >= 0
j = i >> 1
More information about the Pypy-commit
mailing list