Author: Armin Rigo <[email protected]>
Branch: remove-globals-in-jit
Changeset: r58924:3180d3717743
Date: 2012-11-15 12:00 +0100
http://bitbucket.org/pypy/pypy/changeset/3180d3717743/
Log: In-progress: kill kill kill failargs_xyz and related data on the
Assembler386 class.
diff --git a/pypy/jit/backend/llsupport/descr.py
b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -226,15 +226,21 @@
def repr_of_descr(self):
return '<InteriorFieldDescr %s>' % self.fielddescr.repr_of_descr()
-def get_interiorfield_descr(gc_ll_descr, ARRAY, name):
+def get_interiorfield_descr(gc_ll_descr, ARRAY, name, arrayfieldname=None):
+ # can be used either with a GcArray of Structs, or with a GcStruct
+ # containing an inlined GcArray of Structs (then arrayfieldname != None).
cache = gc_ll_descr._cache_interiorfield
try:
- return cache[(ARRAY, name)]
+ return cache[(ARRAY, name, arrayfieldname)]
except KeyError:
arraydescr = get_array_descr(gc_ll_descr, ARRAY)
- fielddescr = get_field_descr(gc_ll_descr, ARRAY.OF, name)
+ if arrayfieldname is None:
+ REALARRAY = ARRAY
+ else:
+ REALARRAY = getattr(ARRAY, arrayfieldname)
+ fielddescr = get_field_descr(gc_ll_descr, REALARRAY.OF, name)
descr = InteriorFieldDescr(arraydescr, fielddescr)
- cache[(ARRAY, name)] = descr
+ cache[(ARRAY, name, arrayfieldname)] = descr
return descr
# ____________________________________________________________
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -10,7 +10,7 @@
from pypy.jit.codewriter import heaptracker
from pypy.jit.metainterp.history import ConstPtr, AbstractDescr
from pypy.jit.metainterp.resoperation import ResOperation, rop
-from pypy.jit.backend.llsupport import symbolic
+from pypy.jit.backend.llsupport import symbolic, jitframe
from pypy.jit.backend.llsupport.symbolic import WORD
from pypy.jit.backend.llsupport.descr import SizeDescr, ArrayDescr
from pypy.jit.backend.llsupport.descr import GcCache, get_field_descr
@@ -110,6 +110,15 @@
self._record_constptrs(op, gcrefs_output_list)
return newops
+ @specialize.memo()
+ def getframedescrs(self, cpu):
+ return (
+ cpu.arraydescrof(jitframe.DEADFRAME),
+ cpu.interiorfielddescrof(jitframe.DEADFRAME, 'int', 'jf_values'),
+ cpu.interiorfielddescrof(jitframe.DEADFRAME, 'ref', 'jf_values'),
+ cpu.interiorfielddescrof(jitframe.DEADFRAME, 'float', 'jf_values'),
+ cpu.fielddescrof(jitframe.DEADFRAME, 'jf_descr'))
+
# ____________________________________________________________
class GcLLDescr_boehm(GcLLDescription):
diff --git a/pypy/jit/backend/llsupport/jitframe.py
b/pypy/jit/backend/llsupport/jitframe.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/llsupport/jitframe.py
@@ -0,0 +1,27 @@
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.jit.codewriter import longlong
+
+
+VALUEUNION = lltype.Struct('VALUEUNION',
+ ('int', lltype.Signed),
+ ('ref', llmemory.GCREF),
+ ('float', longlong.FLOATSTORAGE),
+ hints={'union': True})
+
+DEADFRAME = lltype.GcStruct(
+ 'DEADFRAME',
+
+ # Once the execute_token() returns, the field 'jf_descr' stores the
+ # descr of the last executed operation (either a GUARD, or FINISH).
+ # This field is also set immediately before doing CALL_MAY_FORCE
+ # or CALL_ASSEMBLER.
+ ('jf_descr', llmemory.GCREF),
+
+ # For the front-end: a GCREF for the savedata
+ ('jf_savedata', llmemory.GCREF),
+
+ # All values are stored in the following array, for now not very
+ # compactly on 32-bit machines.
+ ('jf_values', lltype.Array(VALUEUNION)))
+
+DEADFRAMEPTR = lltype.Ptr(DEADFRAME)
diff --git a/pypy/jit/backend/llsupport/llmodel.py
b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -45,7 +45,6 @@
self._setup_exception_handling_translated()
else:
self._setup_exception_handling_untranslated()
- self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
self.asmmemmgr = AsmMemoryManager()
self.setup()
if translate_support_code:
@@ -119,6 +118,7 @@
def _setup_exception_handling_translated(self):
+ xxxxxxxxxxx
def pos_exception():
addr = llop.get_exception_addr(llmemory.Address)
@@ -132,12 +132,12 @@
addr = llop.get_exception_addr(llmemory.Address)
addr.address[0] = llmemory.NULL
addr = llop.get_exc_value_addr(llmemory.Address)
- exc_value = rffi.cast(llmemory.GCREF, addr.address[0])
+ exc_value = addr.address[0]
addr.address[0] = llmemory.NULL
# from now on, the state is again consistent -- no more RPython
# exception is set. The following code produces a write barrier
# in the assignment to self.saved_exc_value, as needed.
- self.saved_exc_value = exc_value
+ self.saved_exc_value = rffi.cast(llmemory.GCREF, exc_value)
def save_exception_memoryerr():
from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -207,7 +207,8 @@
f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_noexc)
return rffi.cast(lltype.Signed, f)
- def grab_exc_value(self):
+ def grab_exc_value(self, deadframe):
+ xxx
exc = self.saved_exc_value
self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
return exc
@@ -263,8 +264,9 @@
def arraydescrof(self, A):
return get_array_descr(self.gc_ll_descr, A)
- def interiorfielddescrof(self, A, fieldname):
- return get_interiorfield_descr(self.gc_ll_descr, A, fieldname)
+ def interiorfielddescrof(self, A, fieldname, arrayfieldname=None):
+ return get_interiorfield_descr(self.gc_ll_descr, A, fieldname,
+ arrayfieldname)
def unpack_arraydescr(self, arraydescr):
assert isinstance(arraydescr, ArrayDescr)
diff --git a/pypy/jit/backend/llsupport/rewrite.py
b/pypy/jit/backend/llsupport/rewrite.py
--- a/pypy/jit/backend/llsupport/rewrite.py
+++ b/pypy/jit/backend/llsupport/rewrite.py
@@ -1,10 +1,12 @@
import sys
from pypy.rlib.rarithmetic import ovfcheck
+from pypy.jit.metainterp import history
from pypy.jit.metainterp.history import ConstInt, BoxPtr, ConstPtr
from pypy.jit.metainterp.resoperation import ResOperation, rop
from pypy.jit.codewriter import heaptracker
from pypy.jit.backend.llsupport.symbolic import WORD
from pypy.jit.backend.llsupport.descr import SizeDescr, ArrayDescr
+from pypy.jit.backend.llsupport import jitframe
class GcRewriterAssembler(object):
@@ -65,6 +67,10 @@
continue
# ----------
self.newops.append(op)
+ # ---------- FINISH ----------
+ if self.newops[-1].getopnum() == rop.FINISH:
+ self.handle_finish(self.newops.pop())
+ # ----------
return self.newops
# ----------
@@ -337,3 +343,41 @@
# assume that "self.gc_ll_descr.minimal_size_in_nursery" is 2 WORDs
size = max(size, 2 * WORD)
return (size + WORD-1) & ~(WORD-1) # round up
+
+ # ----------
+
+ def handle_finish(self, finish_op):
+ v_deadframe = BoxPtr()
+ args_boxes = finish_op.getarglist() # may contain Consts too
+ #
+ arraydescr, int_descr, ref_descr, float_descr, jf_descr = (
+ self.gc_ll_descr.getframedescrs(self.cpu))
+ #
+ op = ResOperation(rop.NEW_ARRAY,
+ [ConstInt(len(args_boxes))], v_deadframe,
+ descr=arraydescr)
+ self.handle_malloc_operation(op)
+ #
+ for i in range(len(args_boxes)):
+ # Generate setinteriorfields to write the args inside the
+ # deadframe object. Ignore write barriers because it's a
+ # recent object.
+ box = args_boxes[i]
+ if box.type == history.INT: descr = int_descr
+ elif box.type == history.REF: descr = ref_descr
+ elif box.type == history.FLOAT: descr = float_descr
+ else: assert 0, "bad box type?"
+ op = ResOperation(rop.SETINTERIORFIELD_GC,
+ [v_deadframe, ConstInt(i), box], None,
+ descr=descr)
+ self.newops.append(op)
+ #
+ # Generate a setfield to write the finish_op's descr.
+ gcref_descr = finish_op.getdescr().hide(self.cpu)
+ op = ResOperation(rop.SETFIELD_GC,
+ [v_deadframe, ConstPtr(gcref_descr)], None,
+ descr=jf_descr)
+ self.newops.append(op)
+ #
+ op = ResOperation(rop.FINISH, [v_deadframe], None)
+ self.newops.append(op)
diff --git a/pypy/jit/backend/x86/assembler.py
b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -30,7 +30,6 @@
from pypy.rlib.objectmodel import we_are_translated, specialize
from pypy.jit.backend.x86 import rx86, regloc, codebuf
from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.backend.x86.support import values_array
from pypy.jit.backend.x86 import support
from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
have_debug_prints)
@@ -68,16 +67,10 @@
_regalloc = None
_output_loop_log = None
- def __init__(self, cpu, translate_support_code=False,
- failargs_limit=1000):
+ def __init__(self, cpu, translate_support_code=False):
self.cpu = cpu
self.verbose = False
self.rtyper = cpu.rtyper
- self.fail_boxes_int = values_array(lltype.Signed, failargs_limit)
- self.fail_boxes_ptr = values_array(llmemory.GCREF, failargs_limit)
- self.fail_boxes_float = values_array(longlong.FLOATSTORAGE,
- failargs_limit)
- self.fail_ebp = 0
self.loop_run_counters = []
self.float_const_neg_addr = 0
self.float_const_abs_addr = 0
@@ -88,18 +81,12 @@
self.setup_failure_recovery()
self._debug = False
self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i')
- self.fail_boxes_count = 0
self.datablockwrapper = None
self.stack_check_slowpath = 0
self.propagate_exception_path = 0
self.gcrootmap_retaddr_forced = 0
self.teardown()
- def leave_jitted_hook(self):
- ptrs = self.fail_boxes_ptr.ar
- llop.gc_assume_young_pointers(lltype.Void,
- llmemory.cast_ptr_to_adr(ptrs))
-
def set_debug(self, v):
r = self._debug
self._debug = v
@@ -1915,8 +1902,6 @@
n = self.CODE_HOLE
mc.writechar(chr(n))
mc.writechar(chr(self.CODE_STOP))
- # assert that the fail_boxes lists are big enough
- assert len(failargs) <= self.fail_boxes_int.SIZE
def rebuild_faillocs_from_descr(self, bytecode):
from pypy.jit.backend.x86.regalloc import X86FrameManager
@@ -2118,47 +2103,10 @@
self.failure_recovery_code[exc + 2 * withfloats] = rawstart
self.mc = None
- def generate_failure(self, fail_index, locs, exc, locs_are_ref):
- self.mc.begin_reuse_scratch_register()
- for i in range(len(locs)):
- loc = locs[i]
- if isinstance(loc, RegLoc):
- if loc.is_xmm:
- adr = self.fail_boxes_float.get_addr_for_num(i)
- self.mc.MOVSD(heap(adr), loc)
- else:
- if locs_are_ref[i]:
- adr = self.fail_boxes_ptr.get_addr_for_num(i)
- else:
- adr = self.fail_boxes_int.get_addr_for_num(i)
- self.mc.MOV(heap(adr), loc)
- for i in range(len(locs)):
- loc = locs[i]
- if not isinstance(loc, RegLoc):
- if ((isinstance(loc, StackLoc) and loc.type == FLOAT) or
- isinstance(loc, ConstFloatLoc)):
- self.mc.MOVSD(xmm0, loc)
- adr = self.fail_boxes_float.get_addr_for_num(i)
- self.mc.MOVSD(heap(adr), xmm0)
- else:
- if locs_are_ref[i]:
- adr = self.fail_boxes_ptr.get_addr_for_num(i)
- else:
- adr = self.fail_boxes_int.get_addr_for_num(i)
- self.mc.MOV(eax, loc)
- self.mc.MOV(heap(adr), eax)
- self.mc.end_reuse_scratch_register()
-
- # we call a provided function that will
- # - call our on_leave_jitted_hook which will mark
- # the fail_boxes_ptr array as pointing to young objects to
- # avoid unwarranted freeing
- # - optionally save exception depending on the flag
- addr = self.cpu.get_on_leave_jitted_int(save_exception=exc)
- self.mc.CALL(imm(addr))
-
- self.mc.MOV_ri(eax.value, fail_index)
-
+ def genop_finish(self, op, arglocs, result_loc):
+ [argloc] = arglocs
+ if argloc is not eax:
+ self.mov(argloc, eax)
# exit function
self._call_footer()
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -486,15 +486,9 @@
consider_guard_isnull = _consider_guard
def consider_finish(self, op):
- locs = [self.loc(op.getarg(i)) for i in range(op.numargs())]
- locs_are_ref = [op.getarg(i).type == REF for i in range(op.numargs())]
- fail_index = self.assembler.cpu.get_fail_descr_number(op.getdescr())
- # note: no exception should currently be set in llop.get_exception_addr
- # even if this finish may be an exit_frame_with_exception (in this case
- # the exception instance is in locs[0]).
- self.assembler.generate_failure(fail_index, locs, False,
- locs_are_ref)
- self.possibly_free_vars_for_op(op)
+ loc = self.loc(op.getarg(0))
+ self.Perform(op, [loc], None)
+ self.possibly_free_var(op.getarg(0))
def consider_guard_no_exception(self, op):
self.perform_guard(op, [], None)
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -49,15 +49,7 @@
return self.assembler.set_debug(flag)
def setup(self):
- if self.opts is not None:
- failargs_limit = self.opts.failargs_limit
- else:
- failargs_limit = 1000
- self.assembler = Assembler386(self, self.translate_support_code,
- failargs_limit)
-
- def get_on_leave_jitted_hook(self):
- return self.assembler.leave_jitted_hook
+ self.assembler = Assembler386(self, self.translate_support_code)
def setup_once(self):
self.profile_agent.startup()
@@ -118,7 +110,7 @@
return self.assembler.fail_ebp
def make_execute_token(self, *ARGS):
- FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, lltype.Signed))
+ FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, llmemory.GCREF))
#
def execute_token(executable_token, *args):
clt = executable_token.compiled_loop_token
@@ -132,12 +124,12 @@
prev_interpreter = LLInterpreter.current_interpreter
LLInterpreter.current_interpreter = self.debug_ll_interpreter
try:
- fail_index = func(*args)
+ deadframe = func(*args)
finally:
if not self.translate_support_code:
LLInterpreter.current_interpreter = prev_interpreter
#llop.debug_print(lltype.Void, "<<<< Back")
- return self.get_fail_descr_from_number(fail_index)
+ return deadframe
return execute_token
def cast_ptr_to_int(x):
diff --git a/pypy/jit/backend/x86/support.py b/pypy/jit/backend/x86/support.py
--- a/pypy/jit/backend/x86/support.py
+++ b/pypy/jit/backend/x86/support.py
@@ -3,31 +3,6 @@
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.jit.backend.x86.arch import WORD
-
-def values_array(TP, size):
- ATP = lltype.GcArray(TP)
-
- class ValuesArray(object):
- SIZE = size
-
- def __init__(self):
- self.ar = lltype.malloc(ATP, size, zero=True, immortal=True)
-
- def get_addr_for_num(self, i):
- return rffi.cast(lltype.Signed, lltype.direct_ptradd(
- lltype.direct_arrayitems(self.ar), i))
-
- def setitem(self, i, v):
- self.ar[i] = v
-
- def getitem(self, i):
- return self.ar[i]
-
- def _freeze_(self):
- return True
-
- return ValuesArray()
-
# ____________________________________________________________
memcpy_fn = rffi.llexternal('memcpy', [llmemory.Address, llmemory.Address,
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -137,8 +137,10 @@
def same_box(self, other):
return self is other
+
class AbstractDescr(AbstractValue):
__slots__ = ()
+ llopaque = True
def repr_of_descr(self):
return '%r' % (self,)
@@ -151,6 +153,17 @@
assert clone.__class__ is self.__class__
return clone
+ def hide(self, cpu):
+ descr_ptr = cpu.ts.cast_instance_to_base_ref(self)
+ return cpu.ts.cast_to_ref(descr_ptr)
+
+ @staticmethod
+ def show(cpu, descr_gcref):
+ from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+ descr_ptr = cpu.ts.cast_to_baseclass(descr_gcref)
+ return cast_base_ptr_to_instance(AbstractDescr, descr_ptr)
+
+
class AbstractFailDescr(AbstractDescr):
index = -1
diff --git a/pypy/rlib/rerased.py b/pypy/rlib/rerased.py
--- a/pypy/rlib/rerased.py
+++ b/pypy/rlib/rerased.py
@@ -130,6 +130,7 @@
# ---------- implementation-specific ----------
class Erased(object):
+ _TYPE = llmemory.GCREF
def __init__(self, x, identity):
self._x = x
self._identity = identity
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit