[pypy-commit] pypy arm-backend-2: port encoding of locations used for guards from the x86 backend
bivab
noreply at buildbot.pypy.org
Mon Jan 9 11:56:51 CET 2012
Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r51167:ffbd6f34a8c3
Date: 2012-01-04 15:58 +0100
http://bitbucket.org/pypy/pypy/changeset/ffbd6f34a8c3/
Log: port encoding of locations used for guards from the x86 backend
diff --git a/pypy/jit/backend/arm/assembler.py b/pypy/jit/backend/arm/assembler.py
--- a/pypy/jit/backend/arm/assembler.py
+++ b/pypy/jit/backend/arm/assembler.py
@@ -11,6 +11,7 @@
from pypy.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
ARMv7RegisterManager, check_imm_arg,
operations as regalloc_operations,
+ get_fp_offset,
operations_with_guard as regalloc_operations_with_guard)
from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
from pypy.jit.backend.model import CompiledLoopToken
@@ -30,30 +31,6 @@
class AssemblerARM(ResOpAssembler):
- """
- Encoding for locations in memory
- types:
- \xED = FLOAT
- \xEE = REF
- \xEF = INT
- location:
- \xFC = stack location
- \xFD = imm location
- emtpy = reg location
- \xFE = Empty loc
-
- \xFF = END_OF_LOCS
- """
- FLOAT_TYPE = '\xED'
- REF_TYPE = '\xEE'
- INT_TYPE = '\xEF'
-
- STACK_LOC = '\xFC'
- IMM_LOC = '\xFD'
- # REG_LOC is empty
- EMPTY_LOC = '\xFE'
-
- END_OF_LOCS = '\xFF'
STACK_FIXED_AREA = -1
@@ -183,132 +160,138 @@
"""mem_loc is a structure in memory describing where the values for
the failargs are stored. frame loc is the address of the frame
pointer for the frame to be decoded frame """
- return self.decode_registers_and_descr(mem_loc,
- frame_pointer, stack_pointer)
+ vfp_registers = rffi.cast(rffi.LONGLONGP, stack_pointer)
+ registers = rffi.ptradd(vfp_registers, len(r.all_vfp_regs))
+ registers = rffi.cast(rffi.LONGP, registers)
+ return self.decode_registers_and_descr(mem_loc, frame_pointer,
+ registers, vfp_registers)
self.failure_recovery_func = failure_recovery_func
- recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed,
- lltype.Signed, lltype.Signed], lltype.Signed))
+ recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed] * 3,
+ lltype.Signed))
@rgc.no_collect
- def decode_registers_and_descr(self, mem_loc, frame_loc, regs_loc):
+ def decode_registers_and_descr(self, mem_loc, frame_pointer,
+ registers, vfp_registers):
"""Decode locations encoded in memory at mem_loc and write the values
to the failboxes. Values for spilled vars and registers are stored on
stack at frame_loc """
- # XXX check if units are correct here, when comparing words and bytes
- # and stuff assert 0, 'check if units are correct here, when comparing
- # words and bytes and stuff'
+ assert frame_pointer & 1 == 0
+ bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+ num = 0
+ value = 0
+ fvalue = 0
+ code_inputarg = False
+ while True:
+ code = bytecode[0]
+ bytecode = rffi.ptradd(bytecode, 1)
+ if code >= self.CODE_FROMSTACK:
+ if code > 0x7F:
+ shift = 7
+ code &= 0x7F
+ while True:
+ nextcode = rffi.cast(lltype.Signed, bytecode[0])
+ bytecode = rffi.ptradd(bytecode, 1)
+ code |= (nextcode & 0x7F) << shift
+ shift += 7
+ if nextcode <= 0x7F:
+ break
+ # load the value from the stack
+ kind = code & 3
+ code = int((code - self.CODE_FROMSTACK) >> 2)
+ if code_inputarg:
+ code = ~code
+ code_inputarg = False
+ if kind == self.DESCR_FLOAT:
+ # we use code + 1 to get the hi word of the double worded float
+ stackloc = frame_pointer - get_fp_offset(int(code) + 1)
+ assert stackloc & 3 == 0
+ fvalue = rffi.cast(rffi.LONGLONGP, stackloc)[0]
+ else:
+ stackloc = frame_pointer - get_fp_offset(int(code))
+ assert stackloc & 1 == 0
+ value = rffi.cast(rffi.LONGP, stackloc)[0]
+ else:
+ # 'code' identifies a register: load its value
+ kind = code & 3
+ if kind == self.DESCR_SPECIAL:
+ if code == self.CODE_HOLE:
+ num += 1
+ continue
+ if code == self.CODE_INPUTARG:
+ code_inputarg = True
+ continue
+ assert code == self.CODE_STOP
+ break
+ code >>= 2
+ if kind == self.DESCR_FLOAT:
+ fvalue = vfp_registers[code]
+ else:
+ value = registers[code]
+ # store the loaded value into fail_boxes_<type>
+ if kind == self.DESCR_FLOAT:
+ tgt = self.fail_boxes_float.get_addr_for_num(num)
+ rffi.cast(rffi.LONGLONGP, tgt)[0] = fvalue
+ else:
+ if kind == self.DESCR_INT:
+ tgt = self.fail_boxes_int.get_addr_for_num(num)
+ elif kind == self.DESCR_REF:
+ assert (value & 3) == 0, "misaligned pointer"
+ tgt = self.fail_boxes_ptr.get_addr_for_num(num)
+ else:
+ assert 0, "bogus kind"
+ rffi.cast(rffi.LONGP, tgt)[0] = value
+ num += 1
+ self.fail_boxes_count = num
+ fail_index = rffi.cast(rffi.INTP, bytecode)[0]
+ fail_index = rffi.cast(lltype.Signed, fail_index)
+ return fail_index
- enc = rffi.cast(rffi.CCHARP, mem_loc)
- frame_depth = frame_loc - (regs_loc + len(r.all_regs)
- * WORD + len(r.all_vfp_regs) * DOUBLE_WORD)
- assert (frame_loc - frame_depth) % 4 == 0
- stack = rffi.cast(rffi.CCHARP, frame_loc - frame_depth)
- assert regs_loc % 4 == 0
- vfp_regs = rffi.cast(rffi.CCHARP, regs_loc)
- assert (regs_loc + len(r.all_vfp_regs) * DOUBLE_WORD) % 4 == 0
- assert frame_depth >= 0
-
- regs = rffi.cast(rffi.CCHARP,
- regs_loc + len(r.all_vfp_regs) * DOUBLE_WORD)
- i = -1
- fail_index = -1
- while(True):
- i += 1
- fail_index += 1
- res = enc[i]
- if res == self.END_OF_LOCS:
+ def decode_inputargs(self, code):
+ descr_to_box_type = [REF, INT, FLOAT]
+ bytecode = rffi.cast(rffi.UCHARP, code)
+ arglocs = []
+ code_inputarg = False
+ while 1:
+ # decode the next instruction from the bytecode
+ code = rffi.cast(lltype.Signed, bytecode[0])
+ bytecode = rffi.ptradd(bytecode, 1)
+ if code >= self.CODE_FROMSTACK:
+ # 'code' identifies a stack location
+ if code > 0x7F:
+ shift = 7
+ code &= 0x7F
+ while True:
+ nextcode = rffi.cast(lltype.Signed, bytecode[0])
+ bytecode = rffi.ptradd(bytecode, 1)
+ code |= (nextcode & 0x7F) << shift
+ shift += 7
+ if nextcode <= 0x7F:
+ break
+ kind = code & 3
+ code = (code - self.CODE_FROMSTACK) >> 2
+ if code_inputarg:
+ code = ~code
+ code_inputarg = False
+ loc = ARMFrameManager.frame_pos(code, descr_to_box_type[kind])
+ elif code == self.CODE_STOP:
break
- if res == self.EMPTY_LOC:
+ elif code == self.CODE_HOLE:
continue
-
- group = res
- i += 1
- res = enc[i]
- if res == self.IMM_LOC:
- # imm value
- if group == self.INT_TYPE or group == self.REF_TYPE:
- value = decode32(enc, i + 1)
- i += 4
+ elif code == self.CODE_INPUTARG:
+ code_inputarg = True
+ continue
+ else:
+ # 'code' identifies a register
+ kind = code & 3
+ code >>= 2
+ if kind == self.DESCR_FLOAT:
+ loc = r.all_vfp_regs[code]
else:
- assert group == self.FLOAT_TYPE
- adr = decode32(enc, i + 1)
- tp = rffi.CArrayPtr(longlong.FLOATSTORAGE)
- value = rffi.cast(tp, adr)[0]
- self.fail_boxes_float.setitem(fail_index, value)
- i += 4
- continue
- elif res == self.STACK_LOC:
- stack_loc = decode32(enc, i + 1)
- i += 4
- if group == self.FLOAT_TYPE:
- value = decode64(stack,
- frame_depth - (stack_loc + 1) * WORD)
- fvalue = rffi.cast(longlong.FLOATSTORAGE, value)
- self.fail_boxes_float.setitem(fail_index, fvalue)
- continue
- else:
- value = decode32(stack, frame_depth - stack_loc * WORD)
- else: # REG_LOC
- reg = ord(enc[i])
- if group == self.FLOAT_TYPE:
- value = decode64(vfp_regs, reg * DOUBLE_WORD)
- self.fail_boxes_float.setitem(fail_index, value)
- continue
- else:
- value = decode32(regs, reg * WORD)
-
- if group == self.INT_TYPE:
- self.fail_boxes_int.setitem(fail_index, value)
- elif group == self.REF_TYPE:
- assert (value & 3) == 0, "misaligned pointer"
- tgt = self.fail_boxes_ptr.get_addr_for_num(fail_index)
- rffi.cast(rffi.LONGP, tgt)[0] = value
- else:
- assert 0, 'unknown type'
-
- assert enc[i] == self.END_OF_LOCS
- descr = decode32(enc, i + 1)
- self.fail_boxes_count = fail_index
- self.fail_force_index = frame_loc
- return descr
-
- def decode_inputargs(self, enc):
- locs = []
- j = 0
- while enc[j] != self.END_OF_LOCS:
- res = enc[j]
- if res == self.EMPTY_LOC:
- j += 1
- continue
-
- assert res in [self.FLOAT_TYPE, self.INT_TYPE, self.REF_TYPE], \
- 'location type is not supported'
- res_type = res
- j += 1
- res = enc[j]
- if res == self.IMM_LOC:
- # XXX decode imm if necessary
- assert 0, 'Imm Locations are not supported'
- elif res == self.STACK_LOC:
- if res_type == self.FLOAT_TYPE:
- t = FLOAT
- elif res_type == self.INT_TYPE:
- t = INT
- else:
- t = REF
- stack_loc = decode32(enc, j + 1)
- loc = ARMFrameManager.frame_pos(stack_loc, t)
- j += 4
- else: # REG_LOC
- if res_type == self.FLOAT_TYPE:
- loc = r.all_vfp_regs[ord(res)]
- else:
- loc = r.all_regs[ord(res)]
- j += 1
- locs.append(loc)
- return locs
+ loc = r.all_regs[code]
+ arglocs.append(loc)
+ return arglocs[:]
def _build_malloc_slowpath(self):
mc = ARMv7Builder()
@@ -364,85 +347,78 @@
return mc.materialize(self.cpu.asmmemmgr, [],
self.cpu.gc_ll_descr.gcrootmap)
- def gen_descr_encoding(self, descr, args, arglocs):
- # The size of the allocated memory is based on the following sizes
- # first argloc is the frame depth and not considered for the memory
- # allocation
- # 4 bytes for the value
- # 1 byte for the type
- # 1 byte for the location
- # 1 separator byte
- # 4 bytes for the faildescr
- # const floats are stored in memory and the box contains the address
- memsize = (len(arglocs) - 1) * 6 + 5
+ DESCR_REF = 0x00
+ DESCR_INT = 0x01
+ DESCR_FLOAT = 0x02
+ DESCR_SPECIAL = 0x03
+ CODE_FROMSTACK = 64
+ CODE_STOP = 0 | DESCR_SPECIAL
+ CODE_HOLE = 4 | DESCR_SPECIAL
+ CODE_INPUTARG = 8 | DESCR_SPECIAL
+
+ def gen_descr_encoding(self, descr, failargs, locs):
+ buf = []
+ for i in range(len(failargs)):
+ arg = failargs[i]
+ if arg is not None:
+ if arg.type == REF:
+ kind = self.DESCR_REF
+ elif arg.type == INT:
+ kind = self.DESCR_INT
+ elif arg.type == FLOAT:
+ kind = self.DESCR_FLOAT
+ else:
+ raise AssertionError("bogus kind")
+ loc = locs[i]
+ if loc.is_stack():
+ pos = loc.position
+ if pos < 0:
+ buf.append(chr(self.CODE_INPUTARG))
+ pos = ~pos
+ n = self.CODE_FROMSTACK // 4 + pos
+ else:
+ assert loc.is_reg() or loc.is_vfp_reg()
+ n = loc.value
+ n = kind + 4 * n
+ while n > 0x7F:
+ buf.append(chr((n & 0x7F) | 0x80))
+ n >>= 7
+ else:
+ n = self.CODE_HOLE
+ buf.append(chr(n))
+ buf.append(chr(self.CODE_STOP))
+
+ fdescr = self.cpu.get_fail_descr_number(descr)
+ buf.append(chr(fdescr & 0xFF))
+ buf.append(chr(fdescr >> 8 & 0xFF))
+ buf.append(chr(fdescr >> 16 & 0xFF))
+ buf.append(chr(fdescr >> 24 & 0xFF))
+
+ # assert that the fail_boxes lists are big enough
+ assert len(failargs) <= self.fail_boxes_int.SIZE
+
+ memsize = len(buf)
memaddr = self.datablockwrapper.malloc_aligned(memsize, alignment=1)
mem = rffi.cast(rffi.CArrayPtr(lltype.Char), memaddr)
- i = 0
- j = 0
- while i < len(args):
- if arglocs[i + 1]:
- arg = args[i]
- loc = arglocs[i + 1]
- if arg.type == INT:
- mem[j] = self.INT_TYPE
- j += 1
- elif arg.type == REF:
- mem[j] = self.REF_TYPE
- j += 1
- elif arg.type == FLOAT:
- mem[j] = self.FLOAT_TYPE
- j += 1
- else:
- assert 0, 'unknown type'
-
- if loc.is_reg() or loc.is_vfp_reg():
- mem[j] = chr(loc.value)
- j += 1
- elif loc.is_imm() or loc.is_imm_float():
- assert (arg.type == INT or arg.type == REF
- or arg.type == FLOAT)
- mem[j] = self.IMM_LOC
- encode32(mem, j + 1, loc.getint())
- j += 5
- else:
- assert loc.is_stack()
- mem[j] = self.STACK_LOC
- if arg.type == FLOAT:
- # Float locs store the location number with an offset
- # of 1 -.- so we need to take this into account here
- # when generating the encoding
- encode32(mem, j + 1, loc.position - 1)
- else:
- encode32(mem, j + 1, loc.position)
- j += 5
- else:
- mem[j] = self.EMPTY_LOC
- j += 1
- i += 1
-
- mem[j] = chr(0xFF)
-
- n = self.cpu.get_fail_descr_number(descr)
- encode32(mem, j + 1, n)
+ for i in range(memsize):
+ mem[i] = buf[i]
return memaddr
def _gen_path_to_exit_path(self, descr, args, arglocs,
save_exc, fcond=c.AL):
assert isinstance(save_exc, bool)
- memaddr = self.gen_descr_encoding(descr, args, arglocs)
+ memaddr = self.gen_descr_encoding(descr, args, arglocs[1:])
self.gen_exit_code(self.mc, memaddr, save_exc, fcond)
return memaddr
def gen_exit_code(self, mc, memaddr, save_exc, fcond=c.AL):
assert isinstance(save_exc, bool)
self.mc.gen_load_int(r.ip.value, memaddr)
- #mc.LDR_ri(r.ip.value, r.pc.value, imm=WORD)
if save_exc:
path = self._leave_jitted_hook_save_exc
else:
path = self._leave_jitted_hook
mc.B(path)
- #mc.write32(memaddr)
def align(self):
while(self.mc.currpos() % FUNC_ALIGN != 0):
@@ -576,9 +552,8 @@
self._dump(operations, 'bridge')
assert isinstance(faildescr, AbstractFailDescr)
code = faildescr._arm_failure_recovery_code
- enc = rffi.cast(rffi.CCHARP, code)
frame_depth = faildescr._arm_current_frame_depth
- arglocs = self.decode_inputargs(enc)
+ arglocs = self.decode_inputargs(code)
if not we_are_translated():
assert len(inputargs) == len(arglocs)
diff --git a/pypy/jit/backend/arm/locations.py b/pypy/jit/backend/arm/locations.py
--- a/pypy/jit/backend/arm/locations.py
+++ b/pypy/jit/backend/arm/locations.py
@@ -80,9 +80,6 @@
def is_imm(self):
return True
- def as_key(self):
- return self.value + 40
-
class ConstFloatLoc(AssemblerLocation):
"""This class represents an imm float value which is stored in memory at
@@ -103,9 +100,6 @@
def is_imm_float(self):
return True
- def as_key(self):
- return -1 * self.value
-
class StackLocation(AssemblerLocation):
_immutable_ = True
@@ -132,7 +126,7 @@
return True
def as_key(self):
- return -self.position
+ return self.position + 10000
def imm(i):
diff --git a/pypy/jit/backend/arm/regalloc.py b/pypy/jit/backend/arm/regalloc.py
--- a/pypy/jit/backend/arm/regalloc.py
+++ b/pypy/jit/backend/arm/regalloc.py
@@ -327,6 +327,7 @@
count = 0
n_register_args = len(r.argument_regs)
cur_frame_pos = - (self.assembler.STACK_FIXED_AREA / WORD) + 1
+ cur_frame_pos = 1 - (self.assembler.STACK_FIXED_AREA // WORD)
for box in inputargs:
assert isinstance(box, Box)
# handle inputargs in argument registers
More information about the pypy-commit
mailing list