[pypy-svn] r74287 - in pypy/branch/blackhole-improvement/pypy/jit: codewriter codewriter/test metainterp
arigo at codespeak.net
arigo at codespeak.net
Fri Apr 30 16:47:04 CEST 2010
Author: arigo
Date: Fri Apr 30 16:47:02 2010
New Revision: 74287
Modified:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.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
pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py
Log:
Stop abusing the last character of the bytecode, and instead
store all three num_regs_X as a single separate integer.
Use it to implement replace_box() efficiently.
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 Fri Apr 30 16:47:02 2010
@@ -3,6 +3,7 @@
from pypy.jit.codewriter.flatten import ListOfKind, SwitchDictDescr
from pypy.objspace.flow.model import Constant
from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rlib.objectmodel import we_are_translated
class JitCode(AbstractValue):
@@ -11,31 +12,34 @@
_empty_f = []
def __init__(self, name, cfnptr=None, calldescr=None, called_from=None,
- liveness=None):
+ liveness=None, assembler=None):
self.name = name
#self.cfnptr = cfnptr
#self.calldescr = calldescr
#self.called_from = called_from
self.liveness = liveness
+ self._assembler = assembler
def setup(self, code, constants_i=[], constants_r=[], constants_f=[],
- num_regs_r=256):
- # stick an extra char at the end of self.code, which is the
- # highest 'r' register used in this code. It default to 255,
- # which is always correct. Also, even if no 'r' register is
- # used it must be set to 0, which means that register %r0 is
- # always marked as used.
- self.code = code + chr((num_regs_r or 1)-1)
+ num_regs_i=256, num_regs_r=256, num_regs_f=256):
+ self.code = code
# if the following lists are empty, use a single shared empty list
self.constants_i = constants_i or self._empty_i
self.constants_r = constants_r or self._empty_r
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))
- def _code(self):
- return self.code[:-1] # for testing, without the extra char
+ def num_regs_i(self):
+ return self.num_regs_encoded >> 18
- def highest_r_reg(self):
- return ord(self.code[-1])
+ def num_regs_r(self):
+ return (self.num_regs_encoded >> 9) & 0x1FF
+
+ def num_regs_f(self):
+ return self.num_regs_encoded & 0x1FF
def enumerate_live_vars(self, pc, callback, arg,
registers_i, registers_r, registers_f):
@@ -45,11 +49,23 @@
# of that instruction which are no longer used afterwards, and
# also the return value of that instruction.) More precisely,
# this invokes 'callback(arg, box)' where 'box' comes from one
- # of the three lists of registers.
+ # of the three lists of registers. If the callback returns a
+ # box, then it is stored back.
+ if not we_are_translated() and pc not in self.liveness:
+ self._missing_liveness(pc)
live_i, live_r, live_f = self.liveness[pc] # XXX compactify!!
- for c in live_i: callback(arg, registers_i[ord(c)])
- for c in live_r: callback(arg, registers_r[ord(c)])
- for c in live_f: callback(arg, registers_f[ord(c)])
+ for c in live_i:
+ newbox = callback(arg, registers_i[ord(c)])
+ if newbox is not None:
+ registers_i[ord(c)] = newbox
+ for c in live_r:
+ newbox = callback(arg, registers_r[ord(c)])
+ if newbox is not None:
+ registers_r[ord(c)] = newbox
+ for c in live_f:
+ newbox = callback(arg, registers_f[ord(c)])
+ if newbox is not None:
+ registers_f[ord(c)] = newbox
enumerate_live_vars._annspecialcase_ = 'specialize:arg(2)'
def _live_vars(self, pc):
@@ -67,6 +83,16 @@
lst.sort()
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))
+
class Assembler(object):
@@ -223,10 +249,13 @@
assert self.count_regs['float'] + len(self.constants_f) <= 256
def make_jitcode(self, name):
- jitcode = JitCode(name, liveness=self.liveness)
+ jitcode = JitCode(name, liveness=self.liveness,
+ assembler=self)
jitcode.setup(''.join(self.code),
self.constants_i,
self.constants_r,
self.constants_f,
- self.count_regs['ref'])
+ self.count_regs['int'],
+ self.count_regs['ref'],
+ self.count_regs['float'])
return jitcode
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py Fri Apr 30 16:47:02 2010
@@ -12,6 +12,7 @@
# 'switches_require_liveness' to True.
DEFAULT_OPNAMES_REQUIRING_LIVENESS = [
'residual_call_',
+ '(int|ref|float)_guard_value',
]
# ____________________________________________________________
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 Fri Apr 30 16:47:02 2010
@@ -17,10 +17,12 @@
assembler = Assembler()
jitcode = assembler.assemble(ssarepr)
assert jitcode.code == ("\x00\x00\x01\x02"
- "\x01\x02"
- "\x00")
+ "\x01\x02")
assert assembler.insns == {'int_add/iii': 0,
'int_return/i': 1}
+ assert jitcode.num_regs_i() == 3
+ assert jitcode.num_regs_r() == 0
+ assert jitcode.num_regs_f() == 0
def test_assemble_consts():
ssarepr = SSARepr("test")
@@ -37,8 +39,7 @@
"\x01\x12" # use int_return/c for one-byte consts
"\x01\xFC"
"\x00\xFF" # use int_return/i for larger consts
- "\x00\xFE"
- "\x00") # highest_r_reg
+ "\x00\xFE")
assert assembler.insns == {'int_return/i': 0,
'int_return/c': 1}
assert jitcode.constants_i == [128, -129]
@@ -56,8 +57,7 @@
assert jitcode.code == ("\x00\x0D"
"\x00\xFF"
"\x00\xFE"
- "\x00\xFD"
- "\x00")
+ "\x00\xFD")
assert assembler.insns == {'float_return/f': 0}
assert jitcode.constants_f == [18.0, -4.0, 128.1]
@@ -78,8 +78,7 @@
assert jitcode.code == ("\x00\x58"
"\x01\xFF"
"\x01\xFE"
- "\x02\xFF"
- "\x00")
+ "\x02\xFF")
assert assembler.insns == {'int_return/c': 0,
'int_return/i': 1,
'ref_return/r': 2}
@@ -106,8 +105,7 @@
"\x01\x17\x16\x17"
"\x02\x16\x01\x16"
"\x03\x00\x00"
- "\x04\x17"
- "\x00")
+ "\x04\x17")
assert assembler.insns == {'goto_if_not_int_gt/Lic': 0,
'int_add/iii': 1,
'int_sub/ici': 2,
@@ -123,7 +121,7 @@
]
assembler = Assembler()
jitcode = assembler.assemble(ssarepr)
- assert jitcode._code() == "\x00\x03\x16\x17\xFF\x00"
+ assert jitcode.code == "\x00\x03\x16\x17\xFF\x00"
assert assembler.insns == {'foobar/IR': 0}
assert jitcode.constants_i == [42]
@@ -135,21 +133,27 @@
ssarepr.insns = [('foobar', d) for d in descrs[::-1]]
assembler = Assembler()
jitcode = assembler.assemble(ssarepr)
- assert jitcode._code() == ''.join(["\x00" + struct.pack("<H", i)
+ assert jitcode.code == ''.join(["\x00" + struct.pack("<H", i)
for i in range(300)])
assert assembler.insns == {'foobar/d': 0}
assert assembler.descrs == descrs[::-1]
-def test_highest_r_reg():
+def test_num_regs():
assembler = Assembler()
ssarepr = SSARepr("test")
ssarepr.insns = []
jitcode = assembler.assemble(ssarepr)
- assert jitcode.highest_r_reg() == 0
- ssarepr = SSARepr("test")
- ssarepr.insns = [('foobar', Register('int', 51), Register('ref', 27))]
- jitcode = assembler.assemble(ssarepr)
- assert jitcode.highest_r_reg() == 27
+ assert jitcode.num_regs_i() == 0
+ assert jitcode.num_regs_r() == 0
+ assert jitcode.num_regs_f() == 0
+ ssarepr = SSARepr("test")
+ ssarepr.insns = [('foobar', Register('int', 51),
+ Register('ref', 27),
+ Register('int', 12))]
+ jitcode = assembler.assemble(ssarepr)
+ assert jitcode.num_regs_i() == 52
+ assert jitcode.num_regs_r() == 28
+ assert jitcode.num_regs_f() == 0
def test_liveness():
ssarepr = SSARepr("test")
@@ -170,7 +174,7 @@
]
assembler = Assembler()
jitcode = assembler.assemble(ssarepr)
- assert jitcode._code() == ("\x00\x00\x0A\x01"
+ assert jitcode.code == ("\x00\x00\x0A\x01"
"\x00\x00\x03\x02"
"\x01\x01\x02\x03"
"\x00\x00\x06\x04"
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 Fri Apr 30 16:47:02 2010
@@ -10,18 +10,21 @@
return b
cw = CodeWriter()
jitcode = cw.transform_func_to_jitcode(f, [5, 6])
- assert jitcode._code() == ("\x00\x10\x00\x00\x00"
- "\x01\x01\x00\x01"
- "\x02\x00\x01\x00"
- "\x03\x00\x00"
- "\x04\x01")
+ assert jitcode.code == ("\x00\x10\x00\x00\x00"
+ "\x01\x01\x00\x01"
+ "\x02\x00\x01\x00"
+ "\x03\x00\x00"
+ "\x04\x01")
assert cw.assembler.insns == {'goto_if_not_int_gt/Lic': 0,
'int_add/iii': 1,
'int_sub/ici': 2,
'goto/L': 3,
'int_return/i': 4}
+ 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())):
+ for i in range(1, len(jitcode.code)):
py.test.raises(KeyError, jitcode._live_vars, i)
def test_integration():
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 Fri Apr 30 16:47:02 2010
@@ -217,7 +217,7 @@
self.dispatch_loop = builder.dispatch_loop
self.descrs = builder.descrs
self.op_catch_exception = builder.op_catch_exception
- self.cleanup_required_in_registers_r = -1
+ self.cleanup_required_in_registers_r = 0
#
if we_are_translated():
default_i = 0
@@ -247,7 +247,7 @@
code = jitcode.code
self.cleanup_required_in_registers_r = max(
self.cleanup_required_in_registers_r,
- ord(code[-1]))
+ jitcode.num_regs_r())
while True:
try:
self.dispatch_loop(self, code, position)
@@ -286,11 +286,9 @@
# To avoid keeping references alive, this cleans up the registers_r.
# It does not clear the references set by copy_constants(), but
# these are all prebuilt constants anyway.
- i = self.cleanup_required_in_registers_r
- self.cleanup_required_in_registers_r = -1
- while i >= 0:
+ for i in range(self.cleanup_required_in_registers_r):
self.registers_r[i] = NULL
- i -= 1
+ self.cleanup_required_in_registers_r = 0
self.tmpreg_r = NULL
self.exception_last_value = None
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 Fri Apr 30 16:47:02 2010
@@ -93,77 +93,36 @@
outvalue[startindex+i] = reg
prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)'
- 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
- if i & 1:
- return self.constants[j]
- else:
- assert j < len(self.env)
- return self.env[j]
-
- def load_arg(self):
- return self.getenv(self.load_int())
-
- def load_const_arg(self):
- return self.constants[self.load_int()]
-
- def load_varargs(self):
- count = self.load_int()
- return [self.load_arg() for i in range(count)]
-
- def load_constargs(self):
- count = self.load_int()
- return [self.load_const_arg() for i in range(count)]
-
- def ignore_varargs(self):
- count = self.load_int()
+ def get_list_of_active_boxes(self):
+ # XXX find a way to avoid needing the temporary 'env' as a
+ # variable-sized list
+ env = []
+ self.jitcode.enumerate_live_vars(
+ self.pc, MIFrame._store_in_env, env,
+ self.registers_i, self.registers_r, self.registers_f)
+ return env[:]
+
+ @staticmethod
+ def _store_in_env(env, box):
+ env.append(box)
+
+ def replace_active_box_in_frame(self, oldbox, newbox):
+ if isinstance(oldbox, history.BoxInt):
+ count = self.jitcode.num_regs_i()
+ registers = self.registers_i
+ elif isinstance(oldbox, history.BoxPtr):
+ count = self.jitcode.num_regs_r()
+ registers = self.registers_r
+ elif isinstance(oldbox, history.BoxFloat):
+ count = self.jitcode.num_regs_f()
+ registers = self.registers_f
+ else:
+ assert 0, repr(oldbox)
for i in range(count):
- self.load_int()
-
- def getvarenv(self, i):
- return self.env[i]
-
- def make_result_box(self, box):
- assert isinstance(box, Box) or isinstance(box, Const)
- self.env.append(box)
+ if registers[i] is oldbox:
+ registers[i] = newbox
+ if not we_are_translated():
+ assert oldbox not in registers[count:]
# ------------------------------
@@ -1999,11 +1958,9 @@
return boxes
def replace_box(self, oldbox, newbox):
+ assert isinstance(oldbox, Box)
for frame in self.framestack:
- boxes = frame.env
- for i in range(len(boxes)):
- if boxes[i] is oldbox:
- boxes[i] = newbox
+ frame.replace_active_box_in_frame(oldbox, newbox)
boxes = self.virtualref_boxes
for i in range(len(boxes)):
if boxes[i] is oldbox:
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py Fri Apr 30 16:47:02 2010
@@ -21,13 +21,12 @@
self.boxes = boxes
class FrameInfo(object):
- __slots__ = ('prev', 'jitcode', 'pc', 'exception_target')
+ __slots__ = ('prev', 'jitcode', 'pc')
def __init__(self, prev, frame):
self.prev = prev
self.jitcode = frame.jitcode
self.pc = frame.pc
- self.exception_target = frame.exception_target
def _ensure_parent_resumedata(framestack, n):
target = framestack[n]
@@ -40,7 +39,7 @@
back)
target.parent_resumedata_snapshot = Snapshot(
back.parent_resumedata_snapshot,
- back.env[:])
+ back.get_list_of_active_boxes())
def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes,
storage):
@@ -50,7 +49,8 @@
frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list,
top)
storage.rd_frame_info_list = frame_info_list
- snapshot = Snapshot(top.parent_resumedata_snapshot, top.env[:])
+ snapshot = Snapshot(top.parent_resumedata_snapshot,
+ top.get_list_of_active_boxes())
snapshot = Snapshot(snapshot, virtualref_boxes[:]) # xxx for now
if virtualizable_boxes is not None:
snapshot = Snapshot(snapshot, virtualizable_boxes[:]) # xxx for now
@@ -576,7 +576,7 @@
except AttributeError:
jitcodename = str(compute_unique_id(frameinfo.jitcode))
debug_print('\tjitcode/pc', jitcodename,
- frameinfo.pc, frameinfo.exception_target,
+ frameinfo.pc,
'at', compute_unique_id(frameinfo))
frameinfo = frameinfo.prev
numb = storage.rd_numb
More information about the Pypy-commit
mailing list