[pypy-svn] r63518 - pypy/branch/optimize-refactoring/pypy/jit/backend/x86
fijal at codespeak.net
fijal at codespeak.net
Thu Apr 2 07:20:38 CEST 2009
Author: fijal
Date: Thu Apr 2 07:20:36 2009
New Revision: 63518
Modified:
pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py
pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py
pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py
Log:
first round of fixing up the x86 backend. goes slowly though....
Modified: pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py Thu Apr 2 07:20:36 2009
@@ -39,20 +39,40 @@
#raise NotImplementedError
return "?%r" % (arg,)
-class Assembler386(object):
+class MachineCodeStack(object):
MC_SIZE = 1024*1024 # 1MB, but assumed infinite for now
+
+ def __init__(self):
+ self.mcstack = []
+ self.counter = 0
+
+ def next_mc(self):
+ if len(self.mcstack) == self.counter:
+ mc = codebuf.MachineCodeBlock(self.MC_SIZE)
+ self.mcstack.append(mc)
+ else:
+ mc = self.mcstack[self.counter]
+ self.counter += 1
+ return mc
+
+ def give_mc_back(self, mc):
+ assert self.mcstack[self.counter - 1] is mc
+ self.counter -= 1
+
+class Assembler386(object):
generic_return_addr = 0
log_fd = -1
+ mc = None
+ mc2 = None
def __init__(self, cpu, translate_support_code=False):
self.cpu = cpu
self.verbose = False
- self.mc = None
- self.mc2 = None
self.rtyper = cpu.rtyper
self.malloc_func_addr = 0
self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed))
self._exception_addr = 0
+ self.mcstack = MachineCodeStack()
def _get_log(self):
s = os.environ.get('PYPYJITLOG')
@@ -86,17 +106,18 @@
zero=True, flavor='raw')
self._exception_bck_addr = self.cpu.cast_ptr_to_int(
self._exception_bck)
- self.mc = codebuf.MachineCodeBlock(self.MC_SIZE)
- self.mc2 = codebuf.MachineCodeBlock(self.MC_SIZE)
+ self.mc = self.mcstack.next_mc()
+ self.mc2 = self.mcstack.next_mc()
self.generic_return_addr = self.assemble_generic_return()
# the address of the function called by 'new': directly use
# Boehm's GC_malloc function.
if self.malloc_func_addr == 0:
self.malloc_func_addr = gc_malloc_fnaddr()
- def eventually_log_operations(self, operations, guard_op):
+ def eventually_log_operations(self, operations):
if self._log_fd == -1:
return
+ xxx
memo = {}
os.write(self._log_fd, "<<<<<<<<<<\n")
if guard_op is not None:
@@ -116,6 +137,7 @@
def log_failure_recovery(self, gf, guard_index):
if self._log_fd == -1:
return
+ xxx
os.write(self._log_fd, 'xxxxxxxxxx\n')
memo = {}
reprs = []
@@ -130,30 +152,24 @@
def log_call(self, name, valueboxes):
if self._log_fd == -1:
return
+ xxx
memo = {}
args_s = ','.join([repr_of_arg(memo, box) for box in valueboxes])
os.write(self._log_fd, "CALL\n")
os.write(self._log_fd, "%s %s\n" % (name, args_s))
- def assemble(self, operations, guard_op, verbose=False):
- self.verbose = verbose
+ def assemble(self, tree):
# the last operation can be 'jump', 'return' or 'guard_pause';
# a 'jump' can either close a loop, or end a bridge to some
# previously-compiled code.
self.make_sure_mc_exists()
- op0 = operations[0]
+ inputargs = tree.inputargs
+ op0 = tree.operations[0]
op0.position = self.mc.tell()
- self.eventually_log_operations(operations, guard_op)
- regalloc = RegAlloc(self, operations, guard_op,
- self.cpu.translate_support_code)
+ self.eventually_log_operations(tree)
+ regalloc = RegAlloc(self, tree, self.cpu.translate_support_code)
if not we_are_translated():
self._regalloc = regalloc # for debugging
- if guard_op is not None:
- new_rel_addr = self.mc.tell() - guard_op._jmp_from
- TP = rffi.CArrayPtr(lltype.Signed)
- ptr = rffi.cast(TP, guard_op._jmp_from - WORD)
- ptr[0] = new_rel_addr
- self.mc.redone(guard_op._jmp_from - WORD, guard_op._jmp_from)
if self.verbose and not we_are_translated():
import pprint
print
@@ -161,7 +177,7 @@
print
#pprint.pprint(computed_ops)
#print
- regalloc.walk_operations(operations)
+ regalloc.walk_operations(tree)
self.mc.done()
self.mc2.done()
@@ -193,17 +209,17 @@
finally:
Box._extended_display = _prev
- def assemble_comeback_bootstrap(self, mp):
+ def assemble_comeback_bootstrap(self, position, arglocs, stacklocs):
entry_point_addr = self.mc2.tell()
- for i in range(len(mp.arglocs)):
- argloc = mp.arglocs[i]
+ for i in range(len(arglocs)):
+ argloc = arglocs[i]
if isinstance(argloc, REG):
- self.mc2.MOV(argloc, stack_pos(mp.stacklocs[i]))
+ self.mc2.MOV(argloc, stack_pos(stacklocs[i]))
elif not we_are_translated():
# debug checks
if not isinstance(argloc, (IMM8, IMM32)):
- assert repr(argloc) == repr(stack_pos(mp.stacklocs[i]))
- self.mc2.JMP(rel32(mp.position))
+ assert repr(argloc) == repr(stack_pos(stacklocs[i]))
+ self.mc2.JMP(rel32(position))
self.mc2.done()
return entry_point_addr
@@ -228,7 +244,10 @@
def regalloc_perform_discard(self, op, arglocs):
genop_discard_list[op.opnum](self, op, arglocs)
- def regalloc_perform_with_guard(self, op, guard_op, arglocs, resloc):
+ def regalloc_perform_with_guard(self, op, guard_op, regalloc,
+ arglocs, resloc):
+ addr = self.implement_guard_recovery(guard_op, regalloc, arglocs)
+ xxx
genop_guard_list[op.opnum](self, op, guard_op, arglocs, resloc)
def _unaryop(asmop):
@@ -501,11 +520,11 @@
self.cpu.translate_support_code)
self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize))
- def genop_discard_merge_point(self, op, locs):
- op.position = self.mc.tell()
- op.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(op)
-
- genop_discard_catch = genop_discard_merge_point
+ def make_merge_point(self, tree, locs, stacklocs):
+ pos = self.mc.tell()
+ tree.position = pos
+ tree.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(pos,
+ locs, stacklocs)
def genop_discard_return(self, op, locs):
if op.args:
@@ -574,8 +593,19 @@
# self.mc.CMP(mem(eax, offset), imm(0))
# self.implement_guard(op, self.mc.JNE)
+ def implement_guard_recovery(self, guard_op, locs, regalloc):
+ oldmc = self.mc
+ self.mc = self.mc2
+ self.mc2 = self.mcstack.next_mc()
+ regalloc._walk_operations(guard_op.suboperations)
+ xxx
+ self.mcstack.give_mc_back(self.mc2)
+ self.mc2 = self.mc
+ self.mc = oldmc
+
@specialize.arg(2)
def implement_guard(self, guard_op, emit_jump, locs):
+ xxx
# XXX add caching, as we need only one for each combination
# of locs
recovery_addr = self.get_recovery_code(guard_op, locs)
@@ -583,6 +613,7 @@
guard_op._jmp_from = self.mc.tell()
def get_recovery_code(self, guard_op, locs):
+ xxx
index = self.cpu.make_guard_index(guard_op)
recovery_code_addr = self.mc2.tell()
stacklocs = guard_op.stacklocs
Modified: pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py Thu Apr 2 07:20:36 2009
@@ -47,27 +47,38 @@
raise ValueError("convert_to_imm: got a %s" % c)
class RegAlloc(object):
- def __init__(self, assembler, operations, guard_op=None,
- translate_support_code=False):
+ def __init__(self, assembler, tree, translate_support_code=False,
+ regalloc=None):
# variables that have place in register
self.assembler = assembler
self.translate_support_code = translate_support_code
- self.reg_bindings = newcheckdict()
- self.stack_bindings = {}
- # compute longevity of variables
- self._compute_vars_longevity(operations)
- self.free_regs = REGS[:]
- self.dirty_stack = {}
- mp = operations[0]
- self.first_merge_point = mp
- jump = operations[-1]
- self.startmp = mp
- if guard_op:
- loop_consts, sd = self._start_from_guard_op(guard_op, mp, jump)
+ if regalloc is None:
+ self.reg_bindings = newcheckdict()
+ self.stack_bindings = {}
+ # compute longevity of variables
+ self._compute_vars_longevity(tree)
+ self.free_regs = REGS[:]
+ self.dirty_stack = {}
+ jump = tree.operations[-1]
+ #self.startmp = mp
+ #if guard_op:
+ # loop_consts, sd = self._start_from_guard_op(guard_op, mp, jump)
+ #else:
+ loop_consts, sd = self._compute_loop_consts(tree.inputargs, jump)
+ self.loop_consts = loop_consts
+ self.current_stack_depth = sd
else:
- loop_consts, sd = self._compute_loop_consts(mp, jump)
- self.loop_consts = loop_consts
- self.current_stack_depth = sd
+ self.reg_bindings = regalloc.reg_bindings.copy()
+ self.stack_bindings = regalloc.stack_bindings.copy()
+ self.free_regs = regalloc.free_regs[:]
+ self.dirty_stack = regalloc.dirty_stack.copy()
+ self.loop_consts = regalloc.loop_consts # should never change
+ self.current_stack_depth = regalloc.current_stack_depth
+ self.jump_reg_candidates = regalloc.jump_reg_candidates
+
+ def copy(self):
+ return RegAlloc(self.assembler, None, self.translate_support_code,
+ self)
def _start_from_guard_op(self, guard_op, mp, jump):
rev_stack_binds = {}
@@ -112,19 +123,18 @@
j += 1
return {}, sd
- def _compute_loop_consts(self, mp, jump):
+ def _compute_loop_consts(self, inputargs, jump):
self.jump_reg_candidates = {}
if jump.opnum != rop.JUMP:
loop_consts = {}
else:
- assert jump.jump_target is mp
free_regs = REGS[:]
loop_consts = {}
- for i in range(len(mp.args)):
- if mp.args[i] is jump.args[i]:
- loop_consts[mp.args[i]] = i
- for i in range(len(mp.args)):
- arg = mp.args[i]
+ for i in range(len(inputargs)):
+ if inputargs[i] is jump.args[i]:
+ loop_consts[inputargs[i]] = i
+ for i in range(len(inputargs)):
+ arg = inputargs[i]
jarg = jump.args[i]
if arg is not jarg and not isinstance(jarg, Const):
if free_regs:
@@ -136,7 +146,7 @@
else:
# these are loop consts, but we need stack space anyway
self.stack_bindings[jarg] = stack_pos(i)
- return loop_consts, len(mp.args)
+ return loop_consts, len(inputargs)
def _check_invariants(self):
if not we_are_translated():
@@ -170,12 +180,12 @@
self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
self.assembler.regalloc_perform(op, arglocs, result_loc)
- def PerformWithGuard(self, op, guard_op, arglocs, result_loc):
+ def perform_with_guard(self, op, guard_op, regalloc, arglocs, result_loc):
if not we_are_translated():
self.assembler.dump('%s <- %s(%s) [GUARDED]' % (result_loc, op,
arglocs))
self.assembler.regalloc_perform_with_guard(op, guard_op, arglocs,
- result_loc)
+ regalloc, result_loc)
def PerformDiscard(self, op, arglocs):
if not we_are_translated():
@@ -194,9 +204,15 @@
return False
return True
- def walk_operations(self, operations):
+ def walk_operations(self, tree):
# first pass - walk along the operations in order to find
# load/store places
+ operations = tree.operations
+ self.position = 0
+ self.process_inputargs(tree)
+ self._walk_operations(operations)
+
+ def _walk_operations(self, operations):
i = 0
while i < len(operations):
op = operations[i]
@@ -224,13 +240,14 @@
i += 1
assert not self.reg_bindings
- def _compute_vars_longevity(self, operations):
+ def _compute_vars_longevity(self, tree):
# compute a dictionary that maps variables to index in
# operations that is a "last-time-seen"
longevity = {}
start_live = {}
- for v in operations[0].args:
- start_live[v] = 0
+ for inputarg in tree.inputargs:
+ start_live[inputarg] = 0
+ operations = tree.operations
for i in range(len(operations)):
op = operations[i]
if op.result is not None:
@@ -239,7 +256,7 @@
if isinstance(arg, Box):
longevity[arg] = (start_live[arg], i)
if op.is_guard():
- for arg in op.liveboxes:
+ for arg in op.suboperations[-1].args:
assert isinstance(arg, Box)
longevity[arg] = (start_live[arg], i)
self.longevity = longevity
@@ -453,13 +470,13 @@
loc = self.reg_bindings[result_v]
return loc
- def consider_merge_point(self, op, ignored):
+ def process_inputargs(self, tree):
# XXX we can sort out here by longevity if we need something
# more optimal
-
- locs = [None] * len(op.args)
- for i in range(len(op.args)):
- arg = op.args[i]
+ inputargs = tree.inputargs
+ locs = [None] * len(inputargs)
+ for i in range(len(inputargs)):
+ arg = inputargs[i]
assert not isinstance(arg, Const)
reg = None
loc = stack_pos(i)
@@ -474,35 +491,26 @@
else:
locs[i] = loc
# otherwise we have it saved on stack, so no worry
- op.arglocs = locs
- op.stacklocs = range(len(op.args))
- self.PerformDiscard(op, locs)
+ tree.arglocs = locs
+ tree.stacklocs = range(len(inputargs))
+ self.assembler.make_merge_point(tree, locs, tree.stacklocs)
# XXX be a bit smarter and completely ignore such vars
- self.eventually_free_vars(op.args)
-
- def consider_catch(self, op, ignored):
- locs = []
- for arg in op.args:
- l = self.loc(arg)
- if isinstance(l, REG):
- self.dirty_stack[arg] = True
- locs.append(l)
- # possibly constants
- op.arglocs = locs
- op.stacklocs = [self.stack_loc(arg).position for arg in op.args]
- self.eventually_free_vars(op.args)
- self.PerformDiscard(op, [])
+ self.eventually_free_vars(inputargs)
def _consider_guard(self, op, ignored):
loc = self.make_sure_var_in_reg(op.args[0], [])
locs = self._locs_from_liveboxes(op)
self.eventually_free_var(op.args[0])
self.eventually_free_vars(op.liveboxes)
+ xxx
self.PerformDiscard(op, [loc] + locs)
consider_guard_true = _consider_guard
consider_guard_false = _consider_guard
+ def consider_fail(self, op, ignored):
+ xxx
+
def consider_guard_nonvirtualized(self, op, ignored):
# XXX implement it
locs = self._locs_from_liveboxes(op)
@@ -682,7 +690,9 @@
self.position += 1
self.eventually_free_var(op.result)
self.eventually_free_vars(guard_op.liveboxes)
- self.PerformWithGuard(op, guard_op, arglocs + locs, None)
+ regalloc = self.copy()
+ self.perform_with_guard(op, guard_op, regalloc, arglocs + locs,
+ None)
consider_int_lt = _consider_compop
consider_int_gt = _consider_compop
@@ -895,11 +905,10 @@
middle_busy_regs = []
for i in range(len(op.args)):
arg = op.args[i]
- mp = op.jump_target
- res = mp.arglocs[i]
+ loop = op.jump_target
+ res = loop.inputargs[i]
if not (isinstance(arg, Const) or (arg in self.loop_consts
and self.loop_consts[arg] == i)):
- assert mp.opnum == rop.MERGE_POINT
if arg in self.reg_bindings:
if not isinstance(res, REG):
self.Store(arg, self.loc(arg),
Modified: pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py (original)
+++ pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py Thu Apr 2 07:20:36 2009
@@ -180,84 +180,8 @@
self.assembler._exception_bck[0] = ovf_vtable
self.assembler._exception_bck[1] = ovf_inst
-# def execute_operation(self, opnum, valueboxes, result_type):
-# xxx
-# if execute[opnum] is not None:
-# return execute[opnum](valueboxes)
-
-# # mostly a hack: fall back to compiling and executing the single
-# # operation.
-# key = []
-# for valuebox in valueboxes:
-# if isinstance(valuebox, Box):
-# key.append(valuebox.type)
-# else:
-# key.append(str(valuebox.get_()))
-# mp = self.get_compiled_single_operation(opnum, result_type,
-# key, valueboxes)
-# res = self.execute_operations_in_new_frame(opname[opnum], mp,
-# valueboxes,
-# result_type)
-# if not self.translate_support_code:
-# if self.assembler._exception_data[0] != 0:
-# TP = lltype.Ptr(rclass.OBJECT_VTABLE)
-# TP_V = lltype.Ptr(rclass.OBJECT)
-# exc_t_a = self.cast_int_to_adr(self.get_exception(None))
-# exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP)
-# exc_v_a = self.get_exc_value(None)
-# exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a)
-# # clean up the exception
-# self.assembler._exception_data[0] = 0
-# raise LLException(exc_type, exc_val)
-# # otherwise exception data is set correctly, no problem at all
-# return res
-
-# def get_compiled_single_operation(self, opnum, result_type, key,
-# valueboxes):
-# xxx
-# real_key = '%d,%s' % (opnum, result_type) + ','.join(key)
-# try:
-# return self._compiled_ops[real_key]
-# except KeyError:
-# livevarlist = []
-# i = 0
-# # clonebox below is necessary, because sometimes we know
-# # that the value is constant (ie ArrayDescr), but we're not
-# # going to get the contant. So instead we get a box with correct
-# # value
-# for box in valueboxes:
-# if box.type == 'int':
-# box = valueboxes[i].clonebox()
-# elif box.type == 'ptr':
-# box = valueboxes[i].clonebox()
-# else:
-# raise ValueError(type)
-# livevarlist.append(box)
-# i += 1
-# mp = ResOperation(rop.MERGE_POINT, livevarlist, None)
-# if result_type == 'void':
-# result = None
-# elif result_type == 'int':
-# result = history.BoxInt()
-# elif result_type == 'ptr':
-# result = history.BoxPtr()
-# else:
-# raise ValueError(result_type)
-# if result is None:
-# results = []
-# else:
-# results = [result]
-# operations = [mp,
-# ResOperation(opnum, livevarlist, result),
-# ResOperation(rop.RETURN, results, None)]
-# if operations[1].is_guard():
-# operations[1].liveboxes = []
-# self.compile_operations(operations, verbose=False)
-# self._compiled_ops[real_key] = mp
-# return mp
-
- def compile_operations(self, operations, guard_op=None, verbose=True):
- self.assembler.assemble(operations, guard_op, verbose=verbose)
+ def compile_operations(self, tree):
+ self.assembler.assemble(tree)
def get_bootstrap_code(self, startmp):
# key is locations of arguments
@@ -312,7 +236,9 @@
self.generated_mps[calldescr] = operations
return operations
- def execute_operations_in_new_frame(self, name, operations, valueboxes):
+ def execute_operations(self, loop, valueboxes):
+ import pdb
+ pdb.set_trace()
startmp = operations[0]
func = self.get_bootstrap_code(startmp)
# turn all the values into integers
@@ -568,6 +494,7 @@
def do_call(self, args, calldescr):
num_args, size, ptr = self.unpack_calldescr(calldescr)
+ xxx
mp = self._get_mp_for_call(num_args, calldescr)
if size == 0:
self.return_value_type = VOID
@@ -575,7 +502,7 @@
self.return_value_type = PTR
else:
self.return_value_type = INT
- result = self.execute_operations_in_new_frame('call', mp, args)
+ result = self.execute_operations(mp, args)
return result
# ------------------- helpers and descriptions --------------------
More information about the Pypy-commit
mailing list