[pypy-commit] pypy arm-backend-2: merge default
bivab
noreply at buildbot.pypy.org
Fri Aug 10 14:13:11 CEST 2012
Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r56687:d8f3bbebe233
Date: 2012-08-10 08:42 +0000
http://bitbucket.org/pypy/pypy/changeset/d8f3bbebe233/
Log: merge default
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -59,7 +59,8 @@
'resbuffer' is a _rawffi array of length 1 containing the value,
and this returns a general Python object that corresponds.
"""
- res = self.__new__(self)
+ res = object.__new__(self)
+ res.__class__ = self
res.__dict__['_buffer'] = resbuffer
res.__dict__['_base'] = base
res.__dict__['_index'] = index
diff --git a/lib_pypy/_marshal.py b/lib_pypy/_marshal.py
--- a/lib_pypy/_marshal.py
+++ b/lib_pypy/_marshal.py
@@ -430,6 +430,7 @@
def _read(self, n):
pos = self.bufpos
newpos = pos + n
+ if newpos > len(self.bufstr): raise EOFError
ret = self.bufstr[pos : newpos]
self.bufpos = newpos
return ret
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -77,8 +77,6 @@
try:
unbound_method = getattr(_continulet, methodname)
args = unbound_method(current, *args, to=target)
- except GreenletExit, e:
- args = (e,)
finally:
_tls.current = current
#
@@ -132,6 +130,8 @@
_tls.current = greenlet
try:
res = greenlet.run(*args)
+ except GreenletExit, e:
+ res = e
finally:
_continuation.permute(greenlet, greenlet.parent)
return (res,)
diff --git a/lib_pypy/pypy_test/test_marshal_extra.py b/lib_pypy/pypy_test/test_marshal_extra.py
--- a/lib_pypy/pypy_test/test_marshal_extra.py
+++ b/lib_pypy/pypy_test/test_marshal_extra.py
@@ -142,4 +142,6 @@
f2.close()
assert obj == case
-
+def test_load_truncated_string():
+ s = '(\x02\x00\x00\x00i\x03\x00\x00\x00sB\xf9\x00\x00\nabcd'
+ py.test.raises(EOFError, marshal.loads, s)
diff --git a/pypy/jit/backend/arm/test/test_ztranslation.py b/pypy/jit/backend/arm/test/test_ztranslation.py
--- a/pypy/jit/backend/arm/test/test_ztranslation.py
+++ b/pypy/jit/backend/arm/test/test_ztranslation.py
@@ -176,7 +176,6 @@
assert bound & (bound-1) == 0 # a power of two
def test_jit_get_stats(self):
- py.test.xfail()
driver = JitDriver(greens = [], reds = ['i'])
def f():
@@ -192,7 +191,8 @@
return len(ll_times)
res = self.meta_interp(main, [])
- assert res == 1
+ assert res == 3
+ # one for loop, one for entry point and one for the prologue
class TestTranslationRemoveTypePtrARM(CCompiledMixin):
CPUClass = getcpuclass()
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
@@ -127,9 +127,13 @@
self._build_stack_check_slowpath()
if gc_ll_descr.gcrootmap:
self._build_release_gil(gc_ll_descr.gcrootmap)
- debug_start('jit-backend-counts')
- self.set_debug(have_debug_prints())
- debug_stop('jit-backend-counts')
+ if not self._debug:
+ # if self._debug is already set it means that someone called
+ # set_debug by hand before initializing the assembler. Leave it
+ # as it is
+ debug_start('jit-backend-counts')
+ self.set_debug(have_debug_prints())
+ debug_stop('jit-backend-counts')
def setup(self, looptoken):
assert self.memcpy_addr != 0, "setup_once() not called?"
diff --git a/pypy/jit/backend/x86/test/test_ztranslation.py b/pypy/jit/backend/x86/test/test_ztranslation.py
--- a/pypy/jit/backend/x86/test/test_ztranslation.py
+++ b/pypy/jit/backend/x86/test/test_ztranslation.py
@@ -172,7 +172,6 @@
assert bound & (bound-1) == 0 # a power of two
def test_jit_get_stats(self):
- py.test.xfail()
driver = JitDriver(greens = [], reds = ['i'])
def f():
@@ -188,7 +187,8 @@
return len(ll_times)
res = self.meta_interp(main, [])
- assert res == 1
+ assert res == 3
+ # one for loop, one for entry point and one for the prologue
class TestTranslationRemoveTypePtrX86(CCompiledMixin):
CPUClass = getcpuclass()
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -277,19 +277,6 @@
def _make_execute_list():
- if 0: # enable this to trace calls to do_xxx
- def wrap(fn):
- def myfn(*args):
- print '<<<', fn.__name__
- try:
- return fn(*args)
- finally:
- print fn.__name__, '>>>'
- return myfn
- else:
- def wrap(fn):
- return fn
- #
execute_by_num_args = {}
for key, value in rop.__dict__.items():
if not key.startswith('_'):
diff --git a/pypy/jit/metainterp/test/test_warmspot.py b/pypy/jit/metainterp/test/test_warmspot.py
--- a/pypy/jit/metainterp/test/test_warmspot.py
+++ b/pypy/jit/metainterp/test/test_warmspot.py
@@ -260,6 +260,33 @@
pass # other case
self.meta_interp(f1, [18])
+ def test_bug_constant_int(self):
+ py.test.skip("crashes because a is a constant")
+ from pypy.rpython.lltypesystem import lltype, rffi
+ mydriver = JitDriver(greens=['a'], reds=['m'])
+ def f1(m, a):
+ while m > 0:
+ mydriver.jit_merge_point(a=a, m=m)
+ m = m - 1
+ def entry(m):
+ f1(m, 42)
+ self.meta_interp(entry, [18])
+
+ def test_bug_constant_instance(self):
+ py.test.skip("crashes because a is a constant")
+ from pypy.rpython.lltypesystem import lltype, rffi
+ mydriver = JitDriver(greens=['a'], reds=['m'])
+ class A(object):
+ pass
+ a1 = A()
+ def f1(m, a):
+ while m > 0:
+ mydriver.jit_merge_point(a=a, m=m)
+ m = m - 1
+ def entry(m):
+ f1(m, a1)
+ self.meta_interp(entry, [18])
+
def test_bug_constant_rawptrs(self):
py.test.skip("crashes because a is a constant")
from pypy.rpython.lltypesystem import lltype, rffi
diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py
--- a/pypy/module/_minimal_curses/fficurses.py
+++ b/pypy/module/_minimal_curses/fficurses.py
@@ -9,10 +9,12 @@
from pypy.module._minimal_curses import interp_curses
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from sys import platform
+import os.path
_CYGWIN = platform == 'cygwin'
+_NCURSES_CURSES = os.path.isfile("/usr/include/ncurses/curses.h")
-if _CYGWIN:
+if _CYGWIN or _NCURSES_CURSES:
eci = ExternalCompilationInfo(
includes = ['ncurses/curses.h', 'ncurses/term.h'],
libraries = ['curses'],
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -602,8 +602,10 @@
try:
if find_info.modtype == PY_SOURCE:
- load_source_module(space, w_modulename, w_mod, find_info.filename,
- find_info.stream.readall())
+ load_source_module(
+ space, w_modulename, w_mod,
+ find_info.filename, find_info.stream.readall(),
+ find_info.stream.try_to_find_file_descriptor())
return w_mod
elif find_info.modtype == PY_COMPILED:
magic = _r_long(find_info.stream)
@@ -878,7 +880,7 @@
@jit.dont_look_inside
-def load_source_module(space, w_modulename, w_mod, pathname, source,
+def load_source_module(space, w_modulename, w_mod, pathname, source, fd,
write_pyc=True):
"""
Load a source module from a given file and return its module
@@ -887,8 +889,8 @@
w = space.wrap
if space.config.objspace.usepycfiles:
+ src_stat = os.fstat(fd)
cpathname = pathname + 'c'
- src_stat = os.stat(pathname)
mtime = int(src_stat[stat.ST_MTIME])
mode = src_stat[stat.ST_MODE]
stream = check_compiled_module(space, cpathname, mtime)
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -101,7 +101,8 @@
importing._prepare_module(space, w_mod, filename, None)
importing.load_source_module(
- space, w_modulename, w_mod, filename, stream.readall())
+ space, w_modulename, w_mod,
+ filename, stream.readall(), stream.try_to_find_file_descriptor())
if space.is_w(w_file, space.w_None):
stream.close()
return w_mod
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -104,11 +104,10 @@
filename = str(p.join("x.py"))
stream = streamio.open_file_as_stream(filename, "r")
try:
- importing.load_source_module(space,
- w_modname,
- w(importing.Module(space, w_modname)),
- filename,
- stream.readall())
+ importing.load_source_module(
+ space, w_modname, w(importing.Module(space, w_modname)),
+ filename, stream.readall(),
+ stream.try_to_find_file_descriptor())
finally:
stream.close()
if space.config.objspace.usepycfiles:
@@ -618,6 +617,19 @@
sys.path.insert(0, sys.path.pop())
del sys.modules['itertools']
+ def test_invalid_pathname(self):
+ import imp
+ import pkg
+ import os
+
+ info = ('.py', 'r', imp.PY_SOURCE)
+ pathname = os.path.join(os.path.dirname(pkg.__file__), 'a.py')
+
+ module = imp.load_module('a', open(pathname),
+ 'invalid_path_name', ('.py', 'r', imp.PY_SOURCE))
+ assert module.__name__ == 'a'
+ assert module.__file__ == 'invalid_path_name'
+
class TestAbi:
def test_abi_tag(self):
@@ -783,11 +795,10 @@
pathname = _testfilesource()
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(space,
- w_modulename,
- w_mod,
- pathname,
- stream.readall())
+ w_ret = importing.load_source_module(
+ space, w_modulename, w_mod,
+ pathname, stream.readall(),
+ stream.try_to_find_file_descriptor())
finally:
stream.close()
assert w_mod is w_ret
@@ -806,12 +817,11 @@
pathname = _testfilesource()
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(space,
- w_modulename,
- w_mod,
- pathname,
- stream.readall(),
- write_pyc=False)
+ w_ret = importing.load_source_module(
+ space, w_modulename, w_mod,
+ pathname, stream.readall(),
+ stream.try_to_find_file_descriptor(),
+ write_pyc=False)
finally:
stream.close()
cpathname = udir.join('test.pyc')
@@ -826,11 +836,10 @@
try:
space.setattr(space.sys, space.wrap('dont_write_bytecode'),
space.w_True)
- w_ret = importing.load_source_module(space,
- w_modulename,
- w_mod,
- pathname,
- stream.readall())
+ w_ret = importing.load_source_module(
+ space, w_modulename, w_mod,
+ pathname, stream.readall(),
+ stream.try_to_find_file_descriptor())
finally:
space.setattr(space.sys, space.wrap('dont_write_bytecode'),
space.w_False)
@@ -846,11 +855,10 @@
pathname = _testfilesource(source="<Syntax Error>")
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(space,
- w_modulename,
- w_mod,
- pathname,
- stream.readall())
+ w_ret = importing.load_source_module(
+ space, w_modulename, w_mod,
+ pathname, stream.readall(),
+ stream.try_to_find_file_descriptor())
except OperationError:
# OperationError("Syntax Error")
pass
@@ -867,11 +875,10 @@
pathname = _testfilesource(source="a = unknown_name")
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(space,
- w_modulename,
- w_mod,
- pathname,
- stream.readall())
+ w_ret = importing.load_source_module(
+ space, w_modulename, w_mod,
+ pathname, stream.readall(),
+ stream.try_to_find_file_descriptor())
except OperationError:
# OperationError("NameError", "global name 'unknown_name' is not defined")
pass
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_numbers.py b/pypy/module/test_lib_pypy/ctypes_tests/test_numbers.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_numbers.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_numbers.py
@@ -187,6 +187,14 @@
# probably be changed:
raises(TypeError, c_int, c_long(42))
+ def test_subclass(self):
+ class enum(c_int):
+ def __new__(cls, value):
+ dont_call_me
+ class S(Structure):
+ _fields_ = [('t', enum)]
+ assert isinstance(S().t, enum)
+
## def test_perf(self):
## check_perf()
diff --git a/pypy/module/test_lib_pypy/test_greenlet.py b/pypy/module/test_lib_pypy/test_greenlet.py
--- a/pypy/module/test_lib_pypy/test_greenlet.py
+++ b/pypy/module/test_lib_pypy/test_greenlet.py
@@ -134,6 +134,40 @@
res = g1.switch()
assert res == "ok"
+ def test_throw_GreenletExit(self):
+ from greenlet import greenlet
+ gmain = greenlet.getcurrent()
+ l = [0]
+ #
+ def func():
+ l[0] += 1
+ gmain.switch()
+ l[0] += 1
+ #
+ g = greenlet(func)
+ g.switch()
+ assert l[0] == 1
+ g.throw()
+ assert l[0] == 1
+
+ def test_throw_GreenletExit_result(self):
+ from greenlet import greenlet
+ gmain = greenlet.getcurrent()
+ l = [0]
+ #
+ def func():
+ l[0] += 1
+ gmain.switch()
+ l[0] += 1
+ #
+ g = greenlet(func)
+ g.switch()
+ assert l[0] == 1
+ ge1 = greenlet.GreenletExit(1, 2, 3)
+ ge2 = g.throw(ge1)
+ assert l[0] == 1
+ assert ge1 is ge2
+
def test_nondefault_parent(self):
from greenlet import greenlet
#
diff --git a/pypy/objspace/flow/flowcontext.py b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -4,10 +4,12 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import pyframe, nestedscope
from pypy.interpreter.argument import ArgumentsForTranslation
+from pypy.interpreter.astcompiler.consts import CO_GENERATOR
+from pypy.interpreter.pycode import PyCode, cpython_code_signature
from pypy.objspace.flow import operation
from pypy.objspace.flow.model import *
-from pypy.objspace.flow.framestate import FrameState
-from pypy.rlib import jit
+from pypy.objspace.flow.framestate import (FrameState, recursively_unflatten,
+ recursively_flatten)
from pypy.tool.stdlib_opcode import host_bytecode_spec
class StopFlowing(Exception):
@@ -28,13 +30,6 @@
self.framestate = framestate
self.dead = False
- def patchframe(self, frame):
- if self.dead:
- raise StopFlowing
- self.framestate.restoreframe(frame)
- return BlockRecorder(self)
-
-
class EggBlock(Block):
# make slots optional, for debugging
if hasattr(Block, '__slots__'):
@@ -45,21 +40,6 @@
self.prevblock = prevblock
self.booloutcome = booloutcome
- def patchframe(self, frame):
- parentblocks = []
- block = self
- while isinstance(block, EggBlock):
- block = block.prevblock
- parentblocks.append(block)
- # parentblocks = [Egg, Egg, ..., Egg, Spam] not including self
- block.patchframe(frame)
- recorder = BlockRecorder(self)
- prevblock = self
- for block in parentblocks:
- recorder = Replayer(block, prevblock.booloutcome, recorder)
- prevblock = block
- return recorder
-
def extravars(self, last_exception=None, last_exc_value=None):
self.last_exception = last_exception
@@ -93,7 +73,6 @@
self.crnt_block.operations.append(operation)
def bytecode_trace(self, ec, frame):
- assert frame is ec.crnt_frame, "seeing an unexpected frame!"
ec.crnt_offset = frame.last_instr # save offset for opcode
if self.enterspamblock:
# If we have a SpamBlock, the first call to bytecode_trace()
@@ -110,7 +89,7 @@
# the same block. We will continue, to figure out where the next
# such operation *would* appear, and we make a join point just
# before.
- self.last_join_point = FrameState(frame)
+ self.last_join_point = frame.getstate()
def guessbool(self, ec, w_condition, cases=[False,True],
replace_last_variable_except_in_first_case = None):
@@ -184,43 +163,24 @@
class FlowExecutionContext(ExecutionContext):
- def __init__(self, space, code, globals, constargs={}, outer_func=None,
- name=None, is_generator=False):
- ExecutionContext.__init__(self, space)
- self.code = code
-
- self.w_globals = w_globals = space.wrap(globals)
-
- self.crnt_offset = -1
- self.crnt_frame = None
- if outer_func and outer_func.closure:
- self.closure = [nestedscope.Cell(Constant(value))
- for value in outer_func.closure]
- else:
- self.closure = None
- frame = self.create_frame()
- formalargcount = code.getformalargcount()
- arg_list = [Variable() for i in range(formalargcount)]
- for position, value in constargs.items():
- arg_list[position] = Constant(value)
- frame.setfastscope(arg_list)
- self.joinpoints = {}
- initialblock = SpamBlock(FrameState(frame).copy())
- self.pendingblocks = collections.deque([initialblock])
- self.graph = FunctionGraph(name or code.co_name, initialblock)
- self.is_generator = is_generator
+ def _init_graph(self, func, initialblock):
+ # CallableFactory.pycall may add class_ to functions that are methods
+ name = func.func_name
+ class_ = getattr(func, 'class_', None)
+ if class_ is not None:
+ name = '%s.%s' % (class_.__name__, name)
+ for c in "<>&!":
+ name = name.replace(c, '_')
+ self.graph = graph = FunctionGraph(name, initialblock)
+ graph.func = func
+ # attach a signature and defaults to the graph
+ # so that it becomes even more interchangeable with the function
+ # itself
+ graph.signature = self.code.signature()
+ graph.defaults = func.func_defaults or ()
make_link = Link # overridable for transition tracking
- def create_frame(self):
- # create an empty frame suitable for the code object
- # while ignoring any operation like the creation of the locals dict
- self.recorder = []
- frame = FlowSpaceFrame(self.space, self.code,
- self.w_globals, self)
- frame.last_instr = 0
- return frame
-
def bytecode_trace(self, frame):
self.recorder.bytecode_trace(self, frame)
@@ -247,33 +207,40 @@
w_exc_cls = egg.last_exception
return outcome, w_exc_cls, w_exc_value
- def build_flow(self):
+ def build_flow(self, func, constargs={}):
+ space = self.space
+ code = PyCode._from_code(space, func.func_code)
+ self.is_generator = bool(code.co_flags & CO_GENERATOR)
+ self.code = code
+
+ self.crnt_offset = -1
+ self.frame = frame = FlowSpaceFrame(self.space, code,
+ func, constargs)
+ self.joinpoints = {}
+ initialblock = SpamBlock(frame.getstate())
+ self.pendingblocks = collections.deque([initialblock])
+ self._init_graph(func, initialblock)
+
if self.is_generator:
- self.produce_generator_mark()
+ initialblock.operations.append(
+ SpaceOperation('generator_mark', [], Variable()))
+
while self.pendingblocks:
block = self.pendingblocks.popleft()
- frame = self.create_frame()
try:
- self.recorder = block.patchframe(frame)
+ self.recorder = frame.recording(block)
except StopFlowing:
continue # restarting a dead SpamBlock
try:
- old_frameref = self.topframeref
- self.topframeref = jit.non_virtual_ref(frame)
- self.crnt_frame = frame
- try:
- frame.frame_finished_execution = False
- while True:
- w_result = frame.dispatch(frame.pycode,
- frame.last_instr,
- self)
- if frame.frame_finished_execution:
- break
- else:
- self.generate_yield(frame, w_result)
- finally:
- self.crnt_frame = None
- self.topframeref = old_frameref
+ frame.frame_finished_execution = False
+ while True:
+ w_result = frame.dispatch(frame.pycode,
+ frame.last_instr,
+ self)
+ if frame.frame_finished_execution:
+ break
+ else:
+ self.generate_yield(frame, w_result)
except operation.OperationThatShouldNotBePropagatedError, e:
raise Exception(
@@ -316,11 +283,6 @@
del self.recorder
self.fixeggblocks()
- def produce_generator_mark(self):
- [initialblock] = self.pendingblocks
- initialblock.operations.append(
- SpaceOperation('generator_mark', [], Variable()))
-
def generate_yield(self, frame, w_result):
assert self.is_generator
self.recorder.crnt_block.operations.append(
@@ -408,7 +370,7 @@
# hack for unrolling iterables, don't use this
def replace_in_stack(self, oldvalue, newvalue):
w_new = Constant(newvalue)
- f = self.crnt_frame
+ f = self.frame
stack_items_w = f.locals_stack_w
for i in range(f.valuestackdepth-1, f.pycode.co_nlocals-1, -1):
w_v = stack_items_w[i]
@@ -421,6 +383,71 @@
class FlowSpaceFrame(pyframe.CPythonFrame):
+ def __init__(self, space, code, func, constargs=None):
+ w_globals = Constant(func.func_globals)
+ class outerfunc: pass # hack
+ if func.func_closure is not None:
+ cl = [c.cell_contents for c in func.func_closure]
+ outerfunc.closure = [nestedscope.Cell(Constant(value)) for value in cl]
+ else:
+ outerfunc.closure = None
+ super(FlowSpaceFrame, self).__init__(space, code, w_globals, outerfunc)
+ self.last_instr = 0
+
+ if constargs is None:
+ constargs = {}
+ formalargcount = code.getformalargcount()
+ arg_list = [Variable() for i in range(formalargcount)]
+ for position, value in constargs.items():
+ arg_list[position] = Constant(value)
+ self.setfastscope(arg_list)
+
+ def getstate(self):
+ # getfastscope() can return real None, for undefined locals
+ data = self.save_locals_stack()
+ if self.last_exception is None:
+ data.append(Constant(None))
+ data.append(Constant(None))
+ else:
+ data.append(self.last_exception.w_type)
+ data.append(self.last_exception.get_w_value(self.space))
+ recursively_flatten(self.space, data)
+ nonmergeable = (self.get_blocklist(),
+ self.last_instr, # == next_instr when between bytecodes
+ self.w_locals,)
+ return FrameState(data, nonmergeable)
+
+ def setstate(self, state):
+ """ Reset the frame to the given state. """
+ data = state.mergeable[:]
+ recursively_unflatten(self.space, data)
+ self.restore_locals_stack(data[:-2]) # Nones == undefined locals
+ if data[-2] == Constant(None):
+ assert data[-1] == Constant(None)
+ self.last_exception = None
+ else:
+ self.last_exception = OperationError(data[-2], data[-1])
+ blocklist, self.last_instr, self.w_locals = state.nonmergeable
+ self.set_blocklist(blocklist)
+
+ def recording(self, block):
+ """ Setup recording of the block and return the recorder. """
+ parentblocks = []
+ parent = block
+ while isinstance(parent, EggBlock):
+ parent = parent.prevblock
+ parentblocks.append(parent)
+ # parentblocks = [Egg, Egg, ..., Egg, Spam] not including block
+ if parent.dead:
+ raise StopFlowing
+ self.setstate(parent.framestate)
+ recorder = BlockRecorder(block)
+ prevblock = block
+ for parent in parentblocks:
+ recorder = Replayer(parent, prevblock.booloutcome, recorder)
+ prevblock = parent
+ return recorder
+
def SETUP_WITH(self, offsettoend, next_instr):
# A simpler version than the 'real' 2.7 one:
# directly call manager.__enter__(), don't use special lookup functions
diff --git a/pypy/objspace/flow/framestate.py b/pypy/objspace/flow/framestate.py
--- a/pypy/objspace/flow/framestate.py
+++ b/pypy/objspace/flow/framestate.py
@@ -1,59 +1,16 @@
-from pypy.interpreter.pyframe import PyFrame
from pypy.interpreter.pyopcode import SuspendedUnroller
-from pypy.interpreter.error import OperationError
from pypy.rlib.unroll import SpecTag
from pypy.objspace.flow.model import *
class FrameState:
- # XXX this class depends on the internal state of PyFrame objects
-
- def __init__(self, state):
- if isinstance(state, PyFrame):
- # getfastscope() can return real None, for undefined locals
- data = state.save_locals_stack()
- if state.last_exception is None:
- data.append(Constant(None))
- data.append(Constant(None))
- else:
- data.append(state.last_exception.w_type)
- data.append(state.last_exception.get_w_value(state.space))
- recursively_flatten(state.space, data)
- self.mergeable = data
- self.nonmergeable = (
- state.get_blocklist(),
- state.last_instr, # == next_instr when between bytecodes
- state.w_locals,
- )
- elif isinstance(state, tuple):
- self.mergeable, self.nonmergeable = state
- else:
- raise TypeError("can't get framestate for %r" %
- state.__class__.__name__)
+ def __init__(self, mergeable, nonmergeable):
+ self.mergeable = mergeable
+ self.nonmergeable = nonmergeable
self.next_instr = self.nonmergeable[1]
for w1 in self.mergeable:
assert isinstance(w1, (Variable, Constant)) or w1 is None, (
'%r found in frame state' % w1)
- def restoreframe(self, frame):
- if isinstance(frame, PyFrame):
- data = self.mergeable[:]
- recursively_unflatten(frame.space, data)
- frame.restore_locals_stack(data[:-2]) # Nones == undefined locals
- if data[-2] == Constant(None):
- assert data[-1] == Constant(None)
- frame.last_exception = None
- else:
- frame.last_exception = OperationError(data[-2], data[-1])
- (
- blocklist,
- frame.last_instr,
- frame.w_locals,
- ) = self.nonmergeable
- frame.set_blocklist(blocklist)
- else:
- raise TypeError("can't set framestate for %r" %
- frame.__class__.__name__)
-
def copy(self):
"Make a copy of this state in which all Variables are fresh."
newstate = []
@@ -61,7 +18,7 @@
if isinstance(w, Variable):
w = Variable()
newstate.append(w)
- return FrameState((newstate, self.nonmergeable))
+ return FrameState(newstate, self.nonmergeable)
def getvariables(self):
return [w for w in self.mergeable if isinstance(w, Variable)]
@@ -94,7 +51,7 @@
newstate.append(union(w1, w2))
except UnionError:
return None
- return FrameState((newstate, self.nonmergeable))
+ return FrameState(newstate, self.nonmergeable)
def getoutputargs(self, targetstate):
"Return the output arguments needed to link self to targetstate."
diff --git a/pypy/objspace/flow/objspace.py b/pypy/objspace/flow/objspace.py
--- a/pypy/objspace/flow/objspace.py
+++ b/pypy/objspace/flow/objspace.py
@@ -5,13 +5,12 @@
import types
from pypy.tool import error
from pypy.interpreter.baseobjspace import ObjSpace, Wrappable
-from pypy.interpreter.pycode import PyCode, cpython_code_signature
from pypy.interpreter.module import Module
from pypy.interpreter.error import OperationError
-from pypy.interpreter.astcompiler.consts import CO_GENERATOR
from pypy.interpreter import pyframe, argument
from pypy.objspace.flow.model import *
-from pypy.objspace.flow import flowcontext, operation, specialcase
+from pypy.objspace.flow import flowcontext, operation
+from pypy.objspace.flow.specialcase import SPECIAL_CASES
from pypy.rlib.unroll import unrolling_iterable, _unroller
from pypy.rlib import rstackovf, rarithmetic
from pypy.rlib.rarithmetic import is_valid_int
@@ -76,7 +75,7 @@
for exc in [NameError, UnboundLocalError]:
clsname = exc.__name__
setattr(self, 'w_'+clsname, None)
- self.specialcases = {}
+ self.specialcases = SPECIAL_CASES.copy()
#self.make_builtins()
#self.make_sys()
# w_str is needed because cmp_exc_match of frames checks against it,
@@ -162,7 +161,7 @@
if type(val) is not str:
raise TypeError("expected string: " + repr(w_obj))
return val
- return self.unwrap(w_obj)
+ return self.unwrap(w_obj)
def float_w(self, w_obj):
if isinstance(w_obj, Constant):
@@ -220,10 +219,6 @@
# because it is done each time a FlowExecutionContext is built
return None
- def setup_executioncontext(self, ec):
- self.executioncontext = ec
- specialcase.setup(self)
-
def exception_match(self, w_exc_type, w_check_class):
try:
check_class = self.unwrap(w_check_class)
@@ -260,36 +255,11 @@
"""
if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'):
raise Exception, "%r is tagged as NOT_RPYTHON" % (func,)
- code = func.func_code
- is_generator = bool(code.co_flags & CO_GENERATOR)
- code = PyCode._from_code(self, code)
- if func.func_closure is None:
- cl = None
- else:
- cl = [extract_cell_content(c) for c in func.func_closure]
- # CallableFactory.pycall may add class_ to functions that are methods
- name = func.func_name
- class_ = getattr(func, 'class_', None)
- if class_ is not None:
- name = '%s.%s' % (class_.__name__, name)
- for c in "<>&!":
- name = name.replace(c, '_')
- class outerfunc: # hack
- closure = cl
- ec = flowcontext.FlowExecutionContext(self, code, func.func_globals,
- constargs, outerfunc, name,
- is_generator)
- graph = ec.graph
- graph.func = func
- # attach a signature and defaults to the graph
- # so that it becomes even more interchangeable with the function
- # itself
- graph.signature = cpython_code_signature(code)
- graph.defaults = func.func_defaults or ()
- self.setup_executioncontext(ec)
+ ec = flowcontext.FlowExecutionContext(self)
+ self.executioncontext = ec
try:
- ec.build_flow()
+ ec.build_flow(func, constargs)
except error.FlowingError, a:
# attach additional source info to AnnotatorError
_, _, tb = sys.exc_info()
@@ -297,12 +267,12 @@
str(a))
e = error.FlowingError(formated)
raise error.FlowingError, e, tb
+
+ graph = ec.graph
checkgraph(graph)
- #
- if is_generator and tweak_for_generator:
+ if ec.is_generator and tweak_for_generator:
from pypy.translator.generator import tweak_generator_graph
tweak_generator_graph(graph)
- #
return graph
def fixedview(self, w_tuple, expected_length=None):
@@ -325,7 +295,7 @@
e = OperationError(self.w_ValueError, self.w_None)
e.normalize_exception(self)
raise e
- return [self.do_operation('getitem', w_iterable, self.wrap(i))
+ return [self.do_operation('getitem', w_iterable, self.wrap(i))
for i in range(expected_length)]
return ObjSpace.unpackiterable(self, w_iterable, expected_length)
@@ -391,6 +361,11 @@
return w_item
def setitem(self, w_obj, w_key, w_val):
+ # protect us from globals write access
+ ec = self.getexecutioncontext()
+ if ec and w_obj is ec.frame.w_globals:
+ raise SyntaxError("attempt to modify global attribute %r in %r"
+ % (w_key, ec.graph.func))
if self.concrete_mode:
try:
obj = self.unwrap_for_computation(w_obj)
@@ -400,9 +375,38 @@
return self.w_None
except UnwrapException:
pass
- return self.do_operation_with_implicit_exceptions('setitem', w_obj,
+ return self.do_operation_with_implicit_exceptions('setitem', w_obj,
w_key, w_val)
+ def getattr(self, w_obj, w_name):
+ # handling special things like sys
+ # unfortunately this will never vanish with a unique import logic :-(
+ if w_obj in self.not_really_const:
+ const_w = self.not_really_const[w_obj]
+ if w_name not in const_w:
+ return self.do_operation_with_implicit_exceptions('getattr',
+ w_obj, w_name)
+ try:
+ obj = self.unwrap_for_computation(w_obj)
+ name = self.unwrap_for_computation(w_name)
+ except UnwrapException:
+ pass
+ else:
+ try:
+ result = getattr(obj, name)
+ except Exception, e:
+ etype = e.__class__
+ msg = "generated by a constant operation:\n\t%s%r" % (
+ 'getattr', (obj, name))
+ raise operation.OperationThatShouldNotBePropagatedError(
+ self.wrap(etype), self.wrap(msg))
+ try:
+ return self.wrap(result)
+ except WrapException:
+ pass
+ return self.do_operation_with_implicit_exceptions('getattr',
+ w_obj, w_name)
+
def call_function(self, w_func, *args_w):
nargs = len(args_w)
args = argument.ArgumentsForTranslation(self, list(args_w))
@@ -487,28 +491,3 @@
"flow graph construction")
w_RuntimeError = prebuilt_recursion_error = property(w_RuntimeError)
operation.add_operations(FlowObjSpace)
-
-
-def extract_cell_content(c):
- """Get the value contained in a CPython 'cell', as read through
- the func_closure of a function object."""
- try:
- # This is simple on 2.5
- return getattr(c, "cell_contents")
- except AttributeError:
- class X(object):
- def __cmp__(self, other):
- self.other = other
- return 0
- def __eq__(self, other):
- self.other = other
- return True
- x = X()
- x_cell, = (lambda: x).func_closure
- x_cell == c
- try:
- return x.other # crashes if the cell is actually empty
- except AttributeError:
- raise ValueError("empty cell")
-# ______________________________________________________________________
-# End of objspace.py
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -378,45 +378,7 @@
setattr(fs, name, generic_operator)
-"""
-This is just a placeholder for some code I'm checking in elsewhere.
-It is provenly possible to determine constantness of certain expressions
-a little later. I introduced this a bit too early, together with tieing
-this to something being global, which was a bad idea.
-The concept is still valid, and it can be used to force something to
-be evaluated immediately because it is supposed to be a constant.
-One good possible use of this is loop unrolling.
-This will be found in an 'experimental' folder with some use cases.
-"""
-
-def special_overrides(fs):
- def getattr(self, w_obj, w_name):
- # handling special things like sys
- # unfortunately this will never vanish with a unique import logic :-(
- if w_obj in self.not_really_const:
- const_w = self.not_really_const[w_obj]
- if w_name not in const_w:
- return self.do_operation_with_implicit_exceptions('getattr',
- w_obj, w_name)
- return self.regular_getattr(w_obj, w_name)
-
- fs.regular_getattr = fs.getattr
- fs.getattr = getattr
-
- # protect us from globals write access
- def setitem(self, w_obj, w_key, w_val):
- ec = self.getexecutioncontext()
- if not (ec and w_obj is ec.w_globals):
- return self.regular_setitem(w_obj, w_key, w_val)
- raise SyntaxError("attempt to modify global attribute %r in %r"
- % (w_key, ec.graph.func))
-
- fs.regular_setitem = fs.setitem
- fs.setitem = setitem
-
-
def add_operations(fs):
"""Add function operations to the flow space."""
for line in ObjSpace.MethodTable:
make_op(fs, *line)
- special_overrides(fs)
diff --git a/pypy/objspace/flow/specialcase.py b/pypy/objspace/flow/specialcase.py
--- a/pypy/objspace/flow/specialcase.py
+++ b/pypy/objspace/flow/specialcase.py
@@ -19,7 +19,7 @@
if len(args_w) > 2:
w_loc = args_w[2]
if len(args_w) > 3:
- w_frm = args_w[3]
+ w_frm = args_w[3]
if not isinstance(w_loc, Constant):
# import * in a function gives us the locals as Variable
# we always forbid it as a SyntaxError
@@ -89,6 +89,9 @@
# _________________________________________________________________________
def sc_r_uint(space, r_uint, args):
+ # special case to constant-fold r_uint(32-bit-constant)
+ # (normally, the 32-bit constant is a long, and is not allowed to
+ # show up in the flow graphs at all)
args_w, kwds_w = args.unpack()
assert not kwds_w
[w_value] = args_w
@@ -99,20 +102,8 @@
def sc_we_are_translated(space, we_are_translated, args):
return Constant(True)
-def setup(space):
- # fn = pyframe.normalize_exception.get_function(space)
- # this is now routed through the objspace, directly.
- # space.specialcases[fn] = sc_normalize_exception
- space.specialcases[__import__] = sc_import
- # redirect ApplevelClass for print et al.
- space.specialcases[ApplevelClass] = sc_applevel
- # turn calls to built-in functions to the corresponding operation,
- # if possible
- for fn in OperationName:
- space.specialcases[fn] = sc_operator
- # special case to constant-fold r_uint(32-bit-constant)
- # (normally, the 32-bit constant is a long, and is not allowed to
- # show up in the flow graphs at all)
- space.specialcases[r_uint] = sc_r_uint
- # special case we_are_translated() to return True
- space.specialcases[we_are_translated] = sc_we_are_translated
+SPECIAL_CASES = {__import__: sc_import, ApplevelClass: sc_applevel,
+ r_uint: sc_r_uint, we_are_translated: sc_we_are_translated}
+for fn in OperationName:
+ SPECIAL_CASES[fn] = sc_operator
+
diff --git a/pypy/objspace/flow/test/test_framestate.py b/pypy/objspace/flow/test/test_framestate.py
--- a/pypy/objspace/flow/test/test_framestate.py
+++ b/pypy/objspace/flow/test/test_framestate.py
@@ -1,14 +1,13 @@
-
-
from py.test import raises
from pypy.objspace.flow.model import *
-from pypy.objspace.flow.framestate import *
from pypy.interpreter.pycode import PyCode
+from pypy.rlib.unroll import SpecTag
from pypy.objspace.flow.objspace import FlowObjSpace
+from pypy.objspace.flow.flowcontext import FlowSpaceFrame
class TestFrameState:
def setup_class(cls):
- cls.space = FlowObjSpace()
+ cls.space = FlowObjSpace()
def getframe(self, func):
space = self.space
@@ -18,15 +17,9 @@
pass
code = func.func_code
code = PyCode._from_code(self.space, code)
- w_globals = Constant({}) # space.newdict()
- frame = self.space.createframe(code, w_globals)
-
- formalargcount = code.getformalargcount()
- dummy = Constant(None)
- #dummy.dummy = True
- arg_list = ([Variable() for i in range(formalargcount)] +
- [dummy] * (frame.pycode.co_nlocals - formalargcount))
- frame.setfastscope(arg_list)
+ frame = FlowSpaceFrame(space, code, func)
+ # hack the frame
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(None)
return frame
def func_simple(x):
@@ -35,55 +28,55 @@
def test_eq_framestate(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
- fs2 = FrameState(frame)
+ fs1 = frame.getstate()
+ fs2 = frame.getstate()
assert fs1 == fs2
def test_neq_hacked_framestate(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
assert fs1 != fs2
def test_union_on_equal_framestates(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
- fs2 = FrameState(frame)
+ fs1 = frame.getstate()
+ fs2 = frame.getstate()
assert fs1.union(fs2) == fs1
def test_union_on_hacked_framestates(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
assert fs1.union(fs2) == fs2 # fs2 is more general
assert fs2.union(fs1) == fs2 # fs2 is more general
def test_restore_frame(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs1.restoreframe(frame)
- assert fs1 == FrameState(frame)
+ frame.setstate(fs1)
+ assert fs1 == frame.getstate()
def test_copy(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
fs2 = fs1.copy()
assert fs1 == fs2
def test_getvariables(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
vars = fs1.getvariables()
- assert len(vars) == 1
+ assert len(vars) == 1
def test_getoutputargs(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
outputargs = fs1.getoutputargs(fs2)
# 'x' -> 'x' is a Variable
# locals_w[n-1] -> locals_w[n-1] is Constant(None)
@@ -91,17 +84,17 @@
def test_union_different_constants(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(42)
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
fs3 = fs1.union(fs2)
- fs3.restoreframe(frame)
+ frame.setstate(fs3)
assert isinstance(frame.locals_stack_w[frame.pycode.co_nlocals-1],
Variable) # generalized
def test_union_spectag(self):
frame = self.getframe(self.func_simple)
- fs1 = FrameState(frame)
+ fs1 = frame.getstate()
frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(SpecTag())
- fs2 = FrameState(frame)
+ fs2 = frame.getstate()
assert fs1.union(fs2) is None # UnionError
diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -32,8 +32,8 @@
if conftest.option.view:
graph.show()
- def setup_class(cls):
- cls.space = FlowObjSpace()
+ def setup_class(cls):
+ cls.space = FlowObjSpace()
def all_operations(self, graph):
result = {}
@@ -77,7 +77,7 @@
if i < 0:
i = j
return user_defined_function(i) + 1
-
+
def test_ifthenelse(self):
x = self.codetest(self.ifthenelse)
@@ -96,7 +96,7 @@
#__________________________________________________________
def print_(i):
print i
-
+
def test_print(self):
x = self.codetest(self.print_)
@@ -124,7 +124,7 @@
if i:
i = 5
return i
-
+
def test_union_hard(self):
x = self.codetest(self.union_hard)
@@ -135,7 +135,7 @@
total += i
i = i - 1
return total
-
+
def test_while_union(self):
x = self.codetest(self.while_union)
@@ -145,7 +145,7 @@
for i in lst:
total += i
return total
-
+
def test_simple_for(self):
x = self.codetest(self.simple_for)
@@ -311,7 +311,7 @@
else:
found[link.exitcase] = None
assert found == {IndexError: True, KeyError: True, Exception: None}
-
+
def reraiseAnything(x):
try:
pow(x, 5)
@@ -354,7 +354,7 @@
#__________________________________________________________
def raise1(msg):
raise IndexError
-
+
def test_raise1(self):
x = self.codetest(self.raise1)
simplify_graph(x)
@@ -371,7 +371,7 @@
#__________________________________________________________
def raise2(msg):
raise IndexError, msg
-
+
def test_raise2(self):
x = self.codetest(self.raise2)
# XXX can't check the shape of the graph, too complicated...
@@ -379,7 +379,7 @@
#__________________________________________________________
def raise3(msg):
raise IndexError(msg)
-
+
def test_raise3(self):
x = self.codetest(self.raise3)
# XXX can't check the shape of the graph, too complicated...
@@ -387,7 +387,7 @@
#__________________________________________________________
def raise4(stuff):
raise stuff
-
+
def test_raise4(self):
x = self.codetest(self.raise4)
@@ -405,7 +405,7 @@
except IndexError:
return -1
return 0
-
+
def test_raise_and_catch_1(self):
x = self.codetest(self.raise_and_catch_1)
@@ -416,7 +416,7 @@
except IndexError:
return -1
return 0
-
+
def test_catch_simple_call(self):
x = self.codetest(self.catch_simple_call)
@@ -427,7 +427,7 @@
except (IndexError, OSError):
return -1
return 0
-
+
def test_multiple_catch_simple_call(self):
graph = self.codetest(self.multiple_catch_simple_call)
simplify_graph(graph)
@@ -447,7 +447,7 @@
del x
for i in range(10):
pass
-
+
def test_dellocal(self):
x = self.codetest(self.dellocal)
@@ -456,7 +456,7 @@
x = DATA['x']
z = DATA[name]
return x, z
-
+
def test_globalconstdict(self):
x = self.codetest(self.globalconstdict)
@@ -464,12 +464,12 @@
def dictliteral(name):
x = {'x': 1}
return x
-
+
def test_dictliteral(self):
x = self.codetest(self.dictliteral)
#__________________________________________________________
-
+
def specialcases(x):
operator.lt(x,3)
operator.le(x,3)
@@ -488,7 +488,7 @@
# the following ones are constant-folded
operator.eq(2,3)
operator.__gt__(2,3)
-
+
def test_specialcases(self):
x = self.codetest(self.specialcases)
from pypy.translator.simplify import join_blocks
@@ -765,7 +765,7 @@
raise
graph = self.codetest(f)
simplify_graph(graph)
- assert self.all_operations(graph) == {'getitem_idx': 1}
+ assert self.all_operations(graph) == {'getitem_idx': 1}
def f(c, x):
try:
@@ -775,7 +775,7 @@
graph = self.codetest(f)
simplify_graph(graph)
assert self.all_operations(graph) == {'getitem_key': 1}
-
+
def f(c, x):
try:
return c[x]
@@ -794,7 +794,7 @@
simplify_graph(graph)
self.show(graph)
assert self.all_operations(graph) == {'getitem_idx_key': 1}
-
+
def f(c, x):
try:
return c[x]
@@ -812,7 +812,7 @@
graph = self.codetest(f)
simplify_graph(graph)
assert self.all_operations(graph) == {'getitem_key': 1}
-
+
def f(c, x):
try:
return c[x]
@@ -1004,14 +1004,3 @@
def user_defined_function():
pass
-
-
-def test_extract_cell_content():
- class Strange(object):
- def __cmp__(self, other):
- assert False, "should not be called"
- strange = Strange()
- def f():
- return strange
- res = objspace.extract_cell_content(f.func_closure[0])
- assert res is strange
diff --git a/pypy/rlib/rmarshal.py b/pypy/rlib/rmarshal.py
--- a/pypy/rlib/rmarshal.py
+++ b/pypy/rlib/rmarshal.py
@@ -9,6 +9,7 @@
from pypy.rlib.rarithmetic import r_longlong, intmask, LONG_BIT
from pypy.rlib.rfloat import formatd, rstring_to_float
from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.rstring import assert_str0
class CannotMarshal(Exception):
pass
@@ -223,12 +224,33 @@
return readchr(loader)
add_loader(annmodel.SomeChar(), load_single_char)
+def load_string_nonul(loader):
+ if readchr(loader) != TYPE_STRING:
+ raise ValueError("expected a string")
+ length = readlong(loader)
+ return assert_str0(readstr(loader, length))
+add_loader(annmodel.SomeString(can_be_None=False, no_nul=True),
+ load_string_nonul)
+
def load_string(loader):
if readchr(loader) != TYPE_STRING:
raise ValueError("expected a string")
length = readlong(loader)
return readstr(loader, length)
-add_loader(annmodel.SomeString(can_be_None=False), load_string)
+add_loader(annmodel.SomeString(can_be_None=False, no_nul=False),
+ load_string)
+
+def load_string_or_none_nonul(loader):
+ t = readchr(loader)
+ if t == TYPE_STRING:
+ length = readlong(loader)
+ return assert_str0(readstr(loader, length))
+ elif t == TYPE_NONE:
+ return None
+ else:
+ raise ValueError("expected a string or None")
+add_loader(annmodel.SomeString(can_be_None=True, no_nul=True),
+ load_string_or_none_nonul)
def load_string_or_none(loader):
t = readchr(loader)
@@ -239,7 +261,8 @@
return None
else:
raise ValueError("expected a string or None")
-add_loader(annmodel.SomeString(can_be_None=True), load_string_or_none)
+add_loader(annmodel.SomeString(can_be_None=True, no_nul=False),
+ load_string_or_none)
# ____________________________________________________________
#
diff --git a/pypy/translator/backendopt/removeassert.py b/pypy/translator/backendopt/removeassert.py
--- a/pypy/translator/backendopt/removeassert.py
+++ b/pypy/translator/backendopt/removeassert.py
@@ -41,7 +41,19 @@
log.removeassert("removed %d asserts in %s" % (count, graph.name))
checkgraph(graph)
#transform_dead_op_vars(graph, translator)
- log.removeassert("Could not remove %d asserts, but removed %d asserts." % tuple(total_count))
+ total_count = tuple(total_count)
+ if total_count[0] == 0:
+ if total_count[1] == 0:
+ msg = None
+ else:
+ msg = "Removed %d asserts" % (total_count[1],)
+ else:
+ if total_count[1] == 0:
+ msg = "Could not remove %d asserts" % (total_count[0],)
+ else:
+ msg = "Could not remove %d asserts, but removed %d asserts." % total_count
+ if msg is not None:
+ log.removeassert(msg)
def kill_assertion_link(graph, link):
diff --git a/pypy/translator/sandbox/test/test_sandbox.py b/pypy/translator/sandbox/test/test_sandbox.py
--- a/pypy/translator/sandbox/test/test_sandbox.py
+++ b/pypy/translator/sandbox/test/test_sandbox.py
@@ -21,7 +21,8 @@
g.flush()
def compile(f, gc='ref'):
- t = Translation(f, backend='c', standalone=True, sandbox=True, gc=gc)
+ t = Translation(f, backend='c', standalone=True, sandbox=True, gc=gc,
+ check_str_without_nul=True)
return str(t.compile())
@@ -115,6 +116,21 @@
f.close()
assert tail == ""
+def test_getcwd():
+ def entry_point(argv):
+ t = os.getcwd()
+ os.dup(len(t))
+ return 0
+
+ exe = compile(entry_point)
+ g, f = os.popen2(exe, "t", 0)
+ expect(f, g, "ll_os.ll_os_getcwd", (), "/tmp/foo/bar")
+ expect(f, g, "ll_os.ll_os_dup", (len("/tmp/foo/bar"),), 3)
+ g.close()
+ tail = f.read()
+ f.close()
+ assert tail == ""
+
def test_oserror():
def entry_point(argv):
try:
diff --git a/pypy/translator/unsimplify.py b/pypy/translator/unsimplify.py
--- a/pypy/translator/unsimplify.py
+++ b/pypy/translator/unsimplify.py
@@ -102,7 +102,14 @@
# then it's ok to recreate its value in the target block.
# If not, then we have a problem :-)
from pypy.rpython.lltypesystem import lltype
- assert v.concretetype is lltype.Void
+ if v.concretetype is not lltype.Void:
+ raise Exception(
+ "The variable %r of type %r was not explicitly listed"
+ " in _forcelink. This issue can be caused by a"
+ " jitdriver.jit_merge_point() where some variable"
+ " containing an int or str or instance is actually"
+ " known to be constant, e.g. always 42." % (
+ v, v.concretetype))
c = Constant(None, lltype.Void)
w = varmap[v]
newop = SpaceOperation('same_as', [c], w)
More information about the pypy-commit
mailing list