Author: Maciej Fijalkowski <[email protected]>
Branch: release-1.6.x
Changeset: r46241:5fadf40d80b0
Date: 2011-08-03 13:34 +0200
http://bitbucket.org/pypy/pypy/changeset/5fadf40d80b0/
Log: merge default
diff --git a/pypy/jit/backend/llgraph/test/test_llgraph.py
b/pypy/jit/backend/llgraph/test/test_llgraph.py
--- a/pypy/jit/backend/llgraph/test/test_llgraph.py
+++ b/pypy/jit/backend/llgraph/test/test_llgraph.py
@@ -19,6 +19,9 @@
def setup_method(self, _):
self.cpu = self.cpu_type(None)
+ def test_memoryerror(self):
+ py.test.skip("does not make much sense on the llgraph backend")
+
def test_cast_adr_to_int_and_back():
X = lltype.Struct('X', ('foo', lltype.Signed))
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -544,18 +544,19 @@
assert self.GCClass.inline_simple_malloc
assert self.GCClass.inline_simple_malloc_varsize
- # make a malloc function, with three arguments
+ # make a malloc function, with two arguments
def malloc_basic(size, tid):
type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
has_finalizer = bool(tid & (1<<llgroup.HALFSHIFT))
check_typeid(type_id)
- try:
- res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
- type_id, size, True,
- has_finalizer, False)
- except MemoryError:
- fatalerror("out of memory (from JITted code)")
- res = lltype.nullptr(llmemory.GCREF.TO)
+ res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
+ type_id, size, True,
+ has_finalizer, False)
+ # In case the operation above failed, we are returning NULL
+ # from this function to assembler. There is also an RPython
+ # exception set, typically MemoryError; but it's easier and
+ # faster to check for the NULL return value, as done by
+ # translator/exceptiontransform.py.
#llop.debug_print(lltype.Void, "\tmalloc_basic", size, type_id,
# "-->", res)
return res
@@ -571,14 +572,10 @@
def malloc_array(itemsize, tid, num_elem):
type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
check_typeid(type_id)
- try:
- return llop1.do_malloc_varsize_clear(
- llmemory.GCREF,
- type_id, num_elem, self.array_basesize, itemsize,
- self.array_length_ofs, True)
- except MemoryError:
- fatalerror("out of memory (from JITted code)")
- return lltype.nullptr(llmemory.GCREF.TO)
+ return llop1.do_malloc_varsize_clear(
+ llmemory.GCREF,
+ type_id, num_elem, self.array_basesize, itemsize,
+ self.array_length_ofs, True)
self.malloc_array = malloc_array
self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType(
[lltype.Signed] * 3, llmemory.GCREF))
@@ -591,23 +588,15 @@
unicode_type_id = self.layoutbuilder.get_type_id(rstr.UNICODE)
#
def malloc_str(length):
- try:
- return llop1.do_malloc_varsize_clear(
- llmemory.GCREF,
- str_type_id, length, str_basesize, str_itemsize,
- str_ofs_length, True)
- except MemoryError:
- fatalerror("out of memory (from JITted code)")
- return lltype.nullptr(llmemory.GCREF.TO)
+ return llop1.do_malloc_varsize_clear(
+ llmemory.GCREF,
+ str_type_id, length, str_basesize, str_itemsize,
+ str_ofs_length, True)
def malloc_unicode(length):
- try:
- return llop1.do_malloc_varsize_clear(
- llmemory.GCREF,
- unicode_type_id, length, unicode_basesize,unicode_itemsize,
- unicode_ofs_length, True)
- except MemoryError:
- fatalerror("out of memory (from JITted code)")
- return lltype.nullptr(llmemory.GCREF.TO)
+ return llop1.do_malloc_varsize_clear(
+ llmemory.GCREF,
+ unicode_type_id, length, unicode_basesize,unicode_itemsize,
+ unicode_ofs_length, True)
self.malloc_str = malloc_str
self.malloc_unicode = malloc_unicode
self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType(
@@ -628,16 +617,12 @@
if self.DEBUG:
random_usage_of_xmm_registers()
assert size >= self.minimal_size_in_nursery
- try:
- # NB. although we call do_malloc_fixedsize_clear() here,
- # it's a bit of a hack because we set tid to 0 and may
- # also use it to allocate varsized objects. The tid
- # and possibly the length are both set afterward.
- gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
- 0, size, True, False, False)
- except MemoryError:
- fatalerror("out of memory (from JITted code)")
- return 0
+ # NB. although we call do_malloc_fixedsize_clear() here,
+ # it's a bit of a hack because we set tid to 0 and may
+ # also use it to allocate varsized objects. The tid
+ # and possibly the length are both set afterward.
+ gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
+ 0, size, True, False, False)
return rffi.cast(lltype.Signed, gcref)
self.malloc_slowpath = malloc_slowpath
self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed], lltype.Signed)
diff --git a/pypy/jit/backend/llsupport/test/test_ffisupport.py
b/pypy/jit/backend/llsupport/test/test_ffisupport.py
--- a/pypy/jit/backend/llsupport/test/test_ffisupport.py
+++ b/pypy/jit/backend/llsupport/test/test_ffisupport.py
@@ -1,4 +1,5 @@
from pypy.rlib.libffi import types
+from pypy.jit.codewriter.longlong import is_64_bit
from pypy.jit.backend.llsupport.ffisupport import *
@@ -34,11 +35,14 @@
assert descr.get_result_size(False) == 1
assert descr.is_result_signed() == False
- descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong)
- assert descr is None # missing longlongs
- descr = get_call_descr_dynamic(FakeCPU(supports_longlong=True),
- [], types.slonglong)
- assert isinstance(descr, LongLongCallDescr)
+ if not is_64_bit:
+ descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong)
+ assert descr is None # missing longlongs
+ descr = get_call_descr_dynamic(FakeCPU(supports_longlong=True),
+ [], types.slonglong)
+ assert isinstance(descr, LongLongCallDescr)
+ else:
+ assert types.slonglong is types.slong
descr = get_call_descr_dynamic(FakeCPU(), [], types.float)
assert descr is None # missing singlefloats
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -14,7 +14,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
+ propagate_exception_v = -1
total_compiled_loops = 0
total_compiled_bridges = 0
total_freed_loops = 0
diff --git a/pypy/jit/backend/test/runner_test.py
b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -2807,6 +2807,26 @@
assert mem2 < mem1
assert mem2 == mem0
+ def test_memoryerror(self):
+ excdescr = BasicFailDescr(666)
+ self.cpu.propagate_exception_v = self.cpu.get_fail_descr_number(
+ excdescr)
+ self.cpu.setup_once() # xxx redo it, because we added
+ # propagate_exception_v
+ i0 = BoxInt()
+ p0 = BoxPtr()
+ operations = [
+ ResOperation(rop.NEWUNICODE, [i0], p0),
+ ResOperation(rop.FINISH, [p0], None, descr=BasicFailDescr(1))
+ ]
+ inputargs = [i0]
+ looptoken = LoopToken()
+ self.cpu.compile_loop(inputargs, operations, looptoken)
+ # overflowing value:
+ self.cpu.set_future_value_int(0, sys.maxint // 4 + 1)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail.identifier == excdescr.identifier
+
class OOtypeBackendTest(BaseBackendTest):
diff --git a/pypy/jit/backend/x86/assembler.py
b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -91,6 +91,7 @@
self._current_depths_cache = (0, 0)
self.datablockwrapper = None
self.stack_check_slowpath = 0
+ self.propagate_exception_path = 0
self.teardown()
def leave_jitted_hook(self):
@@ -127,6 +128,7 @@
self._build_failure_recovery(True, withfloats=True)
support.ensure_sse2_floats()
self._build_float_constants()
+ self._build_propagate_exception_path()
if gc_ll_descr.get_malloc_slowpath_addr is not None:
self._build_malloc_slowpath()
self._build_stack_check_slowpath()
@@ -140,6 +142,9 @@
assert self.memcpy_addr != 0, "setup_once() not called?"
self.current_clt = looptoken.compiled_loop_token
self.pending_guard_tokens = []
+ if WORD == 8:
+ self.pending_memoryerror_trampoline_from = []
+ self.error_trampoline_64 = 0
self.mc = codebuf.MachineCodeBlockWrapper()
#assert self.datablockwrapper is None --- but obscure case
# possible, e.g. getting MemoryError and continuing
@@ -149,6 +154,8 @@
def teardown(self):
self.pending_guard_tokens = None
+ if WORD == 8:
+ self.pending_memoryerror_trampoline_from = None
self.mc = None
self.looppos = -1
self.currently_compiling_loop = None
@@ -237,15 +244,47 @@
if self.cpu.supports_floats: # restore the XMM registers
for i in range(self.cpu.NUM_REGS):# from where they were saved
mc.MOVSD_xs(i, (WORD*2)+8*i)
+ #
+ # Note: we check this after the code above, just because the code
+ # above is more than 127 bytes on 64-bits...
+ mc.TEST_rr(eax.value, eax.value)
+ mc.J_il8(rx86.Conditions['Z'], 0) # patched later
+ jz_location = mc.get_relative_pos()
+ #
nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr()
mc.MOV(edx, heap(nursery_free_adr)) # load this in EDX
mc.RET()
+ #
+ # If the slowpath malloc failed, we raise a MemoryError that
+ # always interrupts the current loop, as a "good enough"
+ # approximation. Also note that we didn't RET from this helper;
+ # but the code we jump to will actually restore the stack
+ # position based on EBP, which will get us out of here for free.
+ offset = mc.get_relative_pos() - jz_location
+ assert 0 < offset <= 127
+ mc.overwrite(jz_location-1, chr(offset))
+ mc.JMP(imm(self.propagate_exception_path))
+ #
rawstart = mc.materialize(self.cpu.asmmemmgr, [])
self.malloc_slowpath2 = rawstart
+ def _build_propagate_exception_path(self):
+ if self.cpu.propagate_exception_v < 0:
+ return # not supported (for tests, or non-translated)
+ #
+ self.mc = codebuf.MachineCodeBlockWrapper()
+ # call on_leave_jitted_save_exc()
+ addr = self.cpu.get_on_leave_jitted_int(save_exception=True)
+ self.mc.CALL(imm(addr))
+ self.mc.MOV_ri(eax.value, self.cpu.propagate_exception_v)
+ self._call_footer()
+ rawstart = self.mc.materialize(self.cpu.asmmemmgr, [])
+ self.propagate_exception_path = rawstart
+ self.mc = None
+
def _build_stack_check_slowpath(self):
_, _, slowpathaddr = self.cpu.insert_stack_check()
- if slowpathaddr == 0 or self.cpu.exit_frame_with_exception_v < 0:
+ if slowpathaddr == 0 or self.cpu.propagate_exception_v < 0:
return # no stack check (for tests, or non-translated)
#
# make a "function" that is called immediately at the start of
@@ -301,19 +340,11 @@
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)
+ # call on_leave_jitted_save_exc()
+ addr = self.cpu.get_on_leave_jitted_int(save_exception=True)
mc.CALL(imm(addr))
#
- mc.MOV_ri(eax.value, self.cpu.exit_frame_with_exception_v)
+ mc.MOV_ri(eax.value, self.cpu.propagate_exception_v)
#
# footer -- note the ADD, which skips the return address of this
# function, and will instead return to the caller's caller. Note
@@ -525,6 +556,8 @@
# at the end of self.mc.
for tok in self.pending_guard_tokens:
tok.pos_recovery_stub = self.generate_quick_failure(tok)
+ if WORD == 8 and len(self.pending_memoryerror_trampoline_from) > 0:
+ self.error_trampoline_64 = self.generate_propagate_error_64()
def patch_pending_failure_recoveries(self, rawstart):
# after we wrote the assembler to raw memory, set up
@@ -561,6 +594,12 @@
# less, we would run into the issue that overwriting the
# 5 bytes here might get a few nonsense bytes at the
# return address of the following CALL.
+ if WORD == 8:
+ for pos_after_jz in self.pending_memoryerror_trampoline_from:
+ assert self.error_trampoline_64 != 0 # only if non-empty
+ mc = codebuf.MachineCodeBlockWrapper()
+ mc.writeimm32(self.error_trampoline_64 - pos_after_jz)
+ mc.copy_to_raw_memory(rawstart + pos_after_jz - 4)
def get_asmmemmgr_blocks(self, looptoken):
clt = looptoken.compiled_loop_token
@@ -1422,7 +1461,7 @@
assert isinstance(loc_vtable, ImmedLoc)
arglocs = arglocs[:-1]
self.call(self.malloc_func_addr, arglocs, eax)
- # xxx ignore NULL returns for now
+ self.propagate_memoryerror_if_eax_is_null()
self.set_vtable(eax, loc_vtable)
def set_vtable(self, loc, loc_vtable):
@@ -1441,18 +1480,35 @@
def genop_new(self, op, arglocs, result_loc):
assert result_loc is eax
self.call(self.malloc_func_addr, arglocs, eax)
+ self.propagate_memoryerror_if_eax_is_null()
def genop_new_array(self, op, arglocs, result_loc):
assert result_loc is eax
self.call(self.malloc_array_func_addr, arglocs, eax)
+ self.propagate_memoryerror_if_eax_is_null()
def genop_newstr(self, op, arglocs, result_loc):
assert result_loc is eax
self.call(self.malloc_str_func_addr, arglocs, eax)
+ self.propagate_memoryerror_if_eax_is_null()
def genop_newunicode(self, op, arglocs, result_loc):
assert result_loc is eax
self.call(self.malloc_unicode_func_addr, arglocs, eax)
+ self.propagate_memoryerror_if_eax_is_null()
+
+ def propagate_memoryerror_if_eax_is_null(self):
+ # if self.propagate_exception_path == 0 (tests), this may jump to 0
+ # and segfaults. too bad. the alternative is to continue anyway
+ # with eax==0, but that will segfault too.
+ self.mc.TEST_rr(eax.value, eax.value)
+ if WORD == 4:
+ self.mc.J_il(rx86.Conditions['Z'], self.propagate_exception_path)
+ self.mc.add_pending_relocation()
+ elif WORD == 8:
+ self.mc.J_il(rx86.Conditions['Z'], 0)
+ pos = self.mc.get_relative_pos()
+ self.pending_memoryerror_trampoline_from.append(pos)
# ----------
@@ -1724,6 +1780,12 @@
return GuardToken(faildescr, failargs, fail_locs, exc,
is_guard_not_invalidated)
+ def generate_propagate_error_64(self):
+ assert WORD == 8
+ startpos = self.mc.get_relative_pos()
+ self.mc.JMP(imm(self.propagate_exception_path))
+ return startpos
+
def generate_quick_failure(self, guardtok):
"""Generate the initial code for handling a failure. We try to
keep it as compact as possible.
diff --git a/pypy/jit/backend/x86/codebuf.py b/pypy/jit/backend/x86/codebuf.py
--- a/pypy/jit/backend/x86/codebuf.py
+++ b/pypy/jit/backend/x86/codebuf.py
@@ -25,8 +25,11 @@
self.init_block_builder()
# a list of relative positions; for each position p, the bytes
# at [p-4:p] encode an absolute address that will need to be
- # made relative.
- self.relocations = []
+ # made relative. Only works on 32-bit!
+ if WORD == 4:
+ self.relocations = []
+ else:
+ self.relocations = None
#
# ResOperation --> offset in the assembly.
# ops_offset[None] represents the beginning of the code after the last
op
@@ -42,9 +45,10 @@
def copy_to_raw_memory(self, addr):
self._copy_to_raw_memory(addr)
- for reloc in self.relocations:
- p = addr + reloc
- adr = rffi.cast(rffi.LONGP, p - WORD)
- adr[0] = intmask(adr[0] - p)
+ if self.relocations is not None:
+ for reloc in self.relocations:
+ p = addr + reloc
+ 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)
diff --git a/pypy/jit/backend/x86/test/test_regloc.py
b/pypy/jit/backend/x86/test/test_regloc.py
--- a/pypy/jit/backend/x86/test/test_regloc.py
+++ b/pypy/jit/backend/x86/test/test_regloc.py
@@ -62,7 +62,7 @@
assert mc.relocations == [5]
expected = "\xE8" + struct.pack('<i', target - (rawstart + 5))
elif IS_X86_64:
- assert mc.relocations == []
+ assert mc.relocations is None
if 0 <= target <= 0xffffffff:
assert length == 9
expected = (
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -668,10 +668,9 @@
def handle_fail(self, metainterp_sd, jitdriver_sd):
cpu = metainterp_sd.cpu
exception = cpu.grab_exc_value()
+ assert exception, "PropagateExceptionDescr: no exception??"
raise metainterp_sd.ExitFrameWithExceptionRef(cpu, exception)
-propagate_exception_descr = PropagateExceptionDescr()
-
def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redboxes,
memory_manager=None):
"""Make a LoopToken that corresponds to assembler code that just
@@ -705,7 +704,7 @@
finishargs = []
#
jd = jitdriver_sd
- faildescr = propagate_exception_descr
+ faildescr = PropagateExceptionDescr()
operations = [
ResOperation(rop.CALL, callargs, result, descr=jd.portal_calldescr),
ResOperation(rop.GUARD_NO_EXCEPTION, [], None, descr=faildescr),
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1379,9 +1379,9 @@
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
+ exc_descr = compile.PropagateExceptionDescr()
+ num = self.cpu.get_fail_descr_number(exc_descr)
+ self.cpu.propagate_exception_v = num
#
self.globaldata = MetaInterpGlobalData(self)
diff --git a/pypy/module/cpyext/include/patchlevel.h
b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -31,8 +31,9 @@
/* PyPy version as a string */
#define PYPY_VERSION "1.6.0"
-/* Subversion Revision number of this file (not of the repository) */
-#define PY_PATCHLEVEL_REVISION "$Revision: 77872 $"
+/* Subversion Revision number of this file (not of the repository).
+ * Empty since Mercurial migration. */
+#define PY_PATCHLEVEL_REVISION ""
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
Use this for numeric comparisons, e.g. #if PY_VERSION_HEX >= ... */
diff --git a/pypy/module/itertools/interp_itertools.py
b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -339,16 +339,21 @@
start = 0
else:
start = space.int_w(w_startstop)
+ if start < 0:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "Indicies for islice() must be non-negative integers."))
w_stop = args_w[0]
else:
raise OperationError(space.w_TypeError, space.wrap("islice() takes
at most 4 arguments (" + str(num_args) + " given)"))
if space.is_w(w_stop, space.w_None):
stop = -1
- stoppable = False
else:
stop = space.int_w(w_stop)
- stoppable = True
+ if stop < 0:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "Stop argument must be a non-negative integer or None."))
+ stop = max(start, stop) # for obscure CPython compatibility
if num_args == 2:
w_step = args_w[1]
@@ -356,38 +361,37 @@
step = 1
else:
step = space.int_w(w_step)
+ if step < 1:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "Step must be one or lager for islice()."))
else:
step = 1
- if start < 0:
- raise OperationError(space.w_ValueError, space.wrap("Indicies for
islice() must be non-negative integers."))
- if stoppable and stop < 0:
- raise OperationError(space.w_ValueError, space.wrap("Stop argument
must be a non-negative integer or None."))
- if step < 1:
- raise OperationError(space.w_ValueError, space.wrap("Step must be
one or lager for islice()."))
-
+ self.ignore = step - 1
self.start = start
self.stop = stop
- self.step = step
def iter_w(self):
return self.space.wrap(self)
def next_w(self):
if self.start >= 0: # first call only
- consume = self.start + 1
+ ignore = self.start
self.start = -1
else: # all following calls
- consume = self.step
- if consume > 1:
- self._ignore_items(consume-1)
- if self.stop >= 0:
- if self.stop < consume:
+ ignore = self.ignore
+ stop = self.stop
+ if stop >= 0:
+ if stop <= ignore:
self.stop = 0 # reset the state so that a following next_w()
- self.step = 1 # has no effect any more
+ # has no effect any more
+ if stop > 0:
+ self._ignore_items(stop)
raise OperationError(self.space.w_StopIteration,
self.space.w_None)
- self.stop -= consume
+ self.stop = stop - (ignore + 1)
+ if ignore > 0:
+ self._ignore_items(ignore)
return self.space.next(self.iterable)
def _ignore_items(self, num):
diff --git a/pypy/module/itertools/test/test_itertools.py
b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -266,6 +266,13 @@
raises(StopIteration, islc.next) # drops the 6th and raise
assert it.next() == "j"
+ it = iter("abcdefghij")
+ islc = itertools.islice(it, 3, 4, 3)
+ assert islc.next() == "d" # drops 0, 1, 2, returns item #3
+ assert it.next() == "e"
+ raises(StopIteration, islc.next) # item #4 is 'stop', so just raise
+ assert it.next() == "f"
+
def test_islice_overflow(self):
import itertools
import sys
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py
b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -90,12 +90,12 @@
i46 = call(ConstClass(ll_startswith__rpy_stringPtr_rpy_stringPtr),
p28, ConstPtr(ptr45), descr=<BoolCallDescr>)
guard_false(i46, descr=...)
p51 = new_with_vtable(21136408)
- setfield_gc(p51, p28, descr=<GcPtrFieldDescr
.*NumberStringParser.inst_literal .*>)
- setfield_gc(p51, ConstPtr(ptr51), descr=<GcPtrFieldDescr
pypy.objspace.std.strutil.NumberStringParser.inst_fname .*>)
- setfield_gc(p51, 1, descr=<SignedFieldDescr
.*NumberStringParser.inst_sign .*>)
- setfield_gc(p51, 16, descr=<SignedFieldDescr
.*NumberStringParser.inst_base .*>)
- setfield_gc(p51, p28, descr=<GcPtrFieldDescr
.*NumberStringParser.inst_s .*>)
- setfield_gc(p51, i29, descr=<SignedFieldDescr
.*NumberStringParser.inst_n .*>)
+ setfield_gc(p51, _, descr=...) # 6 setfields, but the order is
dict-order-dependent
+ setfield_gc(p51, _, descr=...)
+ setfield_gc(p51, _, descr=...)
+ setfield_gc(p51, _, descr=...)
+ setfield_gc(p51, _, descr=...)
+ setfield_gc(p51, _, descr=...)
p55 = call(ConstClass(parse_digit_string), p51,
descr=<GcPtrCallDescr>)
guard_no_exception(descr=...)
i57 = call(ConstClass(rbigint.toint), p55, descr=<SignedCallDescr>)
diff --git a/pypy/module/rctime/interp_time.py
b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -207,13 +207,13 @@
t = (((c_time(lltype.nullptr(rffi.TIME_TP.TO))) / YEAR) * YEAR)
# we cannot have reference to stack variable, put it on the heap
t_ref = lltype.malloc(rffi.TIME_TP.TO, 1, flavor='raw')
- t_ref[0] = t
+ t_ref[0] = rffi.cast(rffi.TIME_T, t)
p = c_localtime(t_ref)
janzone = -p.c_tm_gmtoff
tm_zone = rffi.charp2str(p.c_tm_zone)
janname = [" ", tm_zone][bool(tm_zone)]
tt = t + YEAR / 2
- t_ref[0] = tt
+ t_ref[0] = rffi.cast(rffi.TIME_T, tt)
p = c_localtime(t_ref)
lltype.free(t_ref, flavor='raw')
tm_zone = rffi.charp2str(p.c_tm_zone)
@@ -292,11 +292,14 @@
else:
seconds = space.float_w(w_seconds)
try:
- ovfcheck_float_to_int(seconds)
+ seconds = ovfcheck_float_to_int(seconds)
+ t = rffi.r_time_t(seconds)
+ if rffi.cast(lltype.Signed, t) != seconds:
+ raise OverflowError
except OverflowError:
raise OperationError(space.w_ValueError,
space.wrap("time argument too large"))
- return rffi.r_time_t(seconds)
+ return t
def _tm_to_tuple(space, t):
time_tuple = [
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit