[pypy-svn] r80046 - in pypy/branch/fast-forward: . pypy/interpreter pypy/jit/backend pypy/jit/backend/llsupport pypy/jit/backend/llsupport/test pypy/jit/backend/x86 pypy/jit/backend/x86/test pypy/jit/backend/x86/tool pypy/jit/metainterp pypy/module/posix pypy/module/posix/test pypy/module/sys pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rpython/lltypesystem pypy/rpython/module pypy/translator/c/src pypy/translator/c/test
afa at codespeak.net
afa at codespeak.net
Tue Dec 14 00:05:08 CET 2010
Author: afa
Date: Tue Dec 14 00:05:06 2010
New Revision: 80046
Added:
pypy/branch/fast-forward/.hgignore
- copied unchanged from r80045, pypy/trunk/.hgignore
Modified:
pypy/branch/fast-forward/pypy/interpreter/argument.py
pypy/branch/fast-forward/pypy/jit/backend/llsupport/asmmemmgr.py
pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py
pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
pypy/branch/fast-forward/pypy/jit/backend/model.py
pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py
pypy/branch/fast-forward/pypy/jit/backend/x86/codebuf.py
pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py
pypy/branch/fast-forward/pypy/jit/backend/x86/rx86.py
pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py
pypy/branch/fast-forward/pypy/jit/backend/x86/tool/viewcode.py
pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py
pypy/branch/fast-forward/pypy/module/posix/__init__.py
pypy/branch/fast-forward/pypy/module/posix/interp_posix.py
pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py
pypy/branch/fast-forward/pypy/module/sys/__init__.py
pypy/branch/fast-forward/pypy/module/sys/version.py
pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py
pypy/branch/fast-forward/pypy/objspace/std/test/test_dictmultiobject.py
pypy/branch/fast-forward/pypy/rlib/rposix.py
pypy/branch/fast-forward/pypy/rlib/rstack.py
pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/fast-forward/pypy/rpython/module/ll_os.py
pypy/branch/fast-forward/pypy/translator/c/src/stack.h
pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py
Log:
svn merge -r80002:80045 ../trunk
Modified: pypy/branch/fast-forward/pypy/interpreter/argument.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/argument.py (original)
+++ pypy/branch/fast-forward/pypy/interpreter/argument.py Tue Dec 14 00:05:06 2010
@@ -103,9 +103,9 @@
make_sure_not_resized(self.keywords_w)
make_sure_not_resized(self.arguments_w)
- if w_stararg is not None and space.is_true(w_stararg):
+ if w_stararg is not None:
self._combine_starargs_wrapped(w_stararg)
- if w_starstararg is not None and space.is_true(w_starstararg):
+ if w_starstararg is not None:
self._combine_starstarargs_wrapped(w_starstararg)
# if we have a call where **args are used at the callsite
# we shouldn't let the JIT see the argument matching
Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/asmmemmgr.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llsupport/asmmemmgr.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/asmmemmgr.py Tue Dec 14 00:05:06 2010
@@ -2,6 +2,8 @@
from pypy.rlib.rarithmetic import intmask, r_uint, LONG_BIT
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib import rmmap
+from pypy.rlib.debug import debug_start, debug_print, debug_stop
+from pypy.rlib.debug import have_debug_prints
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
@@ -265,6 +267,31 @@
targetindex -= self.SUBBLOCK_SIZE
assert not block
+ def _dump(self, addr, logname, backend=None):
+ debug_start(logname)
+ if have_debug_prints():
+ #
+ if backend is not None:
+ debug_print('BACKEND', backend)
+ #
+ from pypy.jit.backend.hlinfo import highleveljitinfo
+ if highleveljitinfo.sys_executable:
+ debug_print('SYS_EXECUTABLE', highleveljitinfo.sys_executable)
+ #
+ HEX = '0123456789ABCDEF'
+ dump = []
+ src = rffi.cast(rffi.CCHARP, addr)
+ for p in range(self.get_relative_pos()):
+ o = ord(src[p])
+ dump.append(HEX[o >> 4])
+ dump.append(HEX[o & 15])
+ debug_print('CODE_DUMP',
+ '@%x' % addr,
+ '+0 ', # backwards compatibility
+ ''.join(dump))
+ #
+ debug_stop(logname)
+
def materialize(self, asmmemmgr, allblocks, gcrootmap=None):
size = self.get_relative_pos()
malloced = asmmemmgr.malloc(size, size)
Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/llmodel.py Tue Dec 14 00:05:06 2010
@@ -115,6 +115,7 @@
self.pos_exception = pos_exception
self.pos_exc_value = pos_exc_value
self.save_exception = save_exception
+ self.insert_stack_check = lambda: (0, 0, 0)
def _setup_exception_handling_translated(self):
@@ -138,9 +139,20 @@
# in the assignment to self.saved_exc_value, as needed.
self.saved_exc_value = exc_value
+ from pypy.rlib import rstack
+ STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed],
+ lltype.Void))
+ def insert_stack_check():
+ startaddr = rstack._stack_get_start_adr()
+ length = rstack._stack_get_length()
+ f = llhelper(STACK_CHECK_SLOWPATH, rstack.stack_check_slowpath)
+ slowpathaddr = rffi.cast(lltype.Signed, f)
+ return startaddr, length, slowpathaddr
+
self.pos_exception = pos_exception
self.pos_exc_value = pos_exc_value
self.save_exception = save_exception
+ self.insert_stack_check = insert_stack_check
def _setup_on_leave_jitted_untranslated(self):
# assume we don't need a backend leave in this case
Modified: pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_asmmemmgr.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_asmmemmgr.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/llsupport/test/test_asmmemmgr.py Tue Dec 14 00:05:06 2010
@@ -3,6 +3,7 @@
from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
from pypy.jit.backend.llsupport.asmmemmgr import BlockBuilderMixin
from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib import debug
def test_get_index():
@@ -184,9 +185,11 @@
def test_blockbuildermixin(translated=True):
mc = BlockBuilderMixin(translated)
+ writtencode = []
for i in range(mc.SUBBLOCK_SIZE * 2 + 3):
assert mc.get_relative_pos() == i
mc.writechar(chr(i % 255))
+ writtencode.append(chr(i % 255))
if translated:
assert mc._cursubindex == 3
assert mc._cursubblock
@@ -196,16 +199,26 @@
#
for i in range(0, mc.SUBBLOCK_SIZE * 2 + 3, 2):
mc.overwrite(i, chr((i + 63) % 255))
+ writtencode[i] = chr((i + 63) % 255)
#
p = lltype.malloc(rffi.CCHARP.TO, mc.SUBBLOCK_SIZE * 2 + 3, flavor='raw')
addr = rffi.cast(lltype.Signed, p)
mc.copy_to_raw_memory(addr)
#
for i in range(mc.SUBBLOCK_SIZE * 2 + 3):
- if i & 1:
- assert p[i] == chr(i % 255)
- else:
- assert p[i] == chr((i + 63) % 255)
+ assert p[i] == writtencode[i]
+ #
+ debug._log = debug.DebugLog()
+ try:
+ mc._dump(addr, 'test-logname-section')
+ log = list(debug._log)
+ finally:
+ debug._log = None
+ encoded = ''.join(writtencode).encode('hex').upper()
+ ataddr = '@%x' % addr
+ assert log == [('test-logname-section',
+ [('debug_print', 'CODE_DUMP', ataddr, '+0 ', encoded)])]
+ #
lltype.free(p, flavor='raw')
def test_blockbuildermixin2():
Modified: pypy/branch/fast-forward/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/model.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/model.py Tue Dec 14 00:05:06 2010
@@ -8,6 +8,7 @@
done_with_this_frame_int_v = -1
done_with_this_frame_ref_v = -1
done_with_this_frame_float_v = -1
+ exit_frame_with_exception_v = -1
total_compiled_loops = 0
total_compiled_bridges = 0
total_freed_loops = 0
Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/assembler.py Tue Dec 14 00:05:06 2010
@@ -84,6 +84,7 @@
self.fail_boxes_count = 0
self._current_depths_cache = (0, 0)
self.datablockwrapper = None
+ self.stack_check_slowpath_imm = imm0
self.teardown()
def leave_jitted_hook(self):
@@ -122,6 +123,7 @@
self._build_float_constants()
if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
self._build_malloc_fixedsize_slowpath()
+ self._build_stack_check_slowpath()
debug_start('jit-backend-counts')
self.set_debug(have_debug_prints())
debug_stop('jit-backend-counts')
@@ -194,6 +196,82 @@
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
self.malloc_fixedsize_slowpath2 = rawstart
+ _STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed],
+ lltype.Void))
+ def _build_stack_check_slowpath(self):
+ from pypy.rlib import rstack
+ mc = codebuf.MachineCodeBlockWrapper()
+ mc.PUSH_r(ebp.value)
+ mc.MOV_rr(ebp.value, esp.value)
+ #
+ if IS_X86_64:
+ # on the x86_64, we have to save all the registers that may
+ # have been used to pass arguments
+ for reg in [edi, esi, edx, ecx, r8, r9]:
+ mc.PUSH_r(reg.value)
+ mc.SUB_ri(esp.value, 8*8)
+ for i in range(8):
+ mc.MOVSD_sx(8*i, i) # xmm0 to xmm7
+ #
+ if IS_X86_32:
+ mc.LEA_rb(eax.value, +8)
+ mc.PUSH_r(eax.value)
+ elif IS_X86_64:
+ mc.LEA_rb(edi.value, +16)
+ mc.AND_ri(esp.value, -16)
+ #
+ f = llhelper(self._STACK_CHECK_SLOWPATH, rstack.stack_check_slowpath)
+ addr = rffi.cast(lltype.Signed, f)
+ mc.CALL(imm(addr))
+ #
+ mc.MOV(eax, heap(self.cpu.pos_exception()))
+ mc.TEST_rr(eax.value, eax.value)
+ mc.J_il8(rx86.Conditions['NZ'], 0)
+ jnz_location = mc.get_relative_pos()
+ #
+ if IS_X86_64:
+ # restore the registers
+ for i in range(7, -1, -1):
+ mc.MOVSD_xs(i, 8*i)
+ for i, reg in [(6, r9), (5, r8), (4, ecx),
+ (3, edx), (2, esi), (1, edi)]:
+ mc.MOV_rb(reg.value, -8*i)
+ #
+ mc.MOV_rr(esp.value, ebp.value)
+ mc.POP_r(ebp.value)
+ mc.RET()
+ #
+ # patch the JNZ above
+ offset = mc.get_relative_pos() - jnz_location
+ assert 0 < offset <= 127
+ mc.overwrite(jnz_location-1, chr(offset))
+ # clear the exception from the global position
+ mc.MOV(eax, heap(self.cpu.pos_exc_value()))
+ mc.MOV(heap(self.cpu.pos_exception()), imm0)
+ mc.MOV(heap(self.cpu.pos_exc_value()), imm0)
+ # save the current exception instance into fail_boxes_ptr[0]
+ adr = self.fail_boxes_ptr.get_addr_for_num(0)
+ mc.MOV(heap(adr), eax)
+ # call the helper function to set the GC flag on the fail_boxes_ptr
+ # array (note that there is no exception any more here)
+ addr = self.cpu.get_on_leave_jitted_int(save_exception=False)
+ mc.CALL(imm(addr))
+ #
+ assert self.cpu.exit_frame_with_exception_v >= 0
+ mc.MOV_ri(eax.value, self.cpu.exit_frame_with_exception_v)
+ #
+ # footer -- note the ADD, which skips the return address of this
+ # function, and will instead return to the caller's caller. Note
+ # also that we completely ignore the saved arguments, because we
+ # are interrupting the function.
+ mc.MOV_rr(esp.value, ebp.value)
+ mc.POP_r(ebp.value)
+ mc.ADD_ri(esp.value, WORD)
+ mc.RET()
+ #
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+ self.stack_check_slowpath_imm = imm(rawstart)
+
def assemble_loop(self, inputargs, operations, looptoken, log):
'''adds the following attributes to looptoken:
_x86_loop_code (an integer giving an address)
@@ -468,6 +546,24 @@
for regloc in self.cpu.CALLEE_SAVE_REGISTERS:
self.mc.PUSH_r(regloc.value)
+ def _call_header_with_stack_check(self):
+ startaddr, length, slowpathaddr = self.cpu.insert_stack_check()
+ if slowpathaddr == 0:
+ pass # no stack check (e.g. not translated)
+ else:
+ self.mc.MOV(eax, esp) # MOV eax, current
+ self.mc.SUB(eax, heap(startaddr)) # SUB eax, [startaddr]
+ self.mc.CMP(eax, imm(length)) # CMP eax, length
+ self.mc.J_il8(rx86.Conditions['B'], 0) # JB .skip
+ jb_location = self.mc.get_relative_pos()
+ self.mc.CALL(self.stack_check_slowpath_imm) # CALL slowpath
+ # patch the JB above # .skip:
+ offset = self.mc.get_relative_pos() - jb_location
+ assert 0 < offset <= 127
+ self.mc.overwrite(jb_location-1, chr(offset))
+ #
+ self._call_header()
+
def _call_footer(self):
self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD)
@@ -485,7 +581,7 @@
# XXX this can be improved greatly. Right now it'll behave like
# a normal call
nonfloatlocs, floatlocs = arglocs
- self._call_header()
+ self._call_header_with_stack_check()
self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
for i in range(len(nonfloatlocs)):
loc = nonfloatlocs[i]
@@ -526,7 +622,7 @@
unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0]
nonfloatlocs, floatlocs = arglocs
- self._call_header()
+ self._call_header_with_stack_check()
self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
# The lists are padded with Nones
Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/codebuf.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/codebuf.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/codebuf.py Tue Dec 14 00:05:06 2010
@@ -10,8 +10,10 @@
# like this
if IS_X86_32:
codebuilder_cls = X86_32_CodeBuilder
+ backend_name = 'x86'
elif IS_X86_64:
codebuilder_cls = X86_64_CodeBuilder
+ backend_name = 'x86_64'
class MachineCodeBlockWrapper(BlockBuilderMixin,
@@ -34,3 +36,4 @@
adr = rffi.cast(rffi.LONGP, p - WORD)
adr[0] = intmask(adr[0] - p)
valgrind.discard_translations(addr, self.get_relative_pos())
+ self._dump(addr, "jit-backend-dump", backend_name)
Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/regalloc.py Tue Dec 14 00:05:06 2010
@@ -101,7 +101,6 @@
return StackLoc(i, get_ebp_ofs(i), 1, box_type)
class RegAlloc(object):
- exc = False
def __init__(self, assembler, translate_support_code=False):
assert isinstance(translate_support_code, bool)
@@ -428,7 +427,10 @@
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())
- self.assembler.generate_failure(fail_index, locs, self.exc,
+ # 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)
Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/rx86.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/rx86.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/rx86.py Tue Dec 14 00:05:06 2010
@@ -347,6 +347,8 @@
INSN_rr = insn(rex_w, chr(base+1), register(2,8), register(1,1), '\xC0')
INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1))
INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2))
+ INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2))
+ INSN_rj = insn(rex_w, chr(base+3), register(1,8), '\x05', immediate(2))
INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b'))
INSN_bi32= insn(rex_w, '\x81', orbyte(base), stack_bp(1), immediate(2))
@@ -364,7 +366,7 @@
INSN_bi32(mc, offset, immed)
INSN_bi._always_inline_ = True # try to constant-fold single_byte()
- return INSN_ri, INSN_rr, INSN_rb, INSN_bi, INSN_br
+ return INSN_ri, INSN_rr, INSN_rb, INSN_bi, INSN_br, INSN_rm, INSN_rj
def select_8_or_32_bit_immed(insn_8, insn_32):
def INSN(*args):
@@ -442,24 +444,22 @@
# ------------------------------ Arithmetic ------------------------------
- ADD_ri, ADD_rr, ADD_rb, _, _ = common_modes(0)
- OR_ri, OR_rr, OR_rb, _, _ = common_modes(1)
- AND_ri, AND_rr, AND_rb, _, _ = common_modes(4)
- SUB_ri, SUB_rr, SUB_rb, _, _ = common_modes(5)
- XOR_ri, XOR_rr, XOR_rb, _, _ = common_modes(6)
- CMP_ri, CMP_rr, CMP_rb, CMP_bi, CMP_br = common_modes(7)
+ ADD_ri, ADD_rr, ADD_rb, _, _, ADD_rm, ADD_rj = common_modes(0)
+ OR_ri, OR_rr, OR_rb, _, _, OR_rm, OR_rj = common_modes(1)
+ AND_ri, AND_rr, AND_rb, _, _, AND_rm, AND_rj = common_modes(4)
+ SUB_ri, SUB_rr, SUB_rb, _, _, SUB_rm, SUB_rj = common_modes(5)
+ XOR_ri, XOR_rr, XOR_rb, _, _, XOR_rm, XOR_rj = common_modes(6)
+ CMP_ri, CMP_rr, CMP_rb, CMP_bi, CMP_br, CMP_rm, CMP_rj = common_modes(7)
CMP_mi8 = insn(rex_w, '\x83', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'b'))
CMP_mi32 = insn(rex_w, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32)
- CMP_rm = insn(rex_w, '\x3B', register(1, 8), mem_reg_plus_const(2))
CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1))
CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b'))
CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2))
CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32)
- CMP_rj = insn(rex_w, '\x3B', register(1, 8), '\x05', immediate(2))
CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/test/test_ztranslation.py Tue Dec 14 00:05:06 2010
@@ -93,6 +93,9 @@
assert res == expected
def test_direct_assembler_call_translates(self):
+ """Test CALL_ASSEMBLER and the recursion limit"""
+ from pypy.rlib.rstackovf import StackOverflow
+
class Thing(object):
def __init__(self, val):
self.val = val
@@ -135,9 +138,35 @@
i += 1
return frame.thing.val
- res = self.meta_interp(main, [0], inline=True,
+ driver2 = JitDriver(greens = [], reds = ['n'])
+
+ def main2(bound):
+ try:
+ while portal2(bound) == -bound+1:
+ bound *= 2
+ except StackOverflow:
+ pass
+ return bound
+
+ def portal2(n):
+ while True:
+ driver2.jit_merge_point(n=n)
+ n -= 1
+ if n <= 0:
+ return n
+ n = portal2(n)
+ assert portal2(10) == -9
+
+ def mainall(codeno, bound):
+ return main(codeno) + main2(bound)
+
+ res = self.meta_interp(mainall, [0, 1], inline=True,
policy=StopAtXPolicy(change))
- assert res == main(0)
+ print hex(res)
+ assert res & 255 == main(0)
+ bound = res & ~255
+ assert 1024 <= bound <= 131072
+ assert bound & (bound-1) == 0 # a power of two
class TestTranslationRemoveTypePtrX86(CCompiledMixin):
Modified: pypy/branch/fast-forward/pypy/jit/backend/x86/tool/viewcode.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/backend/x86/tool/viewcode.py (original)
+++ pypy/branch/fast-forward/pypy/jit/backend/x86/tool/viewcode.py Tue Dec 14 00:05:06 2010
@@ -1,11 +1,11 @@
#! /usr/bin/env python
"""
-Viewer for the CODE_DUMP output of compiled programs generating code.
+Viewer for the output of compiled programs generating code.
+Use on the log files created with 'PYPYLOG=jit-backend-dump:log'.
Try:
- ./viewcode.py dumpfile.txt
-or
- /tmp/usession-xxx/testing_1/testing_1 -var 4 2>&1 | ./viewcode.py
+ ./viewcode.py --text log # text only disassembly
+ ./viewcode.py log # also includes a pygame viewer
"""
import autopath
@@ -179,6 +179,7 @@
self.symbols = {}
self.logentries = {}
self.backend_name = None
+ self.executable_name = None
def parse(self, f, textonly=True):
for line in f:
@@ -214,7 +215,9 @@
self.logentries[addr] = pieces[3]
elif line.startswith('SYS_EXECUTABLE '):
filename = line[len('SYS_EXECUTABLE '):].strip()
- self.symbols.update(load_symbols(filename))
+ if filename != self.executable_name:
+ self.symbols.update(load_symbols(filename))
+ self.executable_name = filename
def find_cross_references(self):
# find cross-references between blocks
@@ -375,10 +378,19 @@
showgraph = False
else:
showgraph = True
- if len(sys.argv) == 1:
- f = sys.stdin
- else:
- f = open(sys.argv[1], 'r')
+ if len(sys.argv) != 2:
+ print >> sys.stderr, __doc__
+ sys.exit(2)
+ #
+ import cStringIO
+ from pypy.tool import logparser
+ log1 = logparser.parse_log_file(sys.argv[1])
+ text1 = logparser.extract_category(log1, catprefix='jit-backend-dump')
+ f = cStringIO.StringIO()
+ f.writelines(text1)
+ f.seek(0)
+ del log1, text1
+ #
world = World()
world.parse(f)
if showgraph:
Modified: pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/fast-forward/pypy/jit/metainterp/pyjitpl.py Tue Dec 14 00:05:06 2010
@@ -1294,6 +1294,10 @@
num = self.cpu.get_fail_descr_number(tokens[0].finishdescr)
setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num)
#
+ tokens = self.loop_tokens_exit_frame_with_exception_ref
+ num = self.cpu.get_fail_descr_number(tokens[0].finishdescr)
+ self.cpu.exit_frame_with_exception_v = num
+ #
self.globaldata = MetaInterpGlobalData(self)
def _setup_once(self):
Modified: pypy/branch/fast-forward/pypy/module/posix/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/posix/__init__.py Tue Dec 14 00:05:06 2010
@@ -71,6 +71,8 @@
if hasattr(os, 'chown'):
interpleveldefs['chown'] = 'interp_posix.chown'
+ if hasattr(os, 'lchown'):
+ interpleveldefs['lchown'] = 'interp_posix.lchown'
if hasattr(os, 'ftruncate'):
interpleveldefs['ftruncate'] = 'interp_posix.ftruncate'
if hasattr(os, 'fsync'):
@@ -86,6 +88,8 @@
if hasattr(os, 'kill') and sys.platform != 'win32':
interpleveldefs['kill'] = 'interp_posix.kill'
interpleveldefs['abort'] = 'interp_posix.abort'
+ if hasattr(os, 'killpg'):
+ interpleveldefs['killpg'] = 'interp_posix.killpg'
if hasattr(os, 'getpid'):
interpleveldefs['getpid'] = 'interp_posix.getpid'
if hasattr(os, 'link'):
@@ -117,6 +121,12 @@
interpleveldefs['ttyname'] = 'interp_posix.ttyname'
if hasattr(os, 'getloadavg'):
interpleveldefs['getloadavg'] = 'interp_posix.getloadavg'
+ if hasattr(os, 'mkfifo'):
+ interpleveldefs['mkfifo'] = 'interp_posix.mkfifo'
+ if hasattr(os, 'mknod'):
+ interpleveldefs['mknod'] = 'interp_posix.mknod'
+ if hasattr(os, 'nice'):
+ interpleveldefs['nice'] = 'interp_posix.nice'
for name in ['setsid', 'getuid', 'geteuid', 'getgid', 'getegid', 'setuid',
'seteuid', 'setgid', 'setegid', 'getpgrp', 'setpgrp',
Modified: pypy/branch/fast-forward/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/interp_posix.py (original)
+++ pypy/branch/fast-forward/pypy/module/posix/interp_posix.py Tue Dec 14 00:05:06 2010
@@ -161,6 +161,7 @@
ftruncate.unwrap_spec = [ObjSpace, "c_int", r_longlong]
def fsync(space, w_fd):
+ """Force write of file with filedescriptor to disk."""
fd = space.c_filedescriptor_w(w_fd)
try:
os.fsync(fd)
@@ -169,6 +170,8 @@
fsync.unwrap_spec = [ObjSpace, W_Root]
def fdatasync(space, w_fd):
+ """Force write of file with filedescriptor to disk.
+Does not force update of metadata."""
fd = space.c_filedescriptor_w(w_fd)
try:
os.fdatasync(fd)
@@ -177,6 +180,8 @@
fdatasync.unwrap_spec = [ObjSpace, W_Root]
def fchdir(space, w_fd):
+ """Change to the directory of the given file descriptor. fildes must be
+opened on a directory, not a file."""
fd = space.c_filedescriptor_w(w_fd)
try:
os.fchdir(fd)
@@ -557,6 +562,27 @@
raise wrap_oserror(space, e)
rename.unwrap_spec = [ObjSpace, W_Root, W_Root]
+def mkfifo(space, w_filename, mode=0666):
+ """Create a FIFO (a POSIX named pipe)."""
+ try:
+ dispatch_filename(rposix.mkfifo)(space, w_filename, mode)
+ except OSError, e:
+ raise wrap_oserror2(space, e, w_filename)
+mkfifo.unwrap_spec = [ObjSpace, W_Root, "c_int"]
+
+def mknod(space, w_filename, mode=0600, device=0):
+ """Create a filesystem node (file, device special file or named pipe)
+named filename. mode specifies both the permissions to use and the
+type of node to be created, being combined (bitwise OR) with one of
+S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,
+device defines the newly created device special file (probably using
+os.makedev()), otherwise it is ignored."""
+ try:
+ dispatch_filename(rposix.mknod)(space, w_filename, mode, device)
+ except OSError, e:
+ raise wrap_oserror2(space, e, w_filename)
+mknod.unwrap_spec = [ObjSpace, W_Root, "c_int", "c_int"]
+
def umask(space, mask):
"Set the current numeric umask and return the previous umask."
prevmask = os.umask(mask)
@@ -580,6 +606,14 @@
raise wrap_oserror(space, e)
kill.unwrap_spec = [ObjSpace, "c_int", "c_int"]
+def killpg(space, pgid, sig):
+ "Kill a process group with a signal."
+ try:
+ os.killpg(pgid, sig)
+ except OSError, e:
+ raise wrap_oserror(space, e)
+killpg.unwrap_spec = [ObjSpace, "c_int", "c_int"]
+
def abort(space):
"""Abort the interpreter immediately. This 'dumps core' or otherwise fails
in the hardest way possible on the hosting operating system."""
@@ -1034,6 +1068,14 @@
return space.w_None
chown.unwrap_spec = [ObjSpace, str, "c_nonnegint", "c_nonnegint"]
+def lchown(space, path, uid, gid):
+ try:
+ os.lchown(path, uid, gid)
+ except OSError, e:
+ raise wrap_oserror(space, e, path)
+ return space.w_None
+lchown.unwrap_spec = [ObjSpace, str, "c_nonnegint", "c_nonnegint"]
+
def getloadavg(space):
try:
load = os.getloadavg()
@@ -1045,6 +1087,15 @@
space.wrap(load[2])])
getloadavg.unwrap_spec = [ObjSpace]
+def nice(space, inc):
+ "Decrease the priority of process by inc and return the new priority."
+ try:
+ res = os.nice(inc)
+ except OSError, e:
+ raise wrap_oserror(space, e)
+ return space.wrap(res)
+nice.unwrap_spec = [ObjSpace, "c_int"]
+
if _WIN:
from pypy.rlib import rwin32
Modified: pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py (original)
+++ pypy/branch/fast-forward/pypy/module/posix/test/test_posix2.py Tue Dec 14 00:05:06 2010
@@ -672,6 +672,67 @@
f.close()
os.chown(self.path, os.getuid(), os.getgid())
+ if hasattr(os, 'lchown'):
+ def test_lchown(self):
+ os = self.posix
+ os.unlink(self.path)
+ raises(OSError, os.lchown, self.path, os.getuid(), os.getgid())
+ os.symlink('foobar', self.path)
+ os.lchown(self.path, os.getuid(), os.getgid())
+
+ if hasattr(os, 'mkfifo'):
+ def test_mkfifo(self):
+ os = self.posix
+ os.mkfifo(self.path2 + 'test_mkfifo', 0666)
+ st = os.lstat(self.path2 + 'test_mkfifo')
+ import stat
+ assert stat.S_ISFIFO(st.st_mode)
+
+ if hasattr(os, 'mknod'):
+ def test_mknod(self):
+ import stat
+ os = self.posix
+ # not very useful: os.mknod() without specifying 'mode'
+ os.mknod(self.path2 + 'test_mknod-1')
+ st = os.lstat(self.path2 + 'test_mknod-1')
+ assert stat.S_ISREG(st.st_mode)
+ # os.mknod() with S_IFIFO
+ os.mknod(self.path2 + 'test_mknod-2', 0600 | stat.S_IFIFO)
+ st = os.lstat(self.path2 + 'test_mknod-2')
+ assert stat.S_ISFIFO(st.st_mode)
+
+ def test_mknod_with_ifchr(self):
+ # os.mknod() with S_IFCHR
+ # -- usually requires root priviledges --
+ os = self.posix
+ if hasattr(os.lstat('.'), 'st_rdev'):
+ import stat
+ try:
+ os.mknod(self.path2 + 'test_mknod-3', 0600 | stat.S_IFCHR,
+ 0x105)
+ except OSError, e:
+ skip("os.mknod() with S_IFCHR: got %r" % (e,))
+ else:
+ st = os.lstat(self.path2 + 'test_mknod-3')
+ assert stat.S_ISCHR(st.st_mode)
+ assert st.st_rdev == 0x105
+
+ if hasattr(os, 'nice') and hasattr(os, 'fork') and hasattr(os, 'waitpid'):
+ def test_nice(self):
+ os = self.posix
+ myprio = os.nice(0)
+ #
+ pid = os.fork()
+ if pid == 0: # in the child
+ res = os.nice(3)
+ os._exit(res)
+ #
+ pid1, status1 = os.waitpid(pid, 0)
+ assert pid1 == pid
+ assert os.WIFEXITED(status1)
+ assert os.WEXITSTATUS(status1) == myprio + 3
+
+
class AppTestEnvironment(object):
def setup_class(cls):
cls.space = space
Modified: pypy/branch/fast-forward/pypy/module/sys/__init__.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/sys/__init__.py (original)
+++ pypy/branch/fast-forward/pypy/module/sys/__init__.py Tue Dec 14 00:05:06 2010
@@ -64,6 +64,7 @@
'pypy_version_info' : 'version.get_pypy_version_info(space)',
'pypy_svn_url' : 'version.get_svn_url(space)',
'subversion' : 'version.get_subversion_info(space)',
+ '_mercurial' : 'version.get_mercurial_info(space)',
'hexversion' : 'version.get_hexversion(space)',
'displayhook' : 'hook.displayhook',
Modified: pypy/branch/fast-forward/pypy/module/sys/version.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/sys/version.py (original)
+++ pypy/branch/fast-forward/pypy/module/sys/version.py Tue Dec 14 00:05:06 2010
@@ -98,6 +98,39 @@
space.wrap(svnbranch),
space.wrap(str(svn_revision()))])
+def get_mercurial_info(space):
+ '''Obtain Mercurial version information by invoking the 'hg' command.'''
+ # TODO: support extracting from .hg_archival.txt
+ import py
+ from subprocess import Popen, PIPE
+
+ pypyroot = os.path.abspath(os.path.join(pypydir, '..'))
+ hgexe = py.path.local.sysfind('hg')
+
+ if hgexe and os.path.isdir(os.path.join(pypyroot, '.hg')):
+ env = dict(os.environ)
+ # get Mercurial into scripting mode
+ env['HGPLAIN'] = '1'
+ # disable user configuration, extensions, etc.
+ env['HGRCPATH'] = os.devnull
+
+ p = Popen([str(hgexe), 'id', '-i', pypyroot], stdout=PIPE, env=env)
+ hgid = p.stdout.read().strip()
+
+ p = Popen([str(hgexe), 'id', '-t', pypyroot], stdout=PIPE, env=env)
+ hgtag = p.stdout.read().strip().split()[0]
+
+ if hgtag == 'tip':
+ # use the branch instead
+ p = Popen([str(hgexe), 'id', '-b', pypyroot], stdout=PIPE, env=env)
+ hgtag = p.stdout.read().strip()
+
+ return space.newtuple([space.wrap('PyPy'),
+ space.wrap(hgtag),
+ space.wrap(hgid)])
+ else:
+ return space.w_None
+
def tuple2hex(ver):
d = {'alpha': 0xA,
'beta': 0xB,
Modified: pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/dictmultiobject.py Tue Dec 14 00:05:06 2010
@@ -56,9 +56,8 @@
else:
if w_type is None:
w_type = space.w_dict
- w_self = space.allocate_instance(W_DictMultiObject, w_type)
- W_DictMultiObject.__init__(w_self, space)
- w_self.initialize_as_rdict()
+ w_self = space.allocate_instance(EmptyDictImplementation, w_type)
+ EmptyDictImplementation.__init__(w_self, space)
return w_self
def __init__(self, space):
@@ -108,7 +107,7 @@
def impl_setitem_str(self, key, w_value):
raise NotImplementedError("abstract base class")
- def impl_setitem(self, w_key, w_value):
+ def impl_setitem(self, w_key, w_value):
raise NotImplementedError("abstract base class")
def impl_delitem(self, w_key):
@@ -409,6 +408,45 @@
return self.shadowed[i]
+class EmptyDictImplementation(W_DictMultiObject):
+ def __init__(self, space):
+ self.space = space
+
+ def impl_setitem(self, w_key, w_value):
+ self._as_rdict().impl_fallback_setitem(w_key, w_value)
+
+ def impl_setitem_str(self, key, w_value):
+ self._as_rdict().impl_fallback_setitem_str(key, w_value)
+
+ def impl_delitem(self, w_key):
+ raise KeyError
+
+ def impl_length(self):
+ return 0
+
+ def impl_getitem_str(self, key):
+ return None
+
+ def impl_getitem(self, w_key):
+ # in case the key is unhashable, try to hash it
+ self.space.hash(w_key)
+ # return None anyway
+ return None
+
+ def impl_iter(self):
+ # XXX I guess it's not important to be fast in this case?
+ return self._as_rdict().impl_fallback_iter()
+
+ def impl_clear(self):
+ self.r_dict_content = None
+
+ def _as_rdict(self):
+ r_dict_content = self.initialize_as_rdict()
+ return self
+
+ def _clear_fields(self):
+ pass
+
class RDictIteratorImplementation(IteratorImplementation):
def __init__(self, space, dictimplementation):
IteratorImplementation.__init__(self, space, dictimplementation)
Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/test/test_dictmultiobject.py (original)
+++ pypy/branch/fast-forward/pypy/objspace/std/test/test_dictmultiobject.py Tue Dec 14 00:05:06 2010
@@ -16,6 +16,7 @@
space = self.space
d = self.space.newdict()
assert not self.space.is_true(d)
+ assert d.r_dict_content is None
def test_nonempty(self):
space = self.space
Modified: pypy/branch/fast-forward/pypy/rlib/rposix.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rposix.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rposix.py Tue Dec 14 00:05:06 2010
@@ -135,6 +135,20 @@
else:
return os.rmdir(path.as_bytes())
+ at specialize.argtype(0)
+def mkfifo(path, mode):
+ if isinstance(path, str):
+ os.mkfifo(path, mode)
+ else:
+ os.mkfifo(path.as_bytes(), mode)
+
+ at specialize.argtype(0)
+def mknod(path, mode, device):
+ if isinstance(path, str):
+ os.mknod(path, mode, device)
+ else:
+ os.mknod(path.as_bytes(), mode, device)
+
if os.name == 'nt':
import nt
def _getfullpathname(path):
Modified: pypy/branch/fast-forward/pypy/rlib/rstack.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rstack.py (original)
+++ pypy/branch/fast-forward/pypy/rlib/rstack.py Tue Dec 14 00:05:06 2010
@@ -6,21 +6,22 @@
import inspect
from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.rarithmetic import r_uint
+from pypy.rlib import rgc
from pypy.rpython.extregistry import ExtRegistryEntry
-from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.controllerentry import Controller, SomeControlledInstance
from pypy.translator.tool.cbuild import ExternalCompilationInfo
def stack_unwind():
if we_are_translated():
- from pypy.rpython.lltypesystem.lloperation import llop
return llop.stack_unwind(lltype.Void)
raise RuntimeError("cannot unwind stack in non-translated versions")
def stack_capture():
if we_are_translated():
- from pypy.rpython.lltypesystem.lloperation import llop
ptr = llop.stack_capture(OPAQUE_STATE_HEADER_PTR)
return frame_stack_top_controller.box(ptr)
raise RuntimeError("cannot unwind stack in non-translated versions")
@@ -28,26 +29,57 @@
def stack_frames_depth():
if we_are_translated():
- from pypy.rpython.lltypesystem.lloperation import llop
return llop.stack_frames_depth(lltype.Signed)
else:
return len(inspect.stack())
+# ____________________________________________________________
+
compilation_info = ExternalCompilationInfo(includes=['src/stack.h'])
-stack_too_big = rffi.llexternal('LL_stack_too_big', [], rffi.INT,
- compilation_info=compilation_info,
- _nowrapper=True,
- _callable=lambda: _zero,
- sandboxsafe=True)
-_zero = rffi.cast(rffi.INT, 0)
+def llexternal(name, args, res):
+ return rffi.llexternal(name, args, res, compilation_info=compilation_info,
+ sandboxsafe=True, _nowrapper=True)
+
+_stack_get_start = llexternal('LL_stack_get_start', [], lltype.Signed)
+_stack_get_length = llexternal('LL_stack_get_length', [], lltype.Signed)
+_stack_too_big_slowpath = llexternal('LL_stack_too_big_slowpath',
+ [lltype.Signed], lltype.Char)
+# the following is used by the JIT
+_stack_get_start_adr = llexternal('LL_stack_get_start_adr', [], lltype.Signed)
+
def stack_check():
- if rffi.cast(lltype.Signed, stack_too_big()):
+ if not we_are_translated():
+ return
+ #
+ # Load the "current" stack position, or at least some address that
+ # points close to the current stack head
+ current = llop.stack_current(lltype.Signed)
+ #
+ # Load these variables from C code
+ start = _stack_get_start()
+ length = _stack_get_length()
+ #
+ # Common case: if 'current' is within [start:start+length], everything
+ # is fine
+ ofs = r_uint(current - start)
+ if ofs < r_uint(length):
+ return
+ #
+ # Else call the slow path
+ stack_check_slowpath(current)
+stack_check._always_inline_ = True
+
+ at rgc.no_collect
+def stack_check_slowpath(current):
+ if ord(_stack_too_big_slowpath(current)):
+ # Now we are sure that the stack is really too big. Note that the
# stack_unwind implementation is different depending on if stackless
# is enabled. If it is it unwinds the stack, otherwise it simply
# raises a RuntimeError.
stack_unwind()
+stack_check_slowpath._dont_inline_ = True
# ____________________________________________________________
Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/lloperation.py Tue Dec 14 00:05:06 2010
@@ -528,6 +528,8 @@
'get_stack_depth_limit':LLOp(sideeffects=False),
'set_stack_depth_limit':LLOp(),
+ 'stack_current': LLOp(sideeffects=False),
+
# __________ misc operations __________
'keepalive': LLOp(),
Modified: pypy/branch/fast-forward/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/ll_os.py (original)
+++ pypy/branch/fast-forward/pypy/rpython/module/ll_os.py Tue Dec 14 00:05:06 2010
@@ -99,7 +99,7 @@
return 'll_os.ll_os_w' + name
def registering_str_unicode(posixfunc, condition=True):
- if not condition:
+ if not condition or posixfunc is None:
return registering(None, condition=False)
func_name = posixfunc.__name__
@@ -1129,6 +1129,19 @@
return extdef([str, int, int], None, "ll_os.ll_os_chown",
llimpl=os_chown_llimpl)
+ @registering_if(os, 'lchown')
+ def register_os_lchown(self):
+ os_lchown = self.llexternal('lchown',[rffi.CCHARP, rffi.INT, rffi.INT],
+ rffi.INT)
+
+ def os_lchown_llimpl(path, uid, gid):
+ res = os_lchown(path, uid, gid)
+ if res == -1:
+ raise OSError(rposix.get_errno(), "os_lchown failed")
+
+ return extdef([str, int, int], None, "ll_os.ll_os_lchown",
+ llimpl=os_lchown_llimpl)
+
@registering_if(os, 'readlink')
def register_os_readlink(self):
os_readlink = self.llexternal('readlink',
@@ -1323,6 +1336,33 @@
return extdef([traits.str, traits.str], s_None, llimpl=rename_llimpl,
export_name=traits.ll_os_name('rename'))
+ @registering_str_unicode(getattr(os, 'mkfifo', None))
+ def register_os_mkfifo(self, traits):
+ os_mkfifo = self.llexternal(traits.posix_function_name('mkfifo'),
+ [traits.CCHARP, rffi.MODE_T], rffi.INT)
+
+ def mkfifo_llimpl(path, mode):
+ res = rffi.cast(lltype.Signed, os_mkfifo(path, mode))
+ if res < 0:
+ raise OSError(rposix.get_errno(), "os_mkfifo failed")
+
+ return extdef([traits.str, int], s_None, llimpl=mkfifo_llimpl,
+ export_name=traits.ll_os_name('mkfifo'))
+
+ @registering_str_unicode(getattr(os, 'mknod', None))
+ def register_os_mknod(self, traits):
+ os_mknod = self.llexternal(traits.posix_function_name('mknod'),
+ [traits.CCHARP, rffi.MODE_T, rffi.INT],
+ rffi.INT) # xxx: actually ^^^ dev_t
+
+ def mknod_llimpl(path, mode, dev):
+ res = rffi.cast(lltype.Signed, os_mknod(path, mode, dev))
+ if res < 0:
+ raise OSError(rposix.get_errno(), "os_mknod failed")
+
+ return extdef([traits.str, int, int], s_None, llimpl=mknod_llimpl,
+ export_name=traits.ll_os_name('mknod'))
+
@registering(os.umask)
def register_os_umask(self):
os_umask = self.llexternal(underscore_on_windows+'umask', [rffi.MODE_T], rffi.MODE_T)
@@ -1348,6 +1388,20 @@
return extdef([int, int], s_None, llimpl=kill_llimpl,
export_name="ll_os.ll_os_kill")
+ @registering_if(os, 'killpg')
+ def register_os_killpg(self):
+ os_killpg = self.llexternal('killpg', [rffi.INT, rffi.INT],
+ rffi.INT)
+
+ def killpg_llimpl(pid, sig):
+ res = rffi.cast(lltype.Signed, os_killpg(rffi.cast(rffi.INT, pid),
+ rffi.cast(rffi.INT, sig)))
+ if res < 0:
+ raise OSError(rposix.get_errno(), "os_killpg failed")
+
+ return extdef([int, int], s_None, llimpl=killpg_llimpl,
+ export_name="ll_os.ll_os_killpg")
+
@registering_if(os, 'link')
def register_os_link(self):
os_link = self.llexternal('link', [rffi.CCHARP, rffi.CCHARP],
@@ -1444,6 +1498,25 @@
return extdef([int], s_None, llimpl=_exit_llimpl,
export_name="ll_os.ll_os__exit")
+ @registering_if(os, 'nice')
+ def register_os_nice(self):
+ os_nice = self.llexternal('nice', [rffi.INT], rffi.INT)
+
+ def nice_llimpl(inc):
+ # Assume that the system provides a standard-compliant version
+ # of nice() that returns the new priority. Nowadays, FreeBSD
+ # might be the last major non-compliant system (xxx check me).
+ rposix.set_errno(0)
+ res = rffi.cast(lltype.Signed, os_nice(inc))
+ if res == -1:
+ err = rposix.get_errno()
+ if err != 0:
+ raise OSError(err, "os_nice failed")
+ return res
+
+ return extdef([int], int, llimpl=nice_llimpl,
+ export_name="ll_os.ll_os_nice")
+
# --------------------------- os.stat & variants ---------------------------
@registering(os.fstat)
Modified: pypy/branch/fast-forward/pypy/translator/c/src/stack.h
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/src/stack.h (original)
+++ pypy/branch/fast-forward/pypy/translator/c/src/stack.h Tue Dec 14 00:05:06 2010
@@ -11,27 +11,17 @@
* It is needed to have RPyThreadStaticTLS, too. */
#include "thread.h"
+extern char *_LLstacktoobig_stack_start;
+
void LL_stack_unwind(void);
-int LL_stack_too_big_slowpath(void);
+char LL_stack_too_big_slowpath(long); /* returns 0 (ok) or 1 (too big) */
-extern volatile char *_LLstacktoobig_stack_base_pointer;
-extern long _LLstacktoobig_stack_min;
-extern long _LLstacktoobig_stack_max;
+/* some macros referenced from pypy.rlib.rstack */
+#define OP_STACK_CURRENT(r) r = (long)&r
+#define LL_stack_get_start() ((long)_LLstacktoobig_stack_start)
+#define LL_stack_get_length() MAX_STACK_SIZE
+#define LL_stack_get_start_adr() ((long)&_LLstacktoobig_stack_start) /* JIT */
-static int LL_stack_too_big(void)
-{
- /* The fast path of stack_too_big, called extremely often.
- Making it static makes an *inlinable* copy of this small
- function's implementation in each compilation unit. */
- char local;
- long diff = &local - _LLstacktoobig_stack_base_pointer;
- /* common case: we are still in the same thread as last time
- we checked, and still in the allowed part of the stack */
- return ((diff < _LLstacktoobig_stack_min ||
- diff > _LLstacktoobig_stack_max)
- /* if not, call the slow path */
- && LL_stack_too_big_slowpath());
-}
#ifdef __GNUC__
# define PYPY_INHIBIT_TAIL_CALL() asm("/* inhibit_tail_call */")
@@ -61,68 +51,75 @@
return &local - parent;
}
-volatile char *_LLstacktoobig_stack_base_pointer = NULL;
-long _LLstacktoobig_stack_min = 0;
-long _LLstacktoobig_stack_max = 0;
-RPyThreadStaticTLS _LLstacktoobig_stack_base_pointer_key;
+char *_LLstacktoobig_stack_start = NULL;
+int stack_direction = 0;
+RPyThreadStaticTLS start_tls_key;
-int LL_stack_too_big_slowpath(void)
+char LL_stack_too_big_slowpath(long current)
{
- char local;
long diff;
- char *baseptr;
- /* Check that the stack is less than MAX_STACK_SIZE bytes bigger
- than the value recorded in stack_base_pointer. The base
- pointer is updated to the current value if it is still NULL
- or if we later find a &local that is below it. The real
- stack base pointer is stored in thread-local storage, but we
- try to minimize its overhead by keeping a local copy in
- stack_pointer_pointer. */
+ char *baseptr, *curptr = (char*)current;
+
+ /* The stack_start variable is updated to match the current value
+ if it is still 0 or if we later find a 'curptr' position
+ that is below it. The real stack_start pointer is stored in
+ thread-local storage, but we try to minimize its overhead by
+ keeping a local copy in _LLstacktoobig_stack_start. */
- if (_LLstacktoobig_stack_min == _LLstacktoobig_stack_max /* == 0 */) {
+ if (stack_direction == 0) {
/* not initialized */
/* XXX We assume that initialization is performed early,
when there is still only one thread running. This
allows us to ignore race conditions here */
- char *errmsg = RPyThreadStaticTLS_Create(
- &_LLstacktoobig_stack_base_pointer_key);
+ char *errmsg = RPyThreadStaticTLS_Create(&start_tls_key);
if (errmsg) {
/* XXX should we exit the process? */
fprintf(stderr, "Internal PyPy error: %s\n", errmsg);
return 1;
}
if (_LL_stack_growing_direction(NULL) > 0)
- _LLstacktoobig_stack_max = MAX_STACK_SIZE;
+ stack_direction = +1;
else
- _LLstacktoobig_stack_min = -MAX_STACK_SIZE;
+ stack_direction = -1;
}
- baseptr = (char *) RPyThreadStaticTLS_Get(
- _LLstacktoobig_stack_base_pointer_key);
+ baseptr = (char *) RPyThreadStaticTLS_Get(start_tls_key);
if (baseptr != NULL) {
- diff = &local - baseptr;
- if (_LLstacktoobig_stack_min <= diff &&
- diff <= _LLstacktoobig_stack_max) {
- /* within bounds */
- _LLstacktoobig_stack_base_pointer = baseptr;
+ diff = curptr - baseptr;
+ if (((unsigned long)diff) < (unsigned long)MAX_STACK_SIZE) {
+ /* within bounds, probably just had a thread switch */
+ _LLstacktoobig_stack_start = baseptr;
return 0;
}
- if ((_LLstacktoobig_stack_min == 0 && diff < 0) ||
- (_LLstacktoobig_stack_max == 0 && diff > 0)) {
- /* we underflowed the stack, which means that
- the initial estimation of the stack base must
- be revised (see below) */
+ if (stack_direction > 0) {
+ if (diff < 0 && diff > -MAX_STACK_SIZE)
+ ; /* stack underflow */
+ else
+ return 1; /* stack overflow (probably) */
}
else {
- return 1; /* stack overflow */
+ if (diff >= MAX_STACK_SIZE && diff < 2*MAX_STACK_SIZE)
+ ; /* stack underflow */
+ else
+ return 1; /* stack overflow (probably) */
}
+ /* else we underflowed the stack, which means that
+ the initial estimation of the stack base must
+ be revised */
}
/* update the stack base pointer to the current value */
- baseptr = &local;
- RPyThreadStaticTLS_Set(_LLstacktoobig_stack_base_pointer_key, baseptr);
- _LLstacktoobig_stack_base_pointer = baseptr;
+ if (stack_direction > 0) {
+ /* the valid range is [curptr:curptr+MAX_STACK_SIZE] */
+ baseptr = curptr;
+ }
+ else {
+ /* the valid range is [curptr-MAX_STACK_SIZE+1:curptr+1] */
+ baseptr = curptr - MAX_STACK_SIZE + 1;
+ }
+ RPyThreadStaticTLS_Set(start_tls_key, baseptr);
+ _LLstacktoobig_stack_start = baseptr;
return 0;
}
Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py (original)
+++ pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py Tue Dec 14 00:05:06 2010
@@ -4,6 +4,7 @@
from pypy.tool.udir import udir
from pypy.rlib.rarithmetic import r_longlong
from pypy.translator.c.test.test_genc import compile
+from pypy.translator.c.test.test_standalone import StandaloneTests
posix = __import__(os.name)
# note: clock synchronizes itself!
@@ -404,6 +405,28 @@
assert os.path.exists(tmpfile2)
assert not os.path.exists(tmpfile1)
+if hasattr(os, 'mkfifo'):
+ def test_os_mkfifo():
+ tmpfile = str(udir.join('test_os_mkfifo.txt'))
+ def does_stuff():
+ os.mkfifo(tmpfile, 0666)
+ f1 = compile(does_stuff, [])
+ f1()
+ import stat
+ st = os.lstat(tmpfile)
+ assert stat.S_ISFIFO(st.st_mode)
+
+if hasattr(os, 'mknod'):
+ def test_os_mknod():
+ import stat
+ tmpfile = str(udir.join('test_os_mknod.txt'))
+ def does_stuff():
+ os.mknod(tmpfile, 0600 | stat.S_IFIFO, 0)
+ f1 = compile(does_stuff, [])
+ f1()
+ st = os.lstat(tmpfile)
+ assert stat.S_ISFIFO(st.st_mode)
+
def test_os_umask():
def does_stuff():
mask1 = os.umask(0660)
@@ -516,6 +539,62 @@
# for what reason do they want us to shift by 8? See the doc
assert status1 >> 8 == 4
+if hasattr(os, 'kill'):
+ def test_kill_to_send_sigusr1():
+ import signal
+ from pypy.module.signal import interp_signal
+ def does_stuff():
+ interp_signal.pypysig_setflag(signal.SIGUSR1)
+ os.kill(os.getpid(), signal.SIGUSR1)
+ interp_signal.pypysig_ignore(signal.SIGUSR1)
+ while True:
+ n = interp_signal.pypysig_poll()
+ if n < 0 or n == signal.SIGUSR1:
+ break
+ return n
+ f1 = compile(does_stuff, [])
+ got_signal = f1()
+ assert got_signal == signal.SIGUSR1
+
+if hasattr(os, 'killpg'):
+ def test_killpg():
+ import signal
+ from pypy.module.signal import interp_signal
+ def does_stuff():
+ interp_signal.pypysig_setflag(signal.SIGUSR1)
+ os.killpg(os.getpgrp(), signal.SIGUSR1)
+ interp_signal.pypysig_ignore(signal.SIGUSR1)
+ while True:
+ n = interp_signal.pypysig_poll()
+ if n < 0 or n == signal.SIGUSR1:
+ break
+ return n
+ f1 = compile(does_stuff, [])
+ got_signal = f1()
+ assert got_signal == signal.SIGUSR1
+
+if hasattr(os, 'chown') and hasattr(os, 'lchown'):
+ def test_os_chown_lchown():
+ path1 = udir.join('test_os_chown_lchown-1.txt')
+ path2 = udir.join('test_os_chown_lchown-2.txt')
+ path1.write('foobar')
+ path2.mksymlinkto('some-broken-symlink')
+ tmpfile1 = str(path1)
+ tmpfile2 = str(path2)
+ def does_stuff():
+ # xxx not really a test, just checks that they are callable
+ os.chown(tmpfile1, os.getuid(), os.getgid())
+ os.lchown(tmpfile1, os.getuid(), os.getgid())
+ os.lchown(tmpfile2, os.getuid(), os.getgid())
+ try:
+ os.chown(tmpfile2, os.getuid(), os.getgid())
+ except OSError:
+ pass
+ else:
+ raise AssertionError("os.chown(broken symlink) should raise")
+ f1 = compile(does_stuff, [])
+ f1()
+
# ____________________________________________________________
def _real_getenv(var):
@@ -783,3 +862,19 @@
finally:
os.chdir(localdir)
assert res == True
+
+# ____________________________________________________________
+
+
+class TestExtFuncStandalone(StandaloneTests):
+
+ if hasattr(os, 'nice'):
+ def test_os_nice(self):
+ def does_stuff(argv):
+ res = os.nice(3)
+ print 'os.nice returned', res
+ return 0
+ t, cbuilder = self.compile(does_stuff)
+ data = cbuilder.cmdexec('')
+ res = os.nice(0) + 3
+ assert data.startswith('os.nice returned %d\n' % res)
More information about the Pypy-commit
mailing list