[pypy-svn] r28155 - in pypy/dist/pypy: rpython translator/stackless translator/stackless/test
mwh at codespeak.net
mwh at codespeak.net
Sat Jun 3 13:47:15 CEST 2006
Author: mwh
Date: Sat Jun 3 13:47:02 2006
New Revision: 28155
Modified:
pypy/dist/pypy/rpython/rstack.py
pypy/dist/pypy/translator/stackless/code.py
pypy/dist/pypy/translator/stackless/test/test_resume_point.py
pypy/dist/pypy/translator/stackless/transform.py
Log:
(pedronis, mwh)
Reenable the first resume_point test.
Most/all of the code from the branch is now on the trunk, but a little
saner.
Some refactorings were necessary for sanity + a couple bugfixes.
Modified: pypy/dist/pypy/rpython/rstack.py
==============================================================================
--- pypy/dist/pypy/rpython/rstack.py (original)
+++ pypy/dist/pypy/rpython/rstack.py Sat Jun 3 13:47:02 2006
@@ -86,12 +86,12 @@
c_label = hop.inputconst(lltype.Void, hop.args_s[1].const)
r = SimplePointerRepr(lltype.Ptr(STATE_HEADER))
- state_v = hop.inputarg(r, arg=0)
+ v_state = hop.inputarg(r, arg=0)
args_v = hop.args_v[2:]
hop.exception_is_here()
- return hop.genop('resume_state_create', [c_label] + args_v,
+ return hop.genop('resume_state_create', [v_state, c_label] + args_v,
hop.r_result)
class ResumeStateEntry(ExtRegistryEntry):
@@ -116,7 +116,7 @@
def specialize_call(self, hop, **kwds_i):
from pypy.rpython.lltypesystem import lltype
- v_state = hop.args_v[0]
+ v_state = hop.args_v[1]
if 'i_returns' in kwds_i:
assert len(kwds_i) == 1
Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py (original)
+++ pypy/dist/pypy/translator/stackless/code.py Sat Jun 3 13:47:02 2006
@@ -181,6 +181,38 @@
INDEX_CAPTURE = frame.RestartInfo.add_prebuilt(ll_stack_capture,
[EMPTY_STATE])
+RESUME_AFTER_STATE = frame.make_state_header_type('resume_after_state',
+ ('c', lltype.Ptr(STATE_HEADER)),)
+
+def resume_after_void(state, retvalue):
+ if global_state.restart_substate == -1:
+ # normal entry point for a call to state.switch()
+ # first unwind the stack
+ u = UnwindException()
+ s = lltype.malloc(RESUME_AFTER_STATE)
+ s.header.f_restart = INDEX_RESUME_AFTER_VOID
+ s.c = state
+ add_frame_state(u, s.header)
+ raise u
+ elif global_state.restart_substate == 0:
+ # STATE 0: we didn't do anything so far, but the stack is unwound
+ global_state.restart_substate = -1
+ # grab the frame corresponding to ourself
+ # the 'targetstate' local is garbage here, it must be read back from
+ # 's.c' where we saved it by the normal entry point above
+ mystate = global_state.top
+ s = lltype.cast_pointer(lltype.Ptr(RESUME_AFTER_STATE), mystate)
+ targetstate = s.c
+ targetstate.f_back = mystate.f_back
+ global_state.top = targetstate
+ raise UnwindException()
+ else:
+ return 0
+
+resume_after_void.stackless_explicit = True
+INDEX_RESUME_AFTER_VOID = frame.RestartInfo.add_prebuilt(resume_after_void,
+ [RESUME_AFTER_STATE,
+ EMPTY_STATE])
# ____________________________________________________________
class StacklessData:
Modified: pypy/dist/pypy/translator/stackless/test/test_resume_point.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_resume_point.py (original)
+++ pypy/dist/pypy/translator/stackless/test/test_resume_point.py Sat Jun 3 13:47:02 2006
@@ -25,9 +25,9 @@
state = rstack.resume_state_create(None, "rp0", one(), one()+one()+one())
v2 = rstack.resume_state_invoke(int, state)
return v1*10 + v2
- transform_stackless_function(example)
-## res = llinterp_stackless_function(example, assert_unwind=False)
-## assert res == 24
+## transform_stackless_function(example)
+ res = llinterp_stackless_function(example, assert_unwind=False)
+ assert res == 24
def test_call():
def g(x,y):
Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py (original)
+++ pypy/dist/pypy/translator/stackless/transform.py Sat Jun 3 13:47:02 2006
@@ -12,6 +12,7 @@
from pypy.rpython.rbuiltin import gen_cast
from pypy.rpython.rtyper import LowLevelOpList
from pypy.rpython.module import ll_stackless, ll_stack
+from pypy.rpython.objectmodel import ComputedIntSymbolic
from pypy.translator.backendopt import graphanalyze
from pypy.translator.stackless.frame import SAVED_REFERENCE, STORAGE_TYPES
@@ -54,6 +55,15 @@
# abort()
# return retval + x + 1
+class SymbolicRestartNumber(ComputedIntSymbolic):
+ def __init__(self, value=None):
+ ComputedIntSymbolic.__init__(self, self._getvalue)
+ self.value = value
+
+ def _getvalue(self):
+ assert self.value is not None
+ return self.value
+
class ResumePoint:
def __init__(self, var_result, args, links_to_resumption,
frame_state_type, fieldnames):
@@ -223,6 +233,11 @@
self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc(
code.yield_current_frame_to_caller, [], s_StatePtr)
+ self.resume_after_void_ptr = mixlevelannotator.constfunc(
+ code.resume_after_void, [annmodel.SomePtr(lltype.Ptr(STATE_HEADER)),
+ annmodel.s_None],
+ annmodel.SomeInteger())
+
mixlevelannotator.finish()
s_global_state = bk.immutablevalue(code.global_state)
@@ -244,7 +259,8 @@
self.is_finished = False
- self.explicit_resume_points = {}
+ #self.explicit_resume_points = {}
+ self.symbolic_restart_numbers = {}
# register the prebuilt restartinfos
for restartinfo in frame.RestartInfo.prebuilt:
@@ -404,6 +420,96 @@
new_start_block.isstartblock = True
graph.startblock = new_start_block
+ def handle_resume_point(self, block, i):
+ # in some circumstances we might be able to reuse
+ # an already inserted resume point
+ op = block.operations[i]
+ if i == len(block.operations) - 1:
+ link = block.exits[0]
+ else:
+ link = support.split_block_with_keepalive(block, i+1)
+ parms = op.args[1:]
+ if not isinstance(parms[0], model.Variable):
+ assert parms[0].value is None
+ parms[0] = None
+ args = vars_to_save(block)
+ for a in args:
+ if a not in parms:
+ raise Exception, "not covered needed value at resume_point"
+ if parms[0] is not None: # returns= case
+ res = parms[0]
+ args = [arg for arg in args if arg is not res]
+ else:
+ args = args
+ res = op.result
+
+ (frame_type,
+ fieldnames) = self.frametyper.frame_type_for_vars(parms[1:])
+
+ self.resume_points.append(
+ ResumePoint(res, parms[1:], tuple(block.exits),
+ frame_type, fieldnames))
+
+ label = op.args[0].value
+
+ restart_number = len(self.masterarray1) + len(self.resume_points)-1
+
+## assert label not in self.explicit_resume_points
+## self.explicit_resume_points[label] = {
+## 'restype': res.concretetype,
+## }
+
+ if label in self.symbolic_restart_numbers:
+ symb = self.symbolic_restart_numbers[label]
+ assert symb.value is None
+ symb.value = restart_number
+ else:
+ symb = SymbolicRestartNumber(restart_number)
+ self.symbolic_restart_numbers[label] = symb
+
+ return link.target, i
+
+ def handle_resume_state_create(self, block, i):
+ op = block.operations[i]
+ llops = LowLevelOpList()
+ # XXX we do not look at op.args[0], the prevstate, at all
+ label = op.args[1].value
+ parms = op.args[2:]
+ FRAME, fieldnames = self.frametyper.frame_type_for_vars(parms)
+ c_FRAME = model.Constant(FRAME, lltype.Void)
+ v_state = llops.genop('malloc', [c_FRAME],
+ resulttype = lltype.Ptr(FRAME))
+ llops.extend(self.generate_saveops(v_state, parms, fieldnames))
+ v_state = llops.genop('cast_pointer', [v_state],
+ resulttype = lltype.Ptr(frame.STATE_HEADER))
+
+ if label in self.symbolic_restart_numbers:
+ symb = self.symbolic_restart_numbers[label]
+ else:
+ symb = SymbolicRestartNumber()
+ self.symbolic_restart_numbers[label] = symb
+
+ llops.genop('setfield', [v_state,
+ model.Constant('f_restart', lltype.Void),
+ model.Constant(symb, lltype.Signed)])
+ llops.append(model.SpaceOperation('same_as', [v_state], op.result))
+ block.operations[i:i+1] = llops
+
+ def handle_resume_state_invoke(self, block, i):
+ op = block.operations[i]
+ if op.result.concretetype != lltype.Signed:
+ raise NotImplementedError
+ v_returns = op.args[1]
+ if v_returns.concretetype == lltype.Signed:
+ raise NotImplementedError
+ elif v_returns.concretetype == lltype.Void:
+ args = [self.resume_after_void_ptr] + op.args
+ newop = model.SpaceOperation('direct_call', args, op.result)
+ block.operations[i] = newop
+ else:
+ raise NotImplementedError
+ return newop
+
def transform_block(self, block):
i = 0
@@ -424,51 +530,18 @@
op = replace_with_call(self.yield_current_frame_to_caller_ptr)
stackless_op = True
+ if op.opname == 'resume_state_invoke':
+ op = self.handle_resume_state_invoke(block, i)
+ stackless_op = True
+
+ if op.opname == 'resume_state_create':
+ self.handle_resume_state_create(block, i)
+ continue # go back and look at that malloc
+
if (op.opname in ('direct_call', 'indirect_call')
or self.analyzer.operation_is_true(op)):
if op.opname == 'resume_point':
- # in some circumstances we might be able to reuse
- # an already inserted resume point
- if i == len(block.operations) - 1:
- link = block.exits[0]
- else:
- link = support.split_block_with_keepalive(block, i+1)
- parms = op.args[1:]
- if not isinstance(parms[0], model.Variable):
- assert parms[0].value is None
- parms[0] = None
- args = vars_to_save(block)
- for a in args:
- if a not in parms:
- raise Exception, "not covered needed value at resume_point"
- if parms[0] is not None: # returns= case
- res = parms[0]
- args = [arg for arg in args if arg is not res]
- else:
- args = args
- res = op.result
-
- (frame_type,
- fieldnames) = self.frametyper.frame_type_for_vars(args)
-
- self.resume_points.append(
- ResumePoint(res, args, tuple(block.exits),
- frame_type, fieldnames))
-
- field2parm = {}
- for arg, fieldname in zip(args, fieldnames):
- p = parms.index(arg)
- field2parm[fieldname] = p-1 # ignore parm[0]
-
- label = op.args[0].value
- self.explicit_resume_points[label] = {
- 'restart': len(self.masterarray1) + len(self.resume_points)-1,
- 'frame_type': frame_type,
- 'restype': res.concretetype,
- 'field2parm': field2parm,
- }
- block = link.target
- i = 0
+ block, i = self.handle_resume_point(block, i)
continue
# trap calls to stackless-related suggested primitives
@@ -477,7 +550,7 @@
if func in self.suggested_primitives:
op = replace_with_call(self.suggested_primitives[func])
stackless_op = True
-
+
if not stackless_op and not self.analyzer.analyze(op):
i += 1
continue
More information about the Pypy-commit
mailing list