Author: Maciej Fijalkowski <[email protected]>
Branch: jitframe-on-heap
Changeset: r61262:5fadcd6a778d
Date: 2013-02-15 14:37 +0200
http://bitbucket.org/pypy/pypy/changeset/5fadcd6a778d/
Log: work on call_assembler up to the point at least
diff --git a/rpython/jit/backend/arm/opassembler.py
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -1100,78 +1100,48 @@
self.mc.MOV_rr(res_loc.value, r.fp.value)
return fcond
- # from: ../x86/assembler.py:1668
- # XXX Split into some helper methods
+ def imm(self, v):
+ return imm(v)
+
def emit_guard_call_assembler(self, op, guard_op, arglocs, regalloc,
- fcond):
- tmploc = arglocs[1]
- resloc = arglocs[2]
- callargs = arglocs[3:]
+ fcond):
+ if len(arglocs) == 4:
+ [frame_loc, argloc, vloc, tmploc] = arglocs
+ else:
+ [frame_loc, argloc, tmploc] = arglocs
+ vloc = imm(0)
+ self.call_assembler(op, guard_op, frame_loc, argloc, vloc, tmploc)
+ xxx
- self._store_force_index(guard_op)
- descr = op.getdescr()
- assert isinstance(descr, JitCellToken)
- # check value
- assert tmploc is r.r0
- self._emit_call(imm(descr._ll_function_addr),
- callargs, fcond, resloc=tmploc)
- if op.result is None:
- value = self.cpu.done_with_this_frame_void_v
- else:
- kind = op.result.type
- if kind == INT:
- value = self.cpu.done_with_this_frame_int_v
- elif kind == REF:
- value = self.cpu.done_with_this_frame_ref_v
- elif kind == FLOAT:
- value = self.cpu.done_with_this_frame_float_v
- else:
- raise AssertionError(kind)
- from rpython.jit.backend.llsupport.descr import unpack_fielddescr
- from rpython.jit.backend.llsupport.descr import
unpack_interiorfielddescr
- descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
- _offset, _size, _ = unpack_fielddescr(descrs.jf_descr)
- fail_descr = self.cpu.get_fail_descr_from_number(value)
- value = fail_descr.hide(self.cpu)
- rgc._make_sure_does_not_move(value)
- value = rffi.cast(lltype.Signed, value)
+ def _call_assembler_check_descr(self, value, tmploc):
+ ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
+ self.mc.LDR_ri(r.ip.value, tmploc.value, imm=ofs)
+ self.mc.CMP_ri(r.ip.value, imm=value)
+ pos = self.mc.currpos()
+ self.mc.BPKT()
+ return pos
- if check_imm_arg(_offset):
- self.mc.LDR_ri(r.ip.value, tmploc.value, imm=_offset)
- else:
- self.mc.gen_load_int(r.ip.value, _offset)
- self.mc.LDR_rr(r.ip.value, tmploc.value, r.ip.value)
- if check_imm_arg(value):
- self.mc.CMP_ri(r.ip.value, imm=value)
- else:
- self.mc.gen_load_int(r.lr.value, value)
- self.mc.CMP_rr(r.lr.value, r.ip.value)
+ def _call_assembler_patch_je(self, result_loc, jmp_location):
+ pos = self.mc.currpos()
+ self.mc.BPKT()
+ pmc = OverwritingBuilder(self.mc, jmp_location, WORD)
+ pmc.B_offs(self.mc.currpos(), c.EQ)
+ return pos
+ def _call_assembler_reset_vtoken(self, jd, vloc):
+ from rpython.jit.backend.llsupport.descr import FieldDescr
+ fielddescr = jd.vable_token_descr
+ assert isinstance(fielddescr, FieldDescr)
+ ofs = fielddescr.offset
+ tmploc = self._regalloc.get_scratch_reg(INT)
+ self.mov_loc_loc(vloc, r.ip)
+ self.mc.MOV_ri(tmploc.value, 0)
+ self.mc.STR_ri(tmploc.value, r.ip.value, ofs)
- #if values are equal we take the fast path
- # Slow path, calling helper
- # jump to merge point
-
- jd = descr.outermost_jitdriver_sd
- assert jd is not None
-
- # Path A: load return value and reset token
- # Fast Path using result boxes
-
- fast_path_cond = c.EQ
- # Reset the vable token --- XXX really too much special logic here:-(
- if jd.index_of_virtualizable >= 0:
- from rpython.jit.backend.llsupport.descr import FieldDescr
- fielddescr = jd.vable_token_descr
- assert isinstance(fielddescr, FieldDescr)
- ofs = fielddescr.offset
- tmploc = regalloc.get_scratch_reg(INT)
- self.mov_loc_loc(arglocs[0], r.ip, cond=fast_path_cond)
- self.mc.MOV_ri(tmploc.value, 0, cond=fast_path_cond)
- self.mc.STR_ri(tmploc.value, r.ip.value, ofs, cond=fast_path_cond)
-
+ def _call_assembler_load_result(self, op, result_loc):
+ XXX
if op.result is not None:
- # load the return value from fail_boxes_xxx[0]
+ # load the return value from (tmploc, 0)
kind = op.result.type
if kind == FLOAT:
t = unpack_interiorfielddescr(descrs.as_float)[0]
diff --git a/rpython/jit/backend/arm/regalloc.py
b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -1101,20 +1101,10 @@
prepare_guard_call_release_gil = prepare_guard_call_may_force
def prepare_guard_call_assembler(self, op, guard_op, fcond):
- descr = op.getdescr()
- assert isinstance(descr, JitCellToken)
- jd = descr.outermost_jitdriver_sd
- assert jd is not None
- vable_index = jd.index_of_virtualizable
- if vable_index >= 0:
- self._sync_var(op.getarg(vable_index))
- vable = self.frame_manager.loc(op.getarg(vable_index))
- else:
- vable = imm(0)
- # make sure the call result location is free
tmploc = self.get_scratch_reg(INT, selected_reg=r.r0)
+ locs = self.locs_for_call_assembler(op, guard_op)
self.possibly_free_vars(guard_op.getfailargs())
- return [vable, tmploc] + self._prepare_call(op, save_all_regs=True)
+ return locs + [tmploc]
def _prepare_args_for_new_op(self, new_args):
gc_ll_descr = self.cpu.gc_ll_descr
diff --git a/rpython/jit/backend/llsupport/assembler.py
b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -1,7 +1,8 @@
+from rpython.rlib import rgc
from rpython.rlib.rarithmetic import r_uint
from rpython.jit.backend.llsupport.symbolic import WORD
-from rpython.jit.metainterp.history import REF, FLOAT
+from rpython.jit.metainterp.history import INT, REF, FLOAT, JitCellToken
from rpython.rtyper.annlowlevel import cast_instance_to_gcref
from rpython.rtyper.lltypesystem import rffi, lltype
@@ -100,3 +101,59 @@
# we want the descr to keep alive
guardtok.faildescr.rd_loop_token = self.current_clt
return fail_descr, target
+
+ def call_assembler(self, op, guard_op, frame_loc, argloc,
+ vloc, result_loc, tmploc):
+ self._store_force_index(guard_op)
+ descr = op.getdescr()
+ assert isinstance(descr, JitCellToken)
+ #
+ # Write a call to the target assembler
+ # we need to allocate the frame, keep in sync with runner's
+ # execute_token
+ jd = descr.outermost_jitdriver_sd
+ self._emit_call(self.imm(descr._ll_function_addr),
+ [argloc], 0, tmp=tmploc)
+ if op.result is None:
+ assert result_loc is None
+ value = self.cpu.done_with_this_frame_descr_void
+ else:
+ kind = op.result.type
+ if kind == INT:
+ assert result_loc is tmploc
+ value = self.cpu.done_with_this_frame_descr_int
+ elif kind == REF:
+ assert result_loc is tmploc
+ value = self.cpu.done_with_this_frame_descr_ref
+ elif kind == FLOAT:
+ value = self.cpu.done_with_this_frame_descr_float
+ else:
+ raise AssertionError(kind)
+
+ gcref = cast_instance_to_gcref(value)
+ rgc._make_sure_does_not_move(gcref)
+ value = rffi.cast(lltype.Signed, gcref)
+ je_location = self._call_assembler_check_descr(value, tmploc)
+ #
+ # Path A: use assembler_helper_adr
+ assert jd is not None
+ asm_helper_adr = self.cpu.cast_adr_to_int(jd.assembler_helper_adr)
+
+ self._emit_call(self.imm(asm_helper_adr),
+ [tmploc, vloc], 0, tmp=self._second_tmp_reg)
+
+ jmp_location = self._call_assembler_patch_je(result_loc, je_location)
+
+ # Path B: fast path. Must load the return value, and reset the token
+
+ # Reset the vable token --- XXX really too much special logic here:-(
+ if jd.index_of_virtualizable >= 0:
+ self._call_assembler_reset_vtoken(jd, vloc)
+ #
+ self._call_assembler_load_result(op, result_loc)
+ #
+ # Here we join Path A and Path B again
+ self._call_assembler_patch_jmp(jmp_location)
+ # XXX here should be emitted guard_not_forced, but due
+ # to incompatibilities in how it's done, we leave it for the
+ # caller to deal with
diff --git a/rpython/jit/backend/llsupport/regalloc.py
b/rpython/jit/backend/llsupport/regalloc.py
--- a/rpython/jit/backend/llsupport/regalloc.py
+++ b/rpython/jit/backend/llsupport/regalloc.py
@@ -1,5 +1,5 @@
import os
-from rpython.jit.metainterp.history import Const, Box, REF
+from rpython.jit.metainterp.history import Const, Box, REF, JitCellToken
from rpython.rlib.objectmodel import we_are_translated, specialize
from rpython.jit.metainterp.resoperation import rop
@@ -667,6 +667,18 @@
return False
return True
+ def locs_for_call_assembler(self, op, guard_op):
+ descr = op.getdescr()
+ assert isinstance(descr, JitCellToken)
+ arglist = op.getarglist()
+ self.rm._sync_var(arglist[0])
+ frame_loc = self.fm.loc(op.getarg(0))
+ if len(arglist) == 2:
+ self.rm._sync_var(arglist[1])
+ return [frame_loc, self.loc(arglist[0]), self.fm.loc(arglist[1])]
+ else:
+ return [frame_loc, self.loc(arglist[0])]
+
def compute_vars_longevity(inputargs, operations):
# compute a dictionary that maps variables to index in
diff --git a/rpython/jit/backend/x86/assembler.py
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -51,6 +51,7 @@
class Assembler386(BaseAssembler):
_regalloc = None
_output_loop_log = None
+ _second_tmp_reg = ecx
def __init__(self, cpu, translate_support_code=False):
self.cpu = cpu
@@ -2198,76 +2199,51 @@
if isinstance(save_loc, RegLoc) and not save_loc.is_xmm:
self.mc.MOV_rs(save_loc.value, WORD)
+ def imm(self, v):
+ return imm(v)
+
+ # ------------------- CALL ASSEMBLER --------------------------
+
def genop_guard_call_assembler(self, op, guard_op, guard_token,
arglocs, result_loc):
- self._store_force_index(guard_op)
- descr = op.getdescr()
- assert isinstance(descr, JitCellToken)
if len(arglocs) == 3:
[frame_loc, argloc, vloc] = arglocs
else:
[frame_loc, argloc] = arglocs
- vloc = imm(0)
- #
- # Write a call to the target assembler
- # we need to allocate the frame, keep in sync with runner's
- # execute_token
- jd = descr.outermost_jitdriver_sd
- base_ofs = self.cpu.get_baseofs_of_frame_field()
- self._emit_call(imm(descr._ll_function_addr),
- [argloc], 0, tmp=eax)
- if op.result is None:
- assert result_loc is None
- value = self.cpu.done_with_this_frame_descr_void
- else:
- kind = op.result.type
- if kind == INT:
- assert result_loc is eax
- value = self.cpu.done_with_this_frame_descr_int
- elif kind == REF:
- assert result_loc is eax
- value = self.cpu.done_with_this_frame_descr_ref
- elif kind == FLOAT:
- value = self.cpu.done_with_this_frame_descr_float
- else:
- raise AssertionError(kind)
+ vloc = self.imm(0)
+ self.call_assembler(op, guard_op, frame_loc, argloc, vloc,
+ result_loc, eax)
+ self._emit_guard_not_forced(guard_token)
- gcref = cast_instance_to_gcref(value)
- rgc._make_sure_does_not_move(gcref)
- value = rffi.cast(lltype.Signed, gcref)
+ def _call_assembler_check_descr(self, value, tmploc):
ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
self.mc.CMP_mi((eax.value, ofs), value)
# patched later
self.mc.J_il8(rx86.Conditions['E'], 0) # goto B if we get
'done_with_this_frame'
- je_location = self.mc.get_relative_pos()
- #
- # Path A: use assembler_helper_adr
- assert jd is not None
- asm_helper_adr = self.cpu.cast_adr_to_int(jd.assembler_helper_adr)
+ return self.mc.get_relative_pos()
- self._emit_call(imm(asm_helper_adr),
- [eax, vloc], 0, tmp=ecx)
+ def _call_assembler_patch_je(self, result_loc, je_location):
if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type
== FLOAT:
self.mc.FSTPL_b(result_loc.value)
- #else: result_loc is already either eax or None, checked below
self.mc.JMP_l8(0) # jump to done, patched later
jmp_location = self.mc.get_relative_pos()
#
- # Path B: fast path. Must load the return value, and reset the token
offset = jmp_location - je_location
assert 0 < offset <= 127
self.mc.overwrite(je_location - 1, chr(offset))
#
- # Reset the vable token --- XXX really too much special logic here:-(
- if jd.index_of_virtualizable >= 0:
- from rpython.jit.backend.llsupport.descr import FieldDescr
- fielddescr = jd.vable_token_descr
- assert isinstance(fielddescr, FieldDescr)
- vtoken_ofs = fielddescr.offset
- self.mc.MOV(edx, vloc) # we know vloc is on the current frame
- self.mc.MOV_mi((edx.value, vtoken_ofs), 0)
- # in the line above, TOKEN_NONE = 0
- #
+ return jmp_location
+
+ def _call_assembler_reset_vtoken(self, jd, vloc):
+ from rpython.jit.backend.llsupport.descr import FieldDescr
+ fielddescr = jd.vable_token_descr
+ assert isinstance(fielddescr, FieldDescr)
+ vtoken_ofs = fielddescr.offset
+ self.mc.MOV(edx, vloc) # we know vloc is on the current frame
+ self.mc.MOV_mi((edx.value, vtoken_ofs), 0)
+ # in the line above, TOKEN_NONE = 0
+
+ def _call_assembler_load_result(self, op, result_loc):
if op.result is not None:
# load the return value from the dead frame's value index 0
kind = op.result.type
@@ -2282,12 +2258,13 @@
descr = self.cpu.getarraydescr_for_frame(kind)
ofs = self.cpu.unpack_arraydescr(descr)
self.mc.MOV_rm(eax.value, (eax.value, ofs))
- #
- # Here we join Path A and Path B again
+
+ def _call_assembler_patch_jmp(self, jmp_location):
offset = self.mc.get_relative_pos() - jmp_location
assert 0 <= offset <= 127
self.mc.overwrite(jmp_location - 1, chr(offset))
- self._emit_guard_not_forced(guard_token)
+
+ # ------------------- END CALL ASSEMBLER -----------------------
def _write_barrier_fastpath(self, mc, descr, arglocs, array=False,
is_frame=False):
diff --git a/rpython/jit/backend/x86/regalloc.py
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -6,7 +6,7 @@
from rpython.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr,
ConstFloat, BoxInt,
BoxFloat, INT, REF, FLOAT,
- TargetToken, JitCellToken)
+ TargetToken)
from rpython.jit.backend.x86.regloc import *
from rpython.rtyper.lltypesystem import lltype, rffi, rstr
from rpython.rtyper.annlowlevel import cast_instance_to_gcref
@@ -802,16 +802,7 @@
self._consider_call(op)
def consider_call_assembler(self, op, guard_op):
- descr = op.getdescr()
- assert isinstance(descr, JitCellToken)
- arglist = op.getarglist()
- self.rm._sync_var(arglist[0])
- frame_loc = self.fm.loc(op.getarg(0))
- if len(arglist) == 2:
- self.rm._sync_var(arglist[1])
- locs = [frame_loc, self.loc(arglist[0]), self.fm.loc(arglist[1])]
- else:
- locs = [frame_loc, self.loc(arglist[0])]
+ locs = self.locs_for_call_assembler(op, guard_op)
self._call(op, locs, guard_not_forced_op=guard_op)
def consider_cond_call_gc_wb(self, op):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit