[pypy-svn] r73415 - in pypy/branch/jit-stackless/pypy/jit: backend/llgraph backend/x86 backend/x86/test metainterp/test
iammisc at codespeak.net
iammisc at codespeak.net
Mon Apr 5 18:48:40 CEST 2010
Author: iammisc
Date: Mon Apr 5 18:48:39 2010
New Revision: 73415
Added:
pypy/branch/jit-stackless/pypy/jit/backend/x86/test/test_stackless_integration.py
Modified:
pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py
pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py
Log:
Added some tests for x86
Modified: pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/jit-stackless/pypy/jit/backend/llgraph/llimpl.py Mon Apr 5 18:48:39 2010
@@ -463,6 +463,10 @@
log.trace('failed: %s' % (
', '.join(map(str, fail_args)),))
return op.fail_index
+ except UnwindException:
+ assert op.is_guard()
+ self._populate_fail_args(op)
+ raise
#verbose = self.verbose
assert (result is None) == (op.result is None)
if op.result is not None:
Modified: pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/jit-stackless/pypy/jit/backend/x86/assembler.py Mon Apr 5 18:48:39 2010
@@ -32,11 +32,11 @@
def align_stack_words(words):
return (words + CALL_ALIGN - 1) & ~(CALL_ALIGN-1)
-JIT_STATE_HEADER = lltype.Struct('JIT_STATE_HEADER',
- ('header', STATE_HEADER),
- ('saved_ints', lltype.Ptr(lltype.GcArray(lltype.Signed))),
- ('saved_floats', lltype.Ptr(lltype.GcArray(lltype.Float))),
- ('saved_refs', lltype.Ptr(lltype.GcArray(lltype.Ptr))))
+JIT_STATE_HEADER = lltype.GcStruct('JIT_STATE_HEADER',
+ ('header', STATE_HEADER),
+ ('saved_ints', lltype.Ptr(lltype.GcArray(lltype.Signed))),
+ ('saved_floats', lltype.Ptr(lltype.GcArray(lltype.Float))),
+ ('saved_refs', lltype.Ptr(lltype.GcArray(llmemory.GCREF))))
class MachineCodeBlockWrapper(object):
MC_DEFAULT_SIZE = 1024*1024
@@ -987,7 +987,7 @@
loc1 = locs[1]
if self.cpu.stackless:
unwinder_addr = self.generate_unwinder_failure(guard_op.descr, guard_op.fail_args, faillocs)
- stku_type, stku_instance = self.cpu.get_unwind_exception()
+ stku_type, stku_instance = self.cpu.get_unwind_exception()
self.mc.CMP(heap(self.cpu.pos_exception()), imm(stku_type))
self.mc.JE(rel32(unwinder_addr)) # if this is indeed an unwind exception jump to saver code
self.mc.MOV(loc1, heap(self.cpu.pos_exception()))
@@ -1228,37 +1228,97 @@
@rgc.no_collect
def unwind_frame_values(self, bytecode, frame_addr, allregisters):
- # Okay allocate a frame for us,
+ # Allocate a frame for us,
- # then set the proper values in global_state
+ # XXX set the proper values in global_state
+ self.fail_ebp = allregisters[16 + ebp.op]
- bytecode = rffi.cast(rffi.UCHARP, bytecode)
boxes = []
+ kinds = []
+ ints, floats, refs = (0, 0, 0)
+ int_num, float_num, ref_num = (0, 0, 0)
+ int_boxes, float_boxes, ref_boxes = (None, None, None)
+ num = 0
while 1:
# decode the next instruction from the bytecode
code = rffi.cast(lltype.Signed, bytecode[0])
bytecode = rffi.ptradd(bytecode, 1)
- kind = code & 3
- while code > 0x7F:
- code = rffi.cast(lltype.Signed, bytecode[0])
- bytecode = rffi.ptradd(bytecode, 1)
- index = len(boxes)
- # Now kind contains information at the type of data that will go here
- if kind != self.DESCR_SPECIAL:
- kinds.append(kind)
+ 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 = (code - self.CODE_FROMSTACK) >> 2
+ stackloc = frame_addr + get_ebp_ofs(code)
+ value = rffi.cast(rffi.LONGP, stackloc)[0]
+ kinds.append((kind, True, stackloc))
else:
- if code == self.CODE_STOP:
+ kind = code & 3
+ if kind == self.DESCR_SPECIAL:
+ if code == self.CODE_HOLE:
+ num += 1
+ continue
+ assert code == self.CODE_STOP
break
- assert code == self.CODE_HOLE, "Bad code"
+ code >>= 2
+ kinds.append((kind, False, code))
+
+ if kind == self.DESCR_INT:
+ ints += 1
+ elif kind == self.DESCR_FLOAT:
+ floats += 1
+ elif kind == self.DESCR_REF:
+ refs += 1
- # Now kinds contains the types we need to store
+ # Now kinds contains the types we need to store in the right order
state_header = lltype.malloc(JIT_STATE_HEADER, zero=True)
- state_header.saved_ints = lltype.malloc(lltype.GcArray(lltype.Signed), len([x for x in kinds if x == self.DESCR_INT]))
- state_header.saved_floats = lltype.malloc(lltype.GcArray(lltype.Float), len([x for x in kinds if x == self.DESCR_FLOAT]))
- state_header.saved_floats = lltype.malloc(lltype.GcArray(lltype.Ptr), len([x for x in kinds if x == self.DESCR_REF]))
+ if ints:
+ int_boxes = values_array(lltype.Signed, ints)
+ state_header.saved_ints = int_boxes.ar
+ if floats:
+ float_boxes = values_array(lltype.Float, floats)
+ state_header.saved_floats = float_boxes.ar
+ if refs:
+ ref_boxes = values_array(llmemory.GCREF, refs)
+ state_header.saved_refs = ref_boxes.ar
+
+ value, value_hi = (0, 0)
+
+ for (kind, in_stack, loc) in kinds:
+ if in_stack:
+ value = rffi.cast(rffi.LONGP, loc)[0]
+ if kind == self.DESCR_FLOAT:
+ value_hi = value
+ value = rffi.cast(rffi.LONGP, loc - 4)[0]
+ else:
+ if kind == self.DESCR_FLOAT:
+ value = allregisters[2*loc]
+ value_hi = allregisters[2*loc+1]
+ else:
+ value = allregisters[16 + loc]
-
+ if kind == self.DESCR_INT:
+ tgt = int_boxes.get_addr_for_num(int_num)
+ int_num += 1
+ elif kind == self.DESCR_REF:
+ tgt = ref_boxes.get_addr_for_num(ref_num)
+ ref_num += 1
+ elif kind == self.DESCR_FLOAT:
+ tgt = float_boxes.get_addr_for_num(float_num)
+ float_num += 1
+ rffi.cast(rffi.LONGP, tgt)[1] = value_hi
+ rffi.cast(rffi.LONGP, tgt)[0] = value
+
+ return state_header
@rgc.no_collect
def grab_frame_values(self, bytecode, frame_addr, allregisters):
Added: pypy/branch/jit-stackless/pypy/jit/backend/x86/test/test_stackless_integration.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-stackless/pypy/jit/backend/x86/test/test_stackless_integration.py Mon Apr 5 18:48:39 2010
@@ -0,0 +1,141 @@
+from pypy.jit.backend.x86.ri386 import *
+from pypy.jit.backend.x86.assembler import Assembler386
+from pypy.rpython.lltypesystem import lltype, rffi, rstr, llmemory
+from pypy.jit.backend.x86.regalloc import X86FrameManager, get_ebp_ofs
+from pypy.jit.backend.x86.test.test_assembler import FakeMC, FakeCPU
+
+def do_unwinder_recovery_func(withfloats=False):
+ import random
+ S = lltype.GcStruct('S')
+
+ def get_random_int():
+ return random.randrange(-10000, 10000)
+ def get_random_ptr():
+ return lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S))
+
+ def get_random_float():
+ assert withfloats
+ value = random.random() - 0.5
+ # make sure it fits into 64 bits
+ tmp = lltype.malloc(rffi.LONGP.TO, 2, flavor='raw')
+ rffi.cast(rffi.DOUBLEP, tmp)[0] = value
+ return rffi.cast(rffi.DOUBLEP, tmp)[0], tmp[0], tmp[1]
+
+ # memory locations: 26 integers, 26 pointers, 26 floats
+ # main registers: half of them as signed and the other half as ptrs
+ # xmm registers: all floats, from xmm0 to xmm7
+ # holes: 8
+ locations = []
+ baseloc = 4
+ for i in range(26+26+26):
+ if baseloc < 128:
+ baseloc += random.randrange(2, 20)
+ else:
+ baseloc += random.randrange(2, 1000)
+ locations.append(baseloc)
+ random.shuffle(locations)
+ content = ([('int', locations.pop()) for _ in range(26)] +
+ [('ptr', locations.pop()) for _ in range(26)] +
+ [(['int', 'ptr'][random.randrange(0, 2)], reg)
+ for reg in [eax, ecx, edx, ebx, esi, edi]])
+ if withfloats:
+ content += ([('float', locations.pop()) for _ in range(26)] +
+ [('float', reg) for reg in [xmm0, xmm1, xmm2, xmm3,
+ xmm4, xmm5, xmm6, xmm7]])
+ for i in range(8):
+ content.append(('hole', None))
+ random.shuffle(content)
+
+ # prepare the expected target arrays, the descr_bytecode,
+ # the 'registers' and the 'stack' arrays according to 'content'
+ xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+9, flavor='raw')
+ registers = rffi.ptradd(xmmregisters, 16)
+ stacklen = baseloc + 10
+ stack = lltype.malloc(rffi.LONGP.TO, stacklen, flavor='raw')
+ expected_ints = []
+ expected_ptrs = []
+ expected_floats = []
+
+ def write_in_stack(loc, value):
+ assert loc >= 0
+ ofs = get_ebp_ofs(loc)
+ assert ofs < 0
+ assert (ofs % 4) == 0
+ stack[stacklen + ofs//4] = value
+
+ descr_bytecode = []
+ for i, (kind, loc) in enumerate(content):
+ if kind == 'hole':
+ num = Assembler386.CODE_HOLE
+ else:
+ if kind == 'float':
+ value, lo, hi = get_random_float()
+ expected_floats.append(value)
+ kind = Assembler386.DESCR_FLOAT
+ if isinstance(loc, REG):
+ xmmregisters[2*loc.op] = lo
+ xmmregisters[2*loc.op+1] = hi
+ else:
+ write_in_stack(loc, hi)
+ write_in_stack(loc+1, lo)
+ else:
+ if kind == 'int':
+ value = get_random_int()
+ expected_ints.append(value)
+ kind = Assembler386.DESCR_INT
+ elif kind == 'ptr':
+ value = get_random_ptr()
+ expected_ptrs.append(value)
+ kind = Assembler386.DESCR_REF
+ value = rffi.cast(rffi.LONG, value)
+ else:
+ assert 0, kind
+ if isinstance(loc, REG):
+ registers[loc.op] = value
+ else:
+ write_in_stack(loc, value)
+
+ if isinstance(loc, REG):
+ num = kind + 4*loc.op
+ else:
+ num = kind + 4*(8+loc)
+ while num >= 0x80:
+ descr_bytecode.append((num & 0x7F) | 0x80)
+ num >>= 7
+ descr_bytecode.append(num)
+
+ descr_bytecode.append(Assembler386.CODE_STOP)
+ descr_bytecode.append(0xC3) # fail_index = 0x1C3
+ descr_bytecode.append(0x01)
+ descr_bytecode.append(0x00)
+ descr_bytecode.append(0x00)
+ descr_bytecode.append(0xCC) # end marker
+ descr_bytes = lltype.malloc(rffi.UCHARP.TO, len(descr_bytecode),
+ flavor='raw')
+ for i in range(len(descr_bytecode)):
+ assert 0 <= descr_bytecode[i] <= 255
+ descr_bytes[i] = rffi.cast(rffi.UCHAR, descr_bytecode[i])
+ registers[8] = rffi.cast(rffi.LONG, descr_bytes)
+ registers[ebp.op] = rffi.cast(rffi.LONG, stack) + 4*stacklen
+
+ # test
+ assembler = Assembler386(FakeCPU())
+ state_header = assembler.unwinder_recovery_func(registers)
+
+ if state_header.saved_ints:
+ for x,y in zip(state_header.saved_ints, expected_ints):
+ assert x == y
+
+ if state_header.saved_floats:
+ for x,y in zip(state_header.saved_floats, expected_floats):
+ assert x == y
+
+ if state_header.saved_refs:
+ for x,y in zip(state_header.saved_refs, expected_ptrs):
+ assert x == y
+
+def test_unwinder_recovery():
+ do_unwinder_recovery_func()
+
+def test_unwinder_recovery_with_floats():
+ do_unwinder_recovery_func(withfloats=True)
Modified: pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py
==============================================================================
--- pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py (original)
+++ pypy/branch/jit-stackless/pypy/jit/metainterp/test/test_jit_stackless_interop.py Mon Apr 5 18:48:39 2010
@@ -13,8 +13,8 @@
from pypy.translator.stackless.code import yield_current_frame_to_caller
from pypy.translator.translator import TranslationContext, graphof
from pypy.annotation.listdef import s_list_of_strings
+from pypy.rpython import llinterp
from pypy.translator.stackless.transform import StacklessTransformer, FrameTyper
-from pypy.translator.c.genc import CStandaloneBuilder
from pypy.translator.c import gc
from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
from pypy import conftest
@@ -57,3 +57,42 @@
return x
res = meta_interp(f, [100])
assert res == 100
+
+def rtype_stackless_function(fn):
+ t = TranslationContext()
+ t.config.translation.stackless = True
+ annotator = t.buildannotator()
+ annotator.policy.allow_someobjects = False
+
+ s_returnvar = annotator.build_types(fn, [s_list_of_strings])
+ if not isinstance(s_returnvar, annmodel.SomeInteger):
+ raise Exception, "this probably isn't going to work"
+ t.buildrtyper().specialize()
+
+ from pypy.translator.transform import insert_ll_stackcheck
+ insert_ll_stackcheck(t)
+
+# if conftest.option.view:
+# t.view()
+ return t
+
+def llinterp_stackless_function(fn, returntranslator=False,
+ assert_unwind=True):
+ def wrapper(argv):
+ return fn()
+ t = rtype_stackless_function(wrapper)
+ st = StacklessTransformer(t, wrapper, assert_unwind=assert_unwind)
+ st.transform_all()
+ if conftest.option.view:
+ t.view()
+
+ graph = graphof(t, st.slp_entry_point)
+ r_list_of_strings = t.rtyper.getrepr(
+ t.annotator.binding(graph.startblock.inputargs[0]))
+ ll_list = r_list_of_strings.convert_const([''])
+ interp = llinterp.LLInterpreter(t.rtyper)
+ res = interp.eval_graph(graph, [ll_list])
+ if returntranslator:
+ return res, t
+ else:
+ return res
More information about the Pypy-commit
mailing list