[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Sat Apr 20 00:15:50 CEST 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r63514:af2904581ca4
Date: 2013-04-19 15:14 -0700
http://bitbucket.org/pypy/pypy/changeset/af2904581ca4/
Log: merge default
diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst
--- a/pypy/doc/arm.rst
+++ b/pypy/doc/arm.rst
@@ -153,7 +153,7 @@
::
- pypy <path to rpython>/rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py
+ pypy <path to rpython>/rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py
The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -43,11 +43,11 @@
Rudimentary support for bytearray in RPython
.. branch: refactor-call_release_gil
-Fix a bug which casused cffi to return the wrong result when calling a C
+Fix a bug which caused cffi to return the wrong result when calling a C
function which calls a Python callback which forces the frames
.. branch: virtual-raw-mallocs
-JIT optimizations which makes cffi calls even faster, by removing the need to
+JIT optimizations which make cffi calls even faster, by removing the need to
allocate a temporary buffer where to store the arguments.
.. branch: improve-docs-2
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -527,6 +527,7 @@
s_Int = SomeInteger()
s_ImpossibleValue = SomeImpossibleValue()
s_Str0 = SomeString(no_nul=True)
+s_Unicode0 = SomeUnicodeString(no_nul=True)
# ____________________________________________________________
diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -115,7 +115,7 @@
("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT),
("translation.list_comprehension_operations", True)]),
ChoiceOption("jit_backend", "choose the backend for the JIT",
- ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'],
+ ["auto", "x86", "x86-without-sse2", 'arm'],
default="auto", cmdline="--jit-backend"),
ChoiceOption("jit_profiler", "integrate profiler support into the JIT",
["off", "oprofile"],
diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -25,7 +25,6 @@
from rpython.rlib.rarithmetic import r_uint
from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref
from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.jit.backend.arm.detect import detect_hardfloat
class AssemblerARM(ResOpAssembler):
@@ -51,14 +50,13 @@
def setup_once(self):
BaseAssembler.setup_once(self)
- self.hf_abi = detect_hardfloat()
def setup(self, looptoken):
assert self.memcpy_addr != 0, 'setup_once() not called?'
if we_are_translated():
self.debug = False
self.current_clt = looptoken.compiled_loop_token
- self.mc = InstrBuilder(self.cpu.arch_version)
+ self.mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
self.pending_guards = []
assert self.datablockwrapper is None
allblocks = self.get_asmmemmgr_blocks(looptoken)
@@ -82,7 +80,7 @@
if not self.cpu.propagate_exception_descr:
return # not supported (for tests, or non-translated)
#
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
self._store_and_reset_exception(mc, r.r0)
ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
# make sure ofs fits into a register
@@ -167,7 +165,7 @@
# | my own retaddr | <-- sp
# +-----------------------+
#
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
# save argument registers and return address
mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value])
# stack is aligned here
@@ -208,7 +206,7 @@
# write barriers. It must save all registers, and optionally
# all vfp registers. It takes a single argument which is in r0.
# It must keep stack alignment accordingly.
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
#
exc0 = exc1 = None
mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment
@@ -251,8 +249,10 @@
else:
self.wb_slowpath[withcards + 2 * withfloats] = rawstart
- def _build_malloc_slowpath(self):
- mc = InstrBuilder(self.cpu.arch_version)
+ def _build_malloc_slowpath(self, kind):
+ if kind != 'fixed':
+ return 0
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats)
ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
# store the gc pattern
@@ -289,9 +289,7 @@
self.store_reg(mc, r.ip, r.fp, ofs)
# return
mc.POP([r.ip.value, r.pc.value])
-
- rawstart = mc.materialize(self.cpu.asmmemmgr, [])
- self.malloc_slowpath = rawstart
+ return mc.materialize(self.cpu.asmmemmgr, [])
def _reload_frame_if_necessary(self, mc):
gcrootmap = self.cpu.gc_ll_descr.gcrootmap
@@ -364,7 +362,7 @@
self.load_reg(mc, vfpr, r.fp, ofs)
def _build_failure_recovery(self, exc, withfloats=False):
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
self._push_all_regs_to_jitframe(mc, [], withfloats)
if exc:
@@ -647,7 +645,7 @@
expected_size=expected_size)
def _patch_frame_depth(self, adr, allocated_depth):
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
mc.gen_load_int(r.lr.value, allocated_depth)
mc.copy_to_raw_memory(adr)
@@ -723,7 +721,7 @@
# f) store the address of the new jitframe in the shadowstack
# c) set the gcmap field to 0 in the new jitframe
# g) restore registers and return
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats)
# this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame
# and the expected_size pushed in _check_stack_frame
@@ -783,7 +781,7 @@
self.target_tokens_currently_compiling = None
def _patch_stackadjust(self, adr, allocated_depth):
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
mc.gen_load_int(r.lr.value, allocated_depth)
mc.copy_to_raw_memory(adr)
@@ -823,7 +821,7 @@
# patch the guard jumpt to the stub
# overwrite the generate NOP with a B_offs to the pos of the
# stub
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond))
mc.copy_to_raw_memory(guard_pos)
else:
@@ -902,7 +900,7 @@
self.mc.ASR_ri(resloc.value, resloc.value, 16)
def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc):
- b = InstrBuilder(self.cpu.arch_version)
+ b = InstrBuilder(self.cpu.cpuinfo.arch_version)
patch_addr = faildescr._arm_failure_recovery_block
assert patch_addr != 0
b.B(bridge_addr)
diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py
--- a/rpython/jit/backend/arm/detect.py
+++ b/rpython/jit/backend/arm/detect.py
@@ -1,7 +1,10 @@
+import os
+
from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rtyper.tool import rffi_platform
from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP
-from rpython.rtyper.tool import rffi_platform
from rpython.translator.platform import CompilationError
+from rpython.rlib.debug import debug_print, debug_start, debug_stop
eci = ExternalCompilationInfo(
post_include_bits=["""
@@ -26,3 +29,37 @@
return True
except CompilationError:
return False
+
+
+def detect_arch_version(filename="/proc/cpuinfo"):
+ fd = os.open(filename, os.O_RDONLY, 0644)
+ n = 0
+ debug_start("jit-backend-arch")
+ try:
+ buf = os.read(fd, 2048)
+ if not buf:
+ debug_print("Could not detect ARM architecture "
+ "version, assuming", "ARMv%d" % n)
+ n = 6 # we asume ARMv6 as base case
+ finally:
+ os.close(fd)
+ # "Processor : ARMv%d-compatible processor rev 7 (v6l)"
+ i = buf.find('ARMv')
+ if i == -1:
+ n = 6
+ debug_print("Could not detect architecture version, "
+ "falling back to", "ARMv%d" % n)
+ else:
+ n = int(buf[i + 4])
+
+ if n < 6:
+ raise ValueError("Unsupported ARM architecture version")
+
+ debug_print("Detected", "ARMv%d" % n)
+
+ if n > 7:
+ n = 7
+ debug_print("Architecture version not explicitly supported, "
+ "falling back to", "ARMv%d" % n)
+ debug_stop("jit-backend-arch")
+ return n
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
@@ -354,7 +354,7 @@
# whether to worry about a CALL that can collect; this
# is always true except in call_release_gil
can_collect=True):
- if self.hf_abi:
+ if self.cpu.cpuinfo.hf_abi:
stack_args, adr = self._setup_call_hf(adr, arglocs, fcond,
resloc, result_info)
else:
@@ -382,7 +382,7 @@
# ensure the result is wellformed and stored in the correct location
if resloc is not None:
- if resloc.is_vfp_reg() and not self.hf_abi:
+ if resloc.is_vfp_reg() and not self.cpu.cpuinfo.hf_abi:
# move result to the allocated register
self.mov_to_vfp_loc(r.r0, r.r1, resloc)
elif resloc.is_reg() and result_info != (-1, -1):
@@ -1230,7 +1230,7 @@
baseofs = self.cpu.get_baseofs_of_frame_field()
newlooptoken.compiled_loop_token.update_frame_info(
oldlooptoken.compiled_loop_token, baseofs)
- mc = InstrBuilder(self.cpu.arch_version)
+ mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
mc.B(target)
mc.copy_to_raw_memory(oldadr)
diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py
--- a/rpython/jit/backend/arm/runner.py
+++ b/rpython/jit/backend/arm/runner.py
@@ -7,9 +7,14 @@
from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.jit.backend.arm.detect import detect_hardfloat
+from rpython.jit.backend.arm.detect import detect_arch_version
jitframe.STATICSIZE = JITFRAME_FIXED_SIZE
+class CPUInfo(object):
+ hf_abi = False
+ arch_version = 6
+
class AbstractARMCPU(AbstractLLCPU):
IS_64_BIT = False
@@ -25,13 +30,11 @@
float_regs = VFPRegisterManager.all_regs
frame_reg = fp
- hf_abi = False # use hard float abi flag
- arch_version = 7
-
def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
gcdescr=None):
AbstractLLCPU.__init__(self, rtyper, stats, opts,
translate_support_code, gcdescr)
+ self.cpuinfo = CPUInfo()
def set_debug(self, flag):
return self.assembler.set_debug(flag)
@@ -46,6 +49,8 @@
self.assembler = AssemblerARM(self, self.translate_support_code)
def setup_once(self):
+ self.cpuinfo.arch_version = detect_arch_version()
+ self.cpuinfo.hf_abi = detect_hardfloat()
self.assembler.setup_once()
def finish_once(self):
@@ -89,7 +94,7 @@
from rpython.jit.backend.arm.codebuilder import InstrBuilder
for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions:
- mc = InstrBuilder(self.arch_version)
+ mc = InstrBuilder(self.cpuinfo.arch_version)
mc.B_offs(tgt)
mc.copy_to_raw_memory(jmp)
# positions invalidated
@@ -113,10 +118,5 @@
class CPU_ARM(AbstractARMCPU):
- """ARM v7"""
- backend_name = "armv7"
-
-class CPU_ARMv6(AbstractARMCPU):
- """ ARM v6, uses hardfp ABI, requires vfp"""
- arch_version = 6
- backend_name = "armv6"
+ """ARM"""
+ backend_name = "arm"
diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/arm/test/test_detect.py
@@ -0,0 +1,48 @@
+import py
+from rpython.tool.udir import udir
+from rpython.jit.backend.arm.detect import detect_arch_version
+
+cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)"""
+cpuinfo2 = """processor : 0
+vendor_id : GenuineIntel
+cpu family : 6
+model : 23
+model name : Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz
+stepping : 10
+microcode : 0xa07
+cpu MHz : 2997.000
+cache size : 6144 KB
+physical id : 0
+siblings : 2
+core id : 0
+cpu cores : 2
+apicid : 0
+initial apicid : 0
+fpu : yes
+fpu_exception : yes
+cpuid level : 13
+wp : yes
+flags : fpu vme ...
+bogomips : 5993.08
+clflush size : 64
+cache_alignment : 64
+address sizes : 36 bits physical, 48 bits virtual
+power management:
+"""
+
+def write_cpuinfo(info):
+ filepath = udir.join('get_arch_version')
+ filepath.write(info)
+ return str(filepath)
+
+
+def test_detect_arch_version():
+ # currently supported cases
+ for i in (6, 7, ):
+ filepath = write_cpuinfo(cpuinfo % i)
+ assert detect_arch_version(filepath) == i
+ # unsupported cases
+ assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7
+ py.test.raises(ValueError,
+ 'detect_arch_version(write_cpuinfo(cpuinfo % 5))')
+ assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6
diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py
--- a/rpython/jit/backend/arm/test/test_runner.py
+++ b/rpython/jit/backend/arm/test/test_runner.py
@@ -10,6 +10,7 @@
from rpython.rtyper.annlowlevel import llhelper
from rpython.jit.codewriter.effectinfo import EffectInfo
from rpython.jit.metainterp.history import JitCellToken, TargetToken
+from rpython.jit.backend.arm.detect import detect_arch_version
CPU = getcpuclass()
@@ -27,7 +28,8 @@
bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge',
'push', 'mov', 'mov', 'push', 'mov', 'mov',
'blx', 'mov', 'mov', 'bx']
- if CPU.backend_name.startswith('armv7'):
+ arch_version = detect_arch_version()
+ if arch_version == 7:
bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge',
'push', 'mov', 'mov', 'push', 'mov', 'mov',
'blx', 'mov', 'mov', 'bx']
diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py
--- a/rpython/jit/backend/detect_cpu.py
+++ b/rpython/jit/backend/detect_cpu.py
@@ -33,8 +33,8 @@
'x86_64': 'x86',
'amd64': 'x86', # freebsd
'AMD64': 'x86', # win64
- 'armv7l': 'armv7',
- 'armv6l': 'armv6',
+ 'armv7l': 'arm',
+ 'armv6l': 'arm',
}[mach]
except KeyError:
return mach
@@ -75,9 +75,7 @@
return "rpython.jit.backend.x86.runner", "CPU_X86_64"
elif backend_name == 'cli':
return "rpython.jit.backend.cli.runner", "CliCPU"
- elif backend_name.startswith('armv6'):
- return "rpython.jit.backend.arm.runner", "CPU_ARMv6"
- elif backend_name.startswith('armv7'):
+ elif backend_name.startswith('arm'):
return "rpython.jit.backend.arm.runner", "CPU_ARM"
else:
raise ProcessorAutodetectError, (
diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -1057,6 +1057,28 @@
r = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 4, vsdescr)
assert r == 4
+ def test_array_of_structs_all_sizes(self):
+ # x86 has special support that can be used for sizes
+ # 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 16, 18, 20, 24, 32, 36, 40, 64, 72
+ for length in range(1, 75):
+ ITEM = lltype.FixedSizeArray(lltype.Char, length)
+ a_box, A = self.alloc_array_of(ITEM, 5)
+ a = a_box.getref(lltype.Ptr(A))
+ middle = length // 2
+ a[3][middle] = chr(65 + length)
+ fdescr = self.cpu.interiorfielddescrof(A, 'item%d' % middle)
+ r = self.execute_operation(rop.GETINTERIORFIELD_GC,
+ [a_box, BoxInt(3)],
+ 'int', descr=fdescr)
+ r = r.getint()
+ assert r == 65 + length
+ self.execute_operation(rop.SETINTERIORFIELD_GC,
+ [a_box, BoxInt(2), BoxInt(r + 1)],
+ 'void', descr=fdescr)
+ r1 = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 2,
+ fdescr)
+ assert r1 == r + 1
+
def test_string_basic(self):
s_box = self.alloc_string("hello\xfe")
r = self.execute_operation(rop.STRLEN, [s_box], 'int')
@@ -3913,3 +3935,19 @@
descr = self.cpu.get_latest_descr(frame)
assert descr.identifier == 42
assert not self.cpu.grab_exc_value(frame)
+
+ def test_setarrayitem_raw_short(self):
+ # setarrayitem_raw(140737353744432, 0, 30583, descr=<ArrayS 2>)
+ A = rffi.CArray(rffi.SHORT)
+ arraydescr = self.cpu.arraydescrof(A)
+ a = lltype.malloc(A, 2, flavor='raw')
+ a[0] = rffi.cast(rffi.SHORT, 666)
+ a[1] = rffi.cast(rffi.SHORT, 777)
+ a_int = rffi.cast(lltype.Signed, a)
+ print 'a_int:', a_int
+ self.execute_operation(rop.SETARRAYITEM_RAW,
+ [ConstInt(a_int), ConstInt(0), ConstInt(-7654)],
+ 'void', descr=arraydescr)
+ assert rffi.cast(lltype.Signed, a[0]) == -7654
+ assert rffi.cast(lltype.Signed, a[1]) == 777
+ lltype.free(a, flavor='raw')
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
@@ -1537,22 +1537,50 @@
src_addr = addr_add(base_loc, ofs_loc, ofs.value, 0)
self.load_from_mem(resloc, src_addr, size_loc, sign_loc)
+ def _imul_const_scaled(self, mc, targetreg, sourcereg, itemsize):
+ """Produce one operation to do roughly
+ targetreg = sourcereg * itemsize
+ except that the targetreg may still need shifting by 0,1,2,3.
+ """
+ if (itemsize & 7) == 0:
+ shift = 3
+ elif (itemsize & 3) == 0:
+ shift = 2
+ elif (itemsize & 1) == 0:
+ shift = 1
+ else:
+ shift = 0
+ itemsize >>= shift
+ #
+ if _valid_addressing_size(itemsize - 1):
+ mc.LEA_ra(targetreg, (sourcereg, sourcereg,
+ _get_scale(itemsize - 1), 0))
+ elif _valid_addressing_size(itemsize):
+ mc.LEA_ra(targetreg, (rx86.NO_BASE_REGISTER, sourcereg,
+ _get_scale(itemsize), 0))
+ else:
+ mc.IMUL_rri(targetreg, sourcereg, itemsize)
+ #
+ return shift
+
def _get_interiorfield_addr(self, temp_loc, index_loc, itemsize_loc,
base_loc, ofs_loc):
assert isinstance(itemsize_loc, ImmedLoc)
+ itemsize = itemsize_loc.value
if isinstance(index_loc, ImmedLoc):
- temp_loc = imm(index_loc.value * itemsize_loc.value)
- elif _valid_addressing_size(itemsize_loc.value):
- return AddressLoc(base_loc, index_loc, _get_scale(itemsize_loc.value), ofs_loc.value)
+ temp_loc = imm(index_loc.value * itemsize)
+ shift = 0
+ elif _valid_addressing_size(itemsize):
+ temp_loc = index_loc
+ shift = _get_scale(itemsize)
else:
- # XXX should not use IMUL in more cases, it can use a clever LEA
+ assert isinstance(index_loc, RegLoc)
assert isinstance(temp_loc, RegLoc)
- assert isinstance(index_loc, RegLoc)
assert not temp_loc.is_xmm
- self.mc.IMUL_rri(temp_loc.value, index_loc.value,
- itemsize_loc.value)
+ shift = self._imul_const_scaled(self.mc, temp_loc.value,
+ index_loc.value, itemsize)
assert isinstance(ofs_loc, ImmedLoc)
- return AddressLoc(base_loc, temp_loc, 0, ofs_loc.value)
+ return AddressLoc(base_loc, temp_loc, shift, ofs_loc.value)
def genop_getinteriorfield_gc(self, op, arglocs, resloc):
(base_loc, ofs_loc, itemsize_loc, fieldsize_loc,
@@ -2415,11 +2443,12 @@
jmp_adr0 = self.mc.get_relative_pos()
self.mc.MOV(eax, heap(nursery_free_adr))
- shift = size2shift(itemsize)
- if shift < 0:
- self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize)
+ if _valid_addressing_size(itemsize):
+ shift = _get_scale(itemsize)
+ else:
+ shift = self._imul_const_scaled(self.mc, edi.value,
+ varsizeloc.value, itemsize)
varsizeloc = edi
- shift = 0
# now varsizeloc is a register != eax. The size of
# the variable part of the array is (varsizeloc << shift)
assert arraydescr.basesize >= self.gc_minimal_size_in_nursery
@@ -2523,13 +2552,5 @@
os.write(2, '[x86/asm] %s\n' % msg)
raise NotImplementedError(msg)
-def size2shift(size):
- "Return a result 0..3 such that (1<<result) == size, or -1 if impossible"
- if size == 1: return 0
- if size == 2: return 1
- if size == 4: return 2
- if size == 8: return 3
- return -1
-
class BridgeAlreadyCompiled(Exception):
pass
diff --git a/rpython/jit/backend/x86/regloc.py b/rpython/jit/backend/x86/regloc.py
--- a/rpython/jit/backend/x86/regloc.py
+++ b/rpython/jit/backend/x86/regloc.py
@@ -521,17 +521,6 @@
return func_with_new_name(INSN, "INSN_" + name)
- def _16_bit_binaryop(name):
- def INSN(self, loc1, loc2):
- # Select 16-bit operand mode
- self.writechar('\x66')
- # XXX: Hack to let immediate() in rx86 know to do a 16-bit encoding
- self._use_16_bit_immediate = True
- getattr(self, name)(loc1, loc2)
- self._use_16_bit_immediate = False
-
- return INSN
-
def _addr_as_reg_offset(self, addr):
# Encodes a (64-bit) address as an offset from the scratch register.
# If we are within a "reuse_scratch_register" block, we remember the
@@ -616,10 +605,10 @@
NEG = _unaryop('NEG')
CMP = _binaryop('CMP')
- CMP16 = _16_bit_binaryop('CMP')
+ CMP16 = _binaryop('CMP16')
MOV = _binaryop('MOV')
MOV8 = _binaryop('MOV8')
- MOV16 = _16_bit_binaryop('MOV')
+ MOV16 = _binaryop('MOV16')
MOVZX8 = _binaryop('MOVZX8')
MOVSX8 = _binaryop('MOVSX8')
MOVZX16 = _binaryop('MOVZX16')
diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py
--- a/rpython/jit/backend/x86/rx86.py
+++ b/rpython/jit/backend/x86/rx86.py
@@ -125,10 +125,7 @@
elif width == 'q' and mc.WORD == 8:
mc.writeimm64(immediate)
else:
- if mc._use_16_bit_immediate:
- mc.writeimm16(immediate)
- else:
- mc.writeimm32(immediate)
+ mc.writeimm32(immediate)
return 0
def immediate(argnum, width='i'):
@@ -282,16 +279,20 @@
# (the immediate address itself must be explicitely encoded as well,
# with immediate(argnum)).
-def encode_abs(mc, _1, _2, orbyte):
+ at specialize.arg(2)
+def encode_abs(mc, immediate, _, orbyte):
# expands to either '\x05' on 32-bit, or '\x04\x25' on 64-bit
if mc.WORD == 8:
mc.writechar(chr(0x04 | orbyte))
mc.writechar(chr(0x25))
else:
mc.writechar(chr(0x05 | orbyte))
+ # followed by an immediate, always 32 bits
+ mc.writeimm32(immediate)
return 0
-abs_ = encode_abs, 0, None, None
+def abs_(argnum):
+ return encode_abs, argnum, None, None
# ____________________________________________________________
# For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes
@@ -305,9 +306,6 @@
def encode_rex(mc, rexbyte, basevalue, orbyte):
if mc.WORD == 8:
assert 0 <= rexbyte < 8
- # XXX: Hack. Ignore REX.W if we are using 16-bit operands
- if mc._use_16_bit_immediate:
- basevalue &= ~REX_W
if basevalue != 0 or rexbyte != 0:
if basevalue == 0:
basevalue = 0x40
@@ -374,9 +372,8 @@
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), abs_, immediate(2))
- INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1),
- immediate(2,'b'))
+ INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_(2))
+ INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_(1), immediate(2,'b'))
INSN_mi8 = insn(rex_w, '\x83', orbyte(base), mem_reg_plus_const(1),
immediate(2,'b'))
INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b'))
@@ -449,9 +446,6 @@
class AbstractX86CodeBuilder(object):
"""Abstract base class."""
- # Used by the 16-bit version of instructions
- _use_16_bit_immediate = False
-
def writechar(self, char):
raise NotImplementedError
@@ -489,15 +483,13 @@
CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32)
CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1))
- CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_,
- immediate(1), immediate(2, 'b'))
- CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_,
- immediate(1), immediate(2))
+ CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_(1), immediate(2, 'b'))
+ CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_(1), immediate(2))
CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32)
- CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1))
+ CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_(1))
CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
-
+ CMP16_mi = insn('\x66', rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'h'))
CMP8_ri = insn(rex_fw, '\x80', byte_register(1), '\xF8', immediate(2, 'b'))
AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0')
@@ -505,7 +497,7 @@
OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0')
OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1),
immediate(2, 'b'))
- OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1),
+ OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_(1),
immediate(2, 'b'))
NEG_r = insn(rex_w, '\xF7', register(1), '\xD8')
@@ -556,7 +548,7 @@
LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True))
LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2))
LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2))
- LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2))
+ LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_(2))
CALL_l = insn('\xE8', relative(1))
CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3)))
@@ -583,11 +575,11 @@
TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b'))
TEST8_bi = insn(rex_nw, '\xF6', orbyte(0<<3), stack_bp(1), immediate(2, 'b'))
- TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b'))
+ TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_(1), immediate(2, 'b'))
TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1))
- BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_, immediate(1))
+ BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_(1))
# x87 instructions
FSTPL_b = insn('\xDD', orbyte(3<<3), stack_bp(1)) # rffi.DOUBLE ('as' wants L??)
@@ -718,7 +710,7 @@
add_insn('s', stack_sp(modrm_argnum))
add_insn('m', mem_reg_plus_const(modrm_argnum))
add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum))
- add_insn('j', abs_, immediate(modrm_argnum))
+ add_insn('j', abs_(modrm_argnum))
# Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a
# register
@@ -729,6 +721,8 @@
define_modrm_modes('MOV8_*r', [rex_fw, '\x88', byte_register(2, 8)], regtype='BYTE')
define_modrm_modes('MOV8_*i', [rex_fw, '\xC6', orbyte(0<<3)], [immediate(2, 'b')], regtype='BYTE')
+define_modrm_modes('MOV16_*r', ['\x66', rex_nw, '\x89', register(2, 8)])
+define_modrm_modes('MOV16_*i', ['\x66', rex_nw, '\xC7', orbyte(0<<3)], [immediate(2, 'h')])
define_modrm_modes('MOVZX8_r*', [rex_w, '\x0F\xB6', register(1, 8)], regtype='BYTE')
define_modrm_modes('MOVSX8_r*', [rex_w, '\x0F\xBE', register(1, 8)], regtype='BYTE')
@@ -766,7 +760,7 @@
#
assert insnname_template.count('*') == 1
add_insn('x', register(2), '\xC0')
- add_insn('j', abs_, immediate(2))
+ add_insn('j', abs_(2))
add_insn('m', mem_reg_plus_const(2))
define_pxmm_insn('PADDQ_x*', '\xD4')
diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py
--- a/rpython/memory/gc/env.py
+++ b/rpython/memory/gc/env.py
@@ -149,6 +149,10 @@
else:
data = ''.join(data)
linepos = 0
+ # Currently on ARM-linux we won't find any information about caches in
+ # cpuinfo
+ if _detect_arm_cpu(data):
+ return -1
while True:
start = _findend(data, '\ncache size', linepos)
if start < 0:
@@ -201,6 +205,11 @@
pos += 1
return pos
+def _detect_arm_cpu(data):
+ # check for the presence of a 'Processor' entry
+ p = _findend(data, 'Processor', 0)
+ return p >= 0 and _findend(data, 'ARMv', p) > 0
+
# ---------- Darwin ----------
sysctlbyname = rffi.llexternal('sysctlbyname',
@@ -270,7 +279,7 @@
def best_nursery_size_for_L2cache(L2cache):
# Heuristically, the best nursery size to choose is about half
# of the L2 cache.
- if L2cache > 1024 * 1024: # we don't want to have nursery estimated
+ if L2cache > 2 * 1024 * 1024: # we don't want to have nursery estimated
# on L2 when L3 is present
return L2cache // 2
else:
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -130,6 +130,7 @@
FORWARDSTUB = lltype.GcStruct('forwarding_stub',
('forw', llmemory.Address))
FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB)
+NURSARRAY = lltype.Array(llmemory.Address)
# ____________________________________________________________
@@ -263,7 +264,7 @@
self.nursery_top = NULL
self.nursery_real_top = NULL
self.debug_tiny_nursery = -1
- self.debug_rotating_nurseries = None
+ self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY)
self.extra_threshold = 0
#
# The ArenaCollection() handles the nonmovable objects allocation.
@@ -350,8 +351,6 @@
# hacking at the current nursery position in collect_and_reserve().
if newsize <= 0:
newsize = env.estimate_best_nursery_size()
- # 4*1024*1024 # fixed to 4MB by default
- # (it was env.estimate_best_nursery_size())
if newsize <= 0:
newsize = defaultsize
if newsize < minsize:
@@ -471,23 +470,32 @@
# and use them alternatively, while mprotect()ing the unused
# ones to detect invalid access.
debug_start("gc-debug")
- self.debug_rotating_nurseries = []
- for i in range(22):
+ self.debug_rotating_nurseries = lltype.malloc(
+ NURSARRAY, 22, flavor='raw', track_allocation=False)
+ i = 0
+ while i < 22:
nurs = self._alloc_nursery()
llarena.arena_protect(nurs, self._nursery_memory_size(), True)
- self.debug_rotating_nurseries.append(nurs)
+ self.debug_rotating_nurseries[i] = nurs
+ i += 1
debug_print("allocated", len(self.debug_rotating_nurseries),
"extra nurseries")
debug_stop("gc-debug")
def debug_rotate_nursery(self):
- if self.debug_rotating_nurseries is not None:
+ if self.debug_rotating_nurseries:
debug_start("gc-debug")
oldnurs = self.nursery
llarena.arena_protect(oldnurs, self._nursery_memory_size(), True)
- self.debug_rotating_nurseries.append(oldnurs)
#
- newnurs = self.debug_rotating_nurseries.pop(0)
+ newnurs = self.debug_rotating_nurseries[0]
+ i = 0
+ while i < len(self.debug_rotating_nurseries) - 1:
+ self.debug_rotating_nurseries[i] = (
+ self.debug_rotating_nurseries[i + 1])
+ i += 1
+ self.debug_rotating_nurseries[i] = oldnurs
+ #
llarena.arena_protect(newnurs, self._nursery_memory_size(), False)
self.nursery = newnurs
self.nursery_top = self.nursery + self.initial_cleanup
diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py
--- a/rpython/memory/gc/test/test_env.py
+++ b/rpython/memory/gc/test/test_env.py
@@ -161,3 +161,23 @@
""")
result = env.get_L2cache_linux2(str(filepath))
assert result == 3072 * 1024
+
+def test_estimate_best_nursery_size_linux2_arm():
+ filepath = udir.join('estimate_best_nursery_size_linux2')
+ filepath.write("""\
+Processor : ARMv6-compatible processor rev 7 (v6l)
+# this is not actually from cpuinfo, but here for the test
+cache size : 3072 KB
+...
+""")
+ result = env.get_L2cache_linux2(str(filepath))
+ assert result == -1
+
+def test__detect_arm():
+ assert env._detect_arm_cpu("Processor : ARMv6-compatible processor rev 7 (v6l)")
+ assert not env._detect_arm_cpu("""\
+processor : 0
+vendor_id : GenuineIntel
+cpu family : 6
+model : 37
+""")
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -619,6 +619,12 @@
func = getattr(graph, 'func', None)
if func and getattr(func, '_gc_no_collect_', False):
if self.collect_analyzer.analyze_direct_call(graph):
+ print '!'*79
+ ca = CollectAnalyzer(self.translator)
+ ca.verbose = True
+ ca.analyze_direct_call(graph)
+ # ^^^ for the dump of which operation in which graph actually
+ # causes it to return True
raise Exception("'no_collect' function can trigger collection:"
" %s" % func)
diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py
--- a/rpython/rlib/rwin32.py
+++ b/rpython/rlib/rwin32.py
@@ -5,6 +5,7 @@
import os
import errno
+from rpython.rtyper.module.ll_os_environ import make_env_impls
from rpython.rtyper.tool import rffi_platform
from rpython.tool.udir import udir
from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -390,3 +391,5 @@
raise lastWindowsError('os_kill failed to terminate process')
finally:
CloseHandle(handle)
+
+ _wenviron_items, _wgetenv, _wputenv = make_env_impls(win32=True)
diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py
--- a/rpython/rlib/test/test_rwin32.py
+++ b/rpython/rlib/test/test_rwin32.py
@@ -1,3 +1,4 @@
+# encoding: utf-8
import os, py
if os.name != 'nt':
py.test.skip('tests for win32 only')
@@ -47,3 +48,13 @@
rwin32.CloseHandle(handle)
assert proc.wait() == signal.SIGTERM
+ at py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive')
+def test_wenviron():
+ name, value = u'PYPY_TEST_日本', u'foobar日本'
+ rwin32._wputenv(name, value)
+ assert rwin32._wgetenv(name) == value
+ env = dict(rwin32._wenviron_items())
+ assert env[name] == value
+ for key, value in env.iteritems():
+ assert type(key) is unicode
+ assert type(value) is unicode
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -7,14 +7,15 @@
import os, sys, errno
import py
-from rpython.rtyper.module.support import OOSupport
+from rpython.rtyper.module.support import (
+ _WIN32, OOSupport, StringTraits, UnicodeTraits, underscore_on_windows)
from rpython.tool.sourcetools import func_renamer
from rpython.rlib.rarithmetic import r_longlong
from rpython.rtyper.extfunc import (
BaseLazyRegistering, register_external)
from rpython.rtyper.extfunc import registering, registering_if, extdef
from rpython.annotator.model import (
- SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString)
+ SomeInteger, SomeString, SomeTuple, SomeFloat, s_Str0, s_Unicode0)
from rpython.annotator.model import s_ImpossibleValue, s_None, s_Bool
from rpython.rtyper.lltypesystem import rffi
from rpython.rtyper.lltypesystem import lltype
@@ -25,8 +26,8 @@
from rpython.rtyper.lltypesystem.rstr import STR
from rpython.rlib.objectmodel import specialize
-str0 = SomeString(no_nul=True)
-unicode0 = SomeUnicodeString(no_nul=True)
+str0 = s_Str0
+unicode0 = s_Unicode0
def monkeypatch_rposix(posixfunc, unicodefunc, signature):
func_name = posixfunc.__name__
@@ -66,42 +67,6 @@
# Monkeypatch the function in rpython.rlib.rposix
setattr(rposix, func_name, new_func)
-class StringTraits:
- str = str
- str0 = str0
- CHAR = rffi.CHAR
- CCHARP = rffi.CCHARP
- charp2str = staticmethod(rffi.charp2str)
- str2charp = staticmethod(rffi.str2charp)
- free_charp = staticmethod(rffi.free_charp)
- scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
-
- @staticmethod
- def posix_function_name(name):
- return underscore_on_windows + name
-
- @staticmethod
- def ll_os_name(name):
- return 'll_os.ll_os_' + name
-
-class UnicodeTraits:
- str = unicode
- str0 = unicode0
- CHAR = rffi.WCHAR_T
- CCHARP = rffi.CWCHARP
- charp2str = staticmethod(rffi.wcharp2unicode)
- str2charp = staticmethod(rffi.unicode2wcharp)
- free_charp = staticmethod(rffi.free_wcharp)
- scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
-
- @staticmethod
- def posix_function_name(name):
- return underscore_on_windows + 'w' + name
-
- @staticmethod
- def ll_os_name(name):
- return 'll_os.ll_os_w' + name
-
def registering_str_unicode(posixfunc, condition=True):
if not condition or posixfunc is None:
return registering(None, condition=False)
@@ -129,16 +94,6 @@
posix = __import__(os.name)
-if sys.platform.startswith('win'):
- _WIN32 = True
-else:
- _WIN32 = False
-
-if _WIN32:
- underscore_on_windows = '_'
-else:
- underscore_on_windows = ''
-
includes = []
if not _WIN32:
# XXX many of these includes are not portable at all
diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py
--- a/rpython/rtyper/module/ll_os_environ.py
+++ b/rpython/rtyper/module/ll_os_environ.py
@@ -4,10 +4,10 @@
from rpython.rtyper.controllerentry import Controller
from rpython.rtyper.extfunc import register_external
from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.rtyper.module import ll_os
-from rpython.rlib import rposix
+from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
-str0 = ll_os.str0
+str0 = annmodel.s_Str0
# ____________________________________________________________
#
@@ -59,85 +59,8 @@
return r_getenv
# ____________________________________________________________
-#
-# Lower-level interface: dummy placeholders and external registations
-
-def r_getenv(name):
- just_a_placeholder # should return None if name not found
-
-os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP,
- threadsafe=False)
-
-def getenv_llimpl(name):
- with rffi.scoped_str2charp(name) as l_name:
- l_result = os_getenv(l_name)
- return rffi.charp2str(l_result) if l_result else None
-
-register_external(r_getenv, [str0],
- annmodel.SomeString(can_be_None=True, no_nul=True),
- export_name='ll_os.ll_os_getenv',
- llimpl=getenv_llimpl)
-
-# ____________________________________________________________
-
-def r_putenv(name, value):
- just_a_placeholder
-
-class EnvKeepalive:
- pass
-envkeepalive = EnvKeepalive()
-envkeepalive.byname = {}
-
-os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT)
-
-def putenv_llimpl(name, value):
- l_string = rffi.str2charp('%s=%s' % (name, value))
- error = rffi.cast(lltype.Signed, os_putenv(l_string))
- if error:
- rffi.free_charp(l_string)
- raise OSError(rposix.get_errno(), "os_putenv failed")
- # keep 'l_string' alive - we know that the C library needs it
- # until the next call to putenv() with the same 'name'.
- l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO))
- envkeepalive.byname[name] = l_string
- if l_oldstring:
- rffi.free_charp(l_oldstring)
-
-register_external(r_putenv, [str0, str0], annmodel.s_None,
- export_name='ll_os.ll_os_putenv',
- llimpl=putenv_llimpl)
-
-# ____________________________________________________________
-
-def r_unsetenv(name):
- # default implementation for platforms without a real unsetenv()
- r_putenv(name, '')
-
-if hasattr(__import__(os.name), 'unsetenv'):
- os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT)
-
- def unsetenv_llimpl(name):
- with rffi.scoped_str2charp(name) as l_name:
- error = rffi.cast(lltype.Signed, os_unsetenv(l_name))
- if error:
- raise OSError(rposix.get_errno(), "os_unsetenv failed")
- try:
- l_oldstring = envkeepalive.byname[name]
- except KeyError:
- pass
- else:
- del envkeepalive.byname[name]
- rffi.free_charp(l_oldstring)
-
- register_external(r_unsetenv, [str0], annmodel.s_None,
- export_name='ll_os.ll_os_unsetenv',
- llimpl=unsetenv_llimpl)
-
-# ____________________________________________________________
# Access to the 'environ' external variable
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-
if sys.platform.startswith('darwin'):
CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP)
_os_NSGetEnviron = rffi.llexternal(
@@ -146,16 +69,21 @@
)
def os_get_environ():
return _os_NSGetEnviron()[0]
-elif sys.platform.startswith('win'):
+elif _WIN32:
+ eci = ExternalCompilationInfo(includes=['stdlib.h'])
+ CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True}))
+
os_get_environ, _os_set_environ = rffi.CExternVariable(
- rffi.CCHARPP,
- '_environ',
- ExternalCompilationInfo(includes=['stdlib.h']))
+ rffi.CCHARPP, '_environ', eci)
+ get__wenviron, _set__wenviron = rffi.CExternVariable(
+ CWCHARPP, '_wenviron', eci, c_type='wchar_t **')
else:
os_get_environ, _os_set_environ = rffi.CExternVariable(
rffi.CCHARPP, 'environ', ExternalCompilationInfo())
# ____________________________________________________________
+#
+# Lower-level interface: dummy placeholders and external registations
def r_envkeys():
just_a_placeholder
@@ -181,18 +109,109 @@
def r_envitems():
just_a_placeholder
-def envitems_llimpl():
- environ = os_get_environ()
- result = []
- i = 0
- while environ[i]:
- name_value = rffi.charp2str(environ[i])
- p = name_value.find('=')
- if p >= 0:
- result.append((name_value[:p], name_value[p+1:]))
- i += 1
- return result
+def r_getenv(name):
+ just_a_placeholder # should return None if name not found
+
+def r_putenv(name, value):
+ just_a_placeholder
+
+os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP,
+ threadsafe=False)
+os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT)
+if _WIN32:
+ _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP,
+ compilation_info=eci, threadsafe=False)
+ _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT,
+ compilation_info=eci)
+
+class EnvKeepalive:
+ pass
+envkeepalive = EnvKeepalive()
+envkeepalive.byname = {}
+envkeepalive.bywname = {}
+
+def make_env_impls(win32=False):
+ if not win32:
+ traits = StringTraits()
+ get_environ, getenv, putenv = os_get_environ, os_getenv, os_putenv
+ byname, eq = envkeepalive.byname, '='
+ def last_error(msg):
+ from rpython.rlib import rposix
+ raise OSError(rposix.get_errno(), msg)
+ else:
+ traits = UnicodeTraits()
+ get_environ, getenv, putenv = get__wenviron, _wgetenv, _wputenv
+ byname, eq = envkeepalive.bywname, u'='
+ from rpython.rlib.rwin32 import lastWindowsError as last_error
+
+ def envitems_llimpl():
+ environ = get_environ()
+ result = []
+ i = 0
+ while environ[i]:
+ name_value = traits.charp2str(environ[i])
+ p = name_value.find(eq)
+ if p >= 0:
+ result.append((name_value[:p], name_value[p+1:]))
+ i += 1
+ return result
+
+ def getenv_llimpl(name):
+ with traits.scoped_str2charp(name) as l_name:
+ l_result = getenv(l_name)
+ return traits.charp2str(l_result) if l_result else None
+
+ def putenv_llimpl(name, value):
+ l_string = traits.str2charp(name + eq + value)
+ error = rffi.cast(lltype.Signed, putenv(l_string))
+ if error:
+ traits.free_charp(l_string)
+ last_error("putenv failed")
+ # keep 'l_string' alive - we know that the C library needs it
+ # until the next call to putenv() with the same 'name'.
+ l_oldstring = byname.get(name, lltype.nullptr(traits.CCHARP.TO))
+ byname[name] = l_string
+ if l_oldstring:
+ traits.free_charp(l_oldstring)
+
+ return envitems_llimpl, getenv_llimpl, putenv_llimpl
+
+envitems_llimpl, getenv_llimpl, putenv_llimpl = make_env_impls()
register_external(r_envitems, [], [(str0, str0)],
export_name='ll_os.ll_os_envitems',
llimpl=envitems_llimpl)
+register_external(r_getenv, [str0],
+ annmodel.SomeString(can_be_None=True, no_nul=True),
+ export_name='ll_os.ll_os_getenv',
+ llimpl=getenv_llimpl)
+register_external(r_putenv, [str0, str0], annmodel.s_None,
+ export_name='ll_os.ll_os_putenv',
+ llimpl=putenv_llimpl)
+
+# ____________________________________________________________
+
+def r_unsetenv(name):
+ # default implementation for platforms without a real unsetenv()
+ r_putenv(name, '')
+
+if hasattr(__import__(os.name), 'unsetenv'):
+ os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT)
+
+ def unsetenv_llimpl(name):
+ with rffi.scoped_str2charp(name) as l_name:
+ error = rffi.cast(lltype.Signed, os_unsetenv(l_name))
+ if error:
+ from rpython.rlib import rposix
+ raise OSError(rposix.get_errno(), "os_unsetenv failed")
+ try:
+ l_oldstring = envkeepalive.byname[name]
+ except KeyError:
+ pass
+ else:
+ del envkeepalive.byname[name]
+ rffi.free_charp(l_oldstring)
+
+ register_external(r_unsetenv, [str0], annmodel.s_None,
+ export_name='ll_os.ll_os_unsetenv',
+ llimpl=unsetenv_llimpl)
diff --git a/rpython/rtyper/module/support.py b/rpython/rtyper/module/support.py
--- a/rpython/rtyper/module/support.py
+++ b/rpython/rtyper/module/support.py
@@ -1,6 +1,12 @@
-from rpython.rtyper.lltypesystem import lltype
+import os
+import sys
+
+from rpython.annotator import model as annmodel
+from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.ootypesystem import ootype
-import os
+
+_WIN32 = sys.platform.startswith('win')
+underscore_on_windows = '_' if _WIN32 else ''
# utility conversion functions
class LLSupport:
@@ -64,6 +70,45 @@
from_rstr_nonnull = staticmethod(from_rstr_nonnull)
+class StringTraits:
+ str = str
+ str0 = annmodel.s_Str0
+ CHAR = rffi.CHAR
+ CCHARP = rffi.CCHARP
+ charp2str = staticmethod(rffi.charp2str)
+ scoped_str2charp = staticmethod(rffi.scoped_str2charp)
+ str2charp = staticmethod(rffi.str2charp)
+ free_charp = staticmethod(rffi.free_charp)
+ scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
+
+ @staticmethod
+ def posix_function_name(name):
+ return underscore_on_windows + name
+
+ @staticmethod
+ def ll_os_name(name):
+ return 'll_os.ll_os_' + name
+
+class UnicodeTraits:
+ str = unicode
+ str0 = annmodel.s_Unicode0
+ CHAR = rffi.WCHAR_T
+ CCHARP = rffi.CWCHARP
+ charp2str = staticmethod(rffi.wcharp2unicode)
+ str2charp = staticmethod(rffi.unicode2wcharp)
+ scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp)
+ free_charp = staticmethod(rffi.free_wcharp)
+ scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
+
+ @staticmethod
+ def posix_function_name(name):
+ return underscore_on_windows + 'w' + name
+
+ @staticmethod
+ def ll_os_name(name):
+ return 'll_os.ll_os_w' + name
+
+
def ll_strcpy(dst_s, src_s, n):
dstchars = dst_s.chars
srcchars = src_s.chars
@@ -78,5 +123,3 @@
while i < n:
dstchars[i] = srcchars[i]
i += 1
-
-
diff --git a/rpython/translator/backendopt/graphanalyze.py b/rpython/translator/backendopt/graphanalyze.py
--- a/rpython/translator/backendopt/graphanalyze.py
+++ b/rpython/translator/backendopt/graphanalyze.py
@@ -80,21 +80,21 @@
if graph is None:
x = self.analyze_external_call(op, seen)
if self.verbose and x:
- print '\tanalyze_external_call %s: %r' % (op, x)
+ self.dump_info('analyze_external_call %s: %r' % (op, x))
return x
x = self.analyze_direct_call(graph, seen)
if self.verbose and x:
- print '\tanalyze_direct_call(%s): %r' % (graph, x)
+ self.dump_info('analyze_direct_call(%s): %r' % (graph, x))
return x
elif op.opname == "indirect_call":
graphs = op.args[-1].value
if graphs is None:
if self.verbose:
- print '\t%s to unknown' % (op,)
+ self.dump_info('%s to unknown' % (op,))
return self.top_result()
x = self.analyze_indirect_call(graphs, seen)
if self.verbose and x:
- print '\tanalyze_indirect_call(%s): %r' % (graphs, x)
+ self.dump_info('analyze_indirect_call(%s): %r' % (graphs, x))
return x
elif op.opname == "oosend":
name = op.args[0].value
@@ -106,9 +106,12 @@
return self.analyze_oosend(TYPE, name, seen)
x = self.analyze_simple_operation(op, graphinfo)
if self.verbose and x:
- print '\t%s: %r' % (op, x)
+ self.dump_info('%s: %r' % (op, x))
return x
+ def dump_info(self, info):
+ print '[%s] %s' % (self.__class__.__name__, info)
+
def analyze_direct_call(self, graph, seen=None):
if seen is None:
seen = DependencyTracker(self)
More information about the pypy-commit
mailing list