Author: Maciej Fijalkowski <fij...@gmail.com> Branch: Changeset: r75136:dddfb36fd72f Date: 2014-12-29 12:26 +0200 http://bitbucket.org/pypy/pypy/changeset/dddfb36fd72f/
Log: Merge slim-down-resumedescr. It seems to bring down warmup times by about 5% on small benchmarks 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 @@ -901,7 +901,7 @@ descr = tok.faildescr assert isinstance(descr, AbstractFailDescr) failure_recovery_pos = block_start + tok.pos_recovery_stub - descr._arm_failure_recovery_block = failure_recovery_pos + descr.adr_jump_offset = failure_recovery_pos relative_offset = tok.pos_recovery_stub - tok.offset guard_pos = block_start + tok.offset if not tok.is_guard_not_invalidated: @@ -968,11 +968,11 @@ def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): b = InstrBuilder(self.cpu.cpuinfo.arch_version) - patch_addr = faildescr._arm_failure_recovery_block + patch_addr = faildescr.adr_jump_offset assert patch_addr != 0 b.B(bridge_addr) b.copy_to_raw_memory(patch_addr) - faildescr._arm_failure_recovery_block = 0 + faildescr.adr_jump_offset = 0 # regalloc support def load(self, loc, value): diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -192,8 +192,6 @@ positions[i] = rffi.cast(rffi.USHORT, position) # write down the positions of locs guardtok.faildescr.rd_locs = positions - # we want the descr to keep alive - guardtok.faildescr.rd_loop_token = self.current_clt return fail_descr, target def call_assembler(self, op, guard_op, argloc, vloc, result_loc, tmploc): 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 @@ -572,13 +572,13 @@ def patch_pending_failure_recoveries(self, rawstart): # after we wrote the assembler to raw memory, set up - # tok.faildescr._x86_adr_jump_offset to contain the raw address of + # tok.faildescr.adr_jump_offset to contain the raw address of # the 4-byte target field in the JMP/Jcond instruction, and patch # the field in question to point (initially) to the recovery stub clt = self.current_clt for tok in self.pending_guard_tokens: addr = rawstart + tok.pos_jump_offset - tok.faildescr._x86_adr_jump_offset = addr + tok.faildescr.adr_jump_offset = addr relative_target = tok.pos_recovery_stub - (tok.pos_jump_offset + 4) assert rx86.fits_in_32bits(relative_target) # @@ -685,7 +685,7 @@ self.cpu.gc_ll_descr.gcrootmap) def patch_jump_for_descr(self, faildescr, adr_new_target): - adr_jump_offset = faildescr._x86_adr_jump_offset + adr_jump_offset = faildescr.adr_jump_offset assert adr_jump_offset != 0 offset = adr_new_target - (adr_jump_offset + 4) # If the new target fits within a rel32 of the jump, just patch @@ -705,7 +705,7 @@ p = rffi.cast(rffi.INTP, adr_jump_offset) adr_target = adr_jump_offset + 4 + rffi.cast(lltype.Signed, p[0]) mc.copy_to_raw_memory(adr_target) - faildescr._x86_adr_jump_offset = 0 # means "patched" + faildescr.adr_jump_offset = 0 # means "patched" def fixup_target_tokens(self, rawstart): for targettoken in self.target_tokens_currently_compiling: diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -1479,15 +1479,15 @@ assert kind == 'v' return lltype.nullptr(rclass.OBJECTPTR.TO) - def _prepare_resume_from_failure(self, opnum, dont_change_position, - deadframe): + def _prepare_resume_from_failure(self, opnum, deadframe): from rpython.jit.metainterp.resoperation import rop # - if opnum == rop.GUARD_TRUE: + if opnum == rop.GUARD_FUTURE_CONDITION: + pass + elif opnum == rop.GUARD_TRUE: # Produced directly by some goto_if_not_xxx() opcode that did not # jump, but which must now jump. The pc is just after the opcode. - if not dont_change_position: - self.position = self.jitcode.follow_jump(self.position) + self.position = self.jitcode.follow_jump(self.position) # elif opnum == rop.GUARD_FALSE: # Produced directly by some goto_if_not_xxx() opcode that jumped, @@ -1517,8 +1517,7 @@ elif opnum == rop.GUARD_NO_OVERFLOW: # Produced by int_xxx_ovf(). The pc is just after the opcode. # We get here because it did not used to overflow, but now it does. - if not dont_change_position: - return get_llexception(self.cpu, OverflowError()) + return get_llexception(self.cpu, OverflowError()) # elif opnum == rop.GUARD_OVERFLOW: # Produced by int_xxx_ovf(). The pc is just after the opcode. @@ -1649,13 +1648,9 @@ resumedescr, deadframe, all_virtuals) - if isinstance(resumedescr, ResumeAtPositionDescr): - dont_change_position = True - else: - dont_change_position = False current_exc = blackholeinterp._prepare_resume_from_failure( - resumedescr.guard_opnum, dont_change_position, deadframe) + resumedescr.guard_opnum, deadframe) _run_forever(blackholeinterp, current_exc) diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -63,14 +63,18 @@ if metainterp_sd.warmrunnerdesc is not None: # for tests assert original_jitcell_token.generation > 0 # has been registered with memmgr wref = weakref.ref(original_jitcell_token) + clt = original_jitcell_token.compiled_loop_token + clt.loop_token_wref = wref for op in loop.operations: descr = op.getdescr() + # not sure what descr.index is about if isinstance(descr, ResumeDescr): - descr.wref_original_loop_token = wref # stick it there - n = descr.index - if n >= 0: # we also record the resumedescr number - original_jitcell_token.compiled_loop_token.record_faildescr_index(n) - elif isinstance(descr, JitCellToken): + descr.rd_loop_token = clt # stick it there + #n = descr.index + #if n >= 0: # we also record the resumedescr number + # original_jitcell_token.compiled_loop_token.record_faildescr_index(n) + # pass + if isinstance(descr, JitCellToken): # for a CALL_ASSEMBLER: record it as a potential jump. if descr is not original_jitcell_token: original_jitcell_token.record_jump_to(descr) @@ -128,8 +132,8 @@ [ResOperation(rop.LABEL, jumpargs, None, descr=jitcell_token)] try: - start_state = optimize_trace(metainterp_sd, part, enable_opts, - export_state=True) + start_state = optimize_trace(metainterp_sd, jitdriver_sd, part, + enable_opts, export_state=True) except InvalidLoop: return None target_token = part.operations[0].getdescr() @@ -156,7 +160,7 @@ jumpargs = part.operations[-1].getarglist() try: - optimize_trace(metainterp_sd, part, enable_opts, + optimize_trace(metainterp_sd, jitdriver_sd, part, enable_opts, start_state=start_state, export_state=False) except InvalidLoop: return None @@ -209,7 +213,8 @@ orignial_label = label.clone() assert label.getopnum() == rop.LABEL try: - optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts, + optimize_trace(metainterp_sd, jitdriver_sd, part, + jitdriver_sd.warmstate.enable_opts, start_state=start_state, export_state=False) except InvalidLoop: # Fall back on jumping to preamble @@ -219,7 +224,7 @@ [ResOperation(rop.JUMP, inputargs[:], None, descr=loop_jitcell_token)] try: - optimize_trace(metainterp_sd, part, + optimize_trace(metainterp_sd, jitdriver_sd, part, jitdriver_sd.warmstate.enable_opts, inline_short_preamble=False, start_state=start_state, export_state=False) @@ -479,22 +484,31 @@ return d class ResumeDescr(AbstractFailDescr): - pass + _attrs_ = () class ResumeGuardDescr(ResumeDescr): - # this class also gets the following attributes stored by resume.py code - # XXX move all of unused stuff to guard_op, now that we can have - # a separate class, so it does not survive that long - rd_snapshot = None - rd_frame_info_list = None + _attrs_ = ('rd_numb', 'rd_count', 'rd_consts', 'rd_virtuals', + 'rd_frame_info_list', 'rd_pendingfields', 'status') + rd_numb = lltype.nullptr(NUMBERING) rd_count = 0 rd_consts = None rd_virtuals = None + rd_frame_info_list = None rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO) status = r_uint(0) + def copy_all_attributes_from(self, other): + assert isinstance(other, ResumeGuardDescr) + self.rd_count = other.rd_count + self.rd_consts = other.rd_consts + self.rd_frame_info_list = other.rd_frame_info_list + self.rd_pendingfields = other.rd_pendingfields + self.rd_virtuals = other.rd_virtuals + self.rd_numb = other.rd_numb + # we don't copy status + ST_BUSY_FLAG = 0x01 # if set, busy tracing from the guard ST_TYPE_MASK = 0x06 # mask for the type (TY_xxx) ST_SHIFT = 3 # in "status >> ST_SHIFT" is stored: @@ -509,31 +523,12 @@ def store_final_boxes(self, guard_op, boxes, metainterp_sd): guard_op.setfailargs(boxes) self.rd_count = len(boxes) - self.guard_opnum = guard_op.getopnum() # if metainterp_sd.warmrunnerdesc is not None: # for tests jitcounter = metainterp_sd.warmrunnerdesc.jitcounter hash = jitcounter.fetch_next_hash() self.status = hash & self.ST_SHIFT_MASK - def make_a_counter_per_value(self, guard_value_op): - assert guard_value_op.getopnum() == rop.GUARD_VALUE - box = guard_value_op.getarg(0) - try: - i = guard_value_op.getfailargs().index(box) - except ValueError: - return # xxx probably very rare - else: - if box.type == history.INT: - ty = self.TY_INT - elif box.type == history.REF: - ty = self.TY_REF - elif box.type == history.FLOAT: - ty = self.TY_FLOAT - else: - assert 0, box.type - self.status = ty | (r_uint(i) << self.ST_SHIFT) - def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd): if self.must_compile(deadframe, metainterp_sd, jitdriver_sd): self.start_compiling() @@ -632,32 +627,62 @@ self, inputargs, new_loop.operations, new_loop.original_jitcell_token) - def copy_all_attributes_into(self, res): - # XXX a bit ugly to have to list them all here - res.rd_snapshot = self.rd_snapshot - res.rd_frame_info_list = self.rd_frame_info_list - res.rd_numb = self.rd_numb - res.rd_consts = self.rd_consts - res.rd_virtuals = self.rd_virtuals - res.rd_pendingfields = self.rd_pendingfields - res.rd_count = self.rd_count + def make_a_counter_per_value(self, guard_value_op): + assert guard_value_op.getopnum() == rop.GUARD_VALUE + box = guard_value_op.getarg(0) + try: + i = guard_value_op.getfailargs().index(box) + except ValueError: + return # xxx probably very rare + else: + if box.type == history.INT: + ty = self.TY_INT + elif box.type == history.REF: + ty = self.TY_REF + elif box.type == history.FLOAT: + ty = self.TY_FLOAT + else: + assert 0, box.type + self.status = ty | (r_uint(i) << self.ST_SHIFT) - def _clone_if_mutable(self): - res = ResumeGuardDescr() - self.copy_all_attributes_into(res) - return res +class ResumeGuardNonnullDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_NONNULL + +class ResumeGuardIsnullDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_ISNULL + +class ResumeGuardClassDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_CLASS + +class ResumeGuardTrueDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_TRUE + +class ResumeGuardFalseDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_FALSE + +class ResumeGuardNonnullClassDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_NONNULL_CLASS + +class ResumeGuardExceptionDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_EXCEPTION + +class ResumeGuardNoExceptionDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_NO_EXCEPTION + +class ResumeGuardOverflowDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_OVERFLOW + +class ResumeGuardNoOverflowDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_NO_OVERFLOW + +class ResumeGuardValueDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_VALUE class ResumeGuardNotInvalidated(ResumeGuardDescr): - def _clone_if_mutable(self): - res = ResumeGuardNotInvalidated() - self.copy_all_attributes_into(res) - return res + guard_opnum = rop.GUARD_NOT_INVALIDATED class ResumeAtPositionDescr(ResumeGuardDescr): - def _clone_if_mutable(self): - res = ResumeAtPositionDescr() - self.copy_all_attributes_into(res) - return res + guard_opnum = rop.GUARD_FUTURE_CONDITION class AllVirtuals: llopaque = True @@ -678,8 +703,10 @@ class ResumeGuardForcedDescr(ResumeGuardDescr): + guard_opnum = rop.GUARD_NOT_FORCED - def __init__(self, metainterp_sd, jitdriver_sd): + def _init(self, metainterp_sd, jitdriver_sd): + # to please the annotator self.metainterp_sd = metainterp_sd self.jitdriver_sd = jitdriver_sd @@ -740,12 +767,40 @@ hidden_all_virtuals = obj.hide(metainterp_sd.cpu) metainterp_sd.cpu.set_savedata_ref(deadframe, hidden_all_virtuals) - def _clone_if_mutable(self): - res = ResumeGuardForcedDescr(self.metainterp_sd, - self.jitdriver_sd) - self.copy_all_attributes_into(res) - return res - +def invent_fail_descr_for_op(op, optimizer): + opnum = op.getopnum() + if opnum == rop.GUARD_NOT_FORCED or opnum == rop.GUARD_NOT_FORCED_2: + resumedescr = ResumeGuardForcedDescr() + resumedescr._init(optimizer.metainterp_sd, optimizer.jitdriver_sd) + elif opnum == rop.GUARD_NOT_INVALIDATED: + resumedescr = ResumeGuardNotInvalidated() + elif opnum == rop.GUARD_FUTURE_CONDITION: + resumedescr = ResumeAtPositionDescr() + elif opnum == rop.GUARD_VALUE: + resumedescr = ResumeGuardValueDescr() + elif opnum == rop.GUARD_NONNULL: + resumedescr = ResumeGuardNonnullDescr() + elif opnum == rop.GUARD_ISNULL: + resumedescr = ResumeGuardIsnullDescr() + elif opnum == rop.GUARD_NONNULL_CLASS: + resumedescr = ResumeGuardNonnullClassDescr() + elif opnum == rop.GUARD_CLASS: + resumedescr = ResumeGuardClassDescr() + elif opnum == rop.GUARD_TRUE: + resumedescr = ResumeGuardTrueDescr() + elif opnum == rop.GUARD_FALSE: + resumedescr = ResumeGuardFalseDescr() + elif opnum == rop.GUARD_EXCEPTION: + resumedescr = ResumeGuardExceptionDescr() + elif opnum == rop.GUARD_NO_EXCEPTION: + resumedescr = ResumeGuardNoExceptionDescr() + elif opnum == rop.GUARD_OVERFLOW: + resumedescr = ResumeGuardOverflowDescr() + elif opnum == rop.GUARD_NO_OVERFLOW: + resumedescr = ResumeGuardNoOverflowDescr() + else: + assert False + return resumedescr class ResumeFromInterpDescr(ResumeDescr): def __init__(self, original_greenkey): @@ -785,13 +840,15 @@ new_trace.operations = [op.clone() for op in metainterp.history.operations] metainterp_sd = metainterp.staticdata - state = metainterp.jitdriver_sd.warmstate + jitdriver_sd = metainterp.jitdriver_sd + state = jitdriver_sd.warmstate if isinstance(resumekey, ResumeAtPositionDescr): inline_short_preamble = False else: inline_short_preamble = True try: - state = optimize_trace(metainterp_sd, new_trace, state.enable_opts, + state = optimize_trace(metainterp_sd, jitdriver_sd, new_trace, + state.enable_opts, inline_short_preamble, export_state=True) except InvalidLoop: debug_print("compile_new_bridge: got an InvalidLoop") diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -134,14 +134,6 @@ def repr_of_descr(self): return '%r' % (self,) - def _clone_if_mutable(self): - return self - def clone_if_mutable(self): - clone = self._clone_if_mutable() - if not we_are_translated(): - assert clone.__class__ is self.__class__ - return clone - def hide(self, cpu): descr_ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(descr_ptr) @@ -159,6 +151,8 @@ index = -1 final_descr = False + _attrs_ = ('adr_jump_offset', 'rd_locs', 'rd_loop_token') + def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd): raise NotImplementedError def compile_and_attach(self, metainterp, new_loop): diff --git a/rpython/jit/metainterp/inliner.py b/rpython/jit/metainterp/inliner.py --- a/rpython/jit/metainterp/inliner.py +++ b/rpython/jit/metainterp/inliner.py @@ -1,5 +1,6 @@ from rpython.jit.metainterp.history import Const from rpython.jit.metainterp.resume import Snapshot +from rpython.jit.metainterp.resoperation import GuardResOp class Inliner(object): @@ -26,21 +27,16 @@ newop.setfailargs([self.inline_arg(a) for a in args]) else: newop.setfailargs([]) + assert isinstance(newop, GuardResOp) + newop.rd_snapshot = self.inline_snapshot(newop.rd_snapshot) if newop.result and not ignore_result: old_result = newop.result newop.result = newop.result.clonebox() self.argmap[old_result] = newop.result - self.inline_descr_inplace(newop.getdescr()) - return newop - def inline_descr_inplace(self, descr): - from rpython.jit.metainterp.compile import ResumeGuardDescr - if isinstance(descr, ResumeGuardDescr): - descr.rd_snapshot = self.inline_snapshot(descr.rd_snapshot) - def inline_arg(self, arg): if arg is None: return None diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py b/rpython/jit/metainterp/optimizeopt/__init__.py --- a/rpython/jit/metainterp/optimizeopt/__init__.py +++ b/rpython/jit/metainterp/optimizeopt/__init__.py @@ -47,7 +47,7 @@ return optimizations, unroll -def optimize_trace(metainterp_sd, loop, enable_opts, +def optimize_trace(metainterp_sd, jitdriver_sd, loop, enable_opts, inline_short_preamble=True, start_state=None, export_state=True): """Optimize loop.operations to remove internal overheadish operations. @@ -59,11 +59,13 @@ loop.operations) optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts) if unroll: - return optimize_unroll(metainterp_sd, loop, optimizations, + return optimize_unroll(metainterp_sd, jitdriver_sd, loop, + optimizations, inline_short_preamble, start_state, export_state) else: - optimizer = Optimizer(metainterp_sd, loop, optimizations) + optimizer = Optimizer(metainterp_sd, jitdriver_sd, loop, + optimizations) optimizer.propagate_all_forward() finally: debug_stop("jit-optimize") diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -7,7 +7,8 @@ IntLowerBound, MININT,\ MAXINT from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method -from rpython.jit.metainterp.resoperation import rop, ResOperation, AbstractResOp +from rpython.jit.metainterp.resoperation import rop, ResOperation,\ + AbstractResOp, GuardResOp from rpython.jit.metainterp.typesystem import llhelper from rpython.tool.pairtype import extendabletype from rpython.rlib.debug import debug_print @@ -501,8 +502,9 @@ class Optimizer(Optimization): - def __init__(self, metainterp_sd, loop, optimizations=None): + def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations=None): self.metainterp_sd = metainterp_sd + self.jitdriver_sd = jitdriver_sd self.cpu = metainterp_sd.cpu self.loop = loop self.values = {} @@ -734,6 +736,11 @@ while i > 0: i -= 1 if self._newoperations[i] is old_op: + # a bit of dance to make sure we copy all the attrs on + # an already emitted descr + newdescr = new_op.getdescr() + olddescr = old_op.getdescr() + newdescr.copy_all_attributes_from(olddescr) self._newoperations[i] = new_op break else: @@ -741,9 +748,16 @@ def store_final_boxes_in_guard(self, op, pendingfields): assert pendingfields is not None - descr = op.getdescr() + if op.getdescr() is not None: + descr = op.getdescr() + assert isinstance(descr, compile.ResumeAtPositionDescr) + else: + descr = compile.invent_fail_descr_for_op(op, self) + op.setdescr(descr) assert isinstance(descr, compile.ResumeGuardDescr) - modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo) + assert isinstance(op, GuardResOp) + modifier = resume.ResumeDataVirtualAdder(descr, op, + self.resumedata_memo) try: newboxes = modifier.finish(self, pendingfields) if len(newboxes) > self.metainterp_sd.options.failargs_limit: diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -312,15 +312,11 @@ if not previous_classbox.same_constant(expected_classbox): r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) raise InvalidLoop('A GUARD_VALUE (%s) was proven to always fail' % r) + descr = compile.ResumeGuardValueDescr() op = old_guard_op.copy_and_change(rop.GUARD_VALUE, - args = [old_guard_op.getarg(0), op.getarg(1)]) + args = [old_guard_op.getarg(0), op.getarg(1)], + descr = descr) self.optimizer.replaces_guard[op] = old_guard_op - # hack hack hack. Change the guard_opnum on - # new_guard_op.getdescr() so that when resuming, - # the operation is not skipped by pyjitpl.py. - descr = op.getdescr() - assert isinstance(descr, compile.ResumeGuardDescr) - descr.guard_opnum = rop.GUARD_VALUE descr.make_a_counter_per_value(op) # to be safe if isinstance(value, PtrOptValue): @@ -364,15 +360,11 @@ if old_guard_op.getopnum() == rop.GUARD_NONNULL: # it was a guard_nonnull, which we replace with a # guard_nonnull_class. + descr = compile.ResumeGuardNonnullClassDescr() op = old_guard_op.copy_and_change (rop.GUARD_NONNULL_CLASS, - args = [old_guard_op.getarg(0), op.getarg(1)]) + args = [old_guard_op.getarg(0), op.getarg(1)], + descr=descr) self.optimizer.replaces_guard[op] = old_guard_op - # hack hack hack. Change the guard_opnum on - # new_guard_op.getdescr() so that when resuming, - # the operation is not skipped by pyjitpl.py. - descr = op.getdescr() - assert isinstance(descr, compile.ResumeGuardDescr) - descr.guard_opnum = rop.GUARD_NONNULL_CLASS self.emit_operation(op) value.make_constant_class(expectedclassbox, op) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -17,16 +17,16 @@ b0 = BoxInt() b1 = BoxInt() opt = optimizeopt.Optimizer(FakeMetaInterpStaticData(LLtypeMixin.cpu), - None) - fdescr = ResumeGuardDescr() - op = ResOperation(rop.GUARD_TRUE, ['dummy'], None, descr=fdescr) + None, None) + op = ResOperation(rop.GUARD_TRUE, ['dummy'], None) # setup rd data fi0 = resume.FrameInfo(None, "code0", 11) - fdescr.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33) snapshot0 = resume.Snapshot(None, [b0]) - fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1]) + op.rd_snapshot = resume.Snapshot(snapshot0, [b1]) + op.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33) # opt.store_final_boxes_in_guard(op, []) + fdescr = op.getdescr() if op.getfailargs() == [b0, b1]: assert list(fdescr.rd_numb.nums) == [tag(1, TAGBOX)] assert list(fdescr.rd_numb.prev.nums) == [tag(0, TAGBOX)] @@ -97,7 +97,8 @@ enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap" def optimize_loop(self, ops, optops, call_pure_results=None): - loop = self.parse(ops) + + loop = self.parse(ops, postprocess=self.postprocess) token = JitCellToken() loop.operations = [ResOperation(rop.LABEL, loop.inputargs, None, descr=TargetToken(token))] + \ loop.operations @@ -108,42 +109,6 @@ print '\n'.join([str(o) for o in loop.operations]) self.assert_equal(loop, expected) - def setup_method(self, meth=None): - class FailDescr(compile.ResumeGuardDescr): - oparse = None - def _oparser_uses_descr_of_guard(self, oparse, fail_args): - # typically called 3 times: once when parsing 'ops', - # once when parsing 'preamble', once when parsing 'expected'. - self.oparse = oparse - self.rd_frame_info_list, self.rd_snapshot = snapshot(fail_args) - def _clone_if_mutable(self): - assert self is fdescr - return fdescr2 - def __repr__(self): - if self is fdescr: - return 'fdescr' - if self is fdescr2: - return 'fdescr2' - return compile.ResumeGuardDescr.__repr__(self) - # - def snapshot(fail_args, got=[]): - if not got: # only the first time, i.e. when parsing 'ops' - rd_frame_info_list = resume.FrameInfo(None, "code", 11) - rd_snapshot = resume.Snapshot(None, fail_args) - got.append(rd_frame_info_list) - got.append(rd_snapshot) - return got - # - fdescr = instantiate(FailDescr) - self.namespace['fdescr'] = fdescr - fdescr2 = instantiate(FailDescr) - self.namespace['fdescr2'] = fdescr2 - - def teardown_method(self, meth): - self.namespace.pop('fdescr', None) - self.namespace.pop('fdescr2', None) - - class BaseTestOptimizeBasic(BaseTestBasic): @@ -2065,14 +2030,14 @@ def test_merge_guard_nonnull_guard_class(self): ops = """ [p1, i0, i1, i2, p2] - guard_nonnull(p1, descr=fdescr) [i0] + guard_nonnull(p1) [i0] i3 = int_add(i1, i2) guard_class(p1, ConstClass(node_vtable)) [i1] jump(p2, i0, i1, i3, p2) """ expected = """ [p1, i0, i1, i2, p2] - guard_nonnull_class(p1, ConstClass(node_vtable), descr=fdescr) [i0] + guard_nonnull_class(p1, ConstClass(node_vtable)) [i0] i3 = int_add(i1, i2) jump(p2, i0, i1, i3, p2) """ @@ -2082,14 +2047,14 @@ def test_merge_guard_nonnull_guard_value(self): ops = """ [p1, i0, i1, i2, p2] - guard_nonnull(p1, descr=fdescr) [i0] + guard_nonnull(p1) [i0] i3 = int_add(i1, i2) guard_value(p1, ConstPtr(myptr)) [i1] jump(p2, i0, i1, i3, p2) """ expected = """ [p1, i0, i1, i2, p2] - guard_value(p1, ConstPtr(myptr), descr=fdescr) [i0] + guard_value(p1, ConstPtr(myptr)) [i0] i3 = int_add(i1, i2) jump(p2, i0, i1, i3, p2) """ @@ -2099,7 +2064,7 @@ def test_merge_guard_nonnull_guard_class_guard_value(self): ops = """ [p1, i0, i1, i2, p2] - guard_nonnull(p1, descr=fdescr) [i0] + guard_nonnull(p1) [i0] i3 = int_add(i1, i2) guard_class(p1, ConstClass(node_vtable)) [i2] i4 = int_sub(i3, 1) @@ -2108,7 +2073,7 @@ """ expected = """ [p1, i0, i1, i2, p2] - guard_value(p1, ConstPtr(myptr), descr=fdescr) [i0] + guard_value(p1, ConstPtr(myptr)) [i0] i3 = int_add(i1, i2) i4 = int_sub(i3, 1) jump(p2, i0, i1, i4, p2) @@ -2527,7 +2492,7 @@ reader = ResumeDataFakeReader(fdescr, fail_args, MyMetaInterp(self.cpu)) boxes = reader.consume_boxes() - self._verify_fail_args(boxes, fdescr.oparse, expectedtext) + self._verify_fail_args(boxes, self.oparse, expectedtext) def test_expand_fail_1(self): ops = """ @@ -2538,12 +2503,12 @@ i4 = getfield_gc(p1, descr=valuedescr) # i2 = int_add(10, 5) - guard_true(i1, descr=fdescr) [i2, i4] + guard_true(i1) [i2, i4] jump(i1, i4) """ expected = """ [i1, i3] - guard_true(i1, descr=fdescr) [i3] + guard_true(i1) [i3] jump(1, i3) """ self.optimize_loop(ops, expected) @@ -2555,12 +2520,12 @@ p1 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p1, i2, descr=valuedescr) setfield_gc(p1, p1, descr=nextdescr) - guard_true(i1, descr=fdescr) [p1] + guard_true(i1) [p1] jump(i1, i2) """ expected = """ [i1, i2] - guard_true(i1, descr=fdescr) [i2] + guard_true(i1) [i2] jump(1, i2) """ self.optimize_loop(ops, expected) @@ -2577,12 +2542,12 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p3, descr=nextdescr) - guard_true(i1, descr=fdescr) [i3, p1] + guard_true(i1) [i3, p1] jump(i2, i1, i3, p3) """ expected = """ [i1, i2, i3, p3] - guard_true(i1, descr=fdescr) [i3, i2, p3] + guard_true(i1) [i3, i2, p3] jump(i2, 1, i3, p3) """ self.optimize_loop(ops, expected) @@ -2594,7 +2559,6 @@ def test_expand_fail_4(self): for arg in ['p1', 'i2,p1', 'p1,p2', 'p2,p1', 'i2,p1,p2', 'i2,p2,p1']: - self.setup_method() # humpf ops = """ [i1, i2, i3] p1 = new_with_vtable(ConstClass(node_vtable)) @@ -2604,12 +2568,12 @@ setfield_gc(p1, i2, descr=valuedescr) setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) - guard_true(i1, descr=fdescr) [i4, i3, %s] + guard_true(i1) [i4, i3, %s] jump(i1, i2, i3) """ expected = """ [i1, i2, i3] - guard_true(i1, descr=fdescr) [i3, i2] + guard_true(i1) [i3, i2] jump(1, i2, i3) """ self.optimize_loop(ops % arg, expected) @@ -2627,12 +2591,12 @@ setfield_gc(p1, p2, descr=nextdescr) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p2, p1, descr=nextdescr) # a cycle - guard_true(i1, descr=fdescr) [i3, i4, p1, p2] + guard_true(i1) [i3, i4, p1, p2] jump(i2, i1, i3, i4) """ expected = """ [i1, i2, i3, i4] - guard_true(i1, descr=fdescr) [i3, i4, i2] + guard_true(i1) [i3, i4, i2] jump(i2, 1, i3, i4) """ self.optimize_loop(ops, expected) @@ -2644,14 +2608,14 @@ def test_expand_fail_6(self): ops = """ [p0, i0, i1] - guard_true(i0, descr=fdescr) [p0] + guard_true(i0) [p0] p1 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p1, i1, descr=valuedescr) jump(p1, i1, i1) """ expected = """ [i1b, i0, i1] - guard_true(i0, descr=fdescr) [i1b] + guard_true(i0) [i1b] jump(i1, i1, i1) """ py.test.skip("XXX") @@ -2667,13 +2631,13 @@ p1 = new_array(3, descr=arraydescr) setarrayitem_gc(p1, 1, i1, descr=arraydescr) setarrayitem_gc(p1, 0, 25, descr=arraydescr) - guard_true(i1, descr=fdescr) [p1] + guard_true(i1) [p1] i2 = getarrayitem_gc(p1, 1, descr=arraydescr) jump(i2) """ expected = """ [i1] - guard_true(i1, descr=fdescr) [i1] + guard_true(i1) [i1] jump(1) """ self.optimize_loop(ops, expected) @@ -2687,14 +2651,14 @@ p2 = new(descr=ssize) setfield_gc(p2, i1, descr=adescr) setfield_gc(p2, p1, descr=bdescr) - guard_true(i1, descr=fdescr) [p2] + guard_true(i1) [p2] i3 = getfield_gc(p2, descr=adescr) p3 = getfield_gc(p2, descr=bdescr) jump(i3, p3) """ expected = """ [i1, p1] - guard_true(i1, descr=fdescr) [i1, p1] + guard_true(i1) [i1, p1] jump(1, p1) """ self.optimize_loop(ops, expected) @@ -2711,7 +2675,7 @@ setfield_gc(p5s, i2, descr=adescr) setfield_gc(p5s, p7v, descr=bdescr) setarrayitem_gc(p1a, 1, p5s, descr=arraydescr2) - guard_true(i1, descr=fdescr) [p1a] + guard_true(i1) [p1a] p2s = new(descr=ssize) p3v = new_with_vtable(ConstClass(node_vtable)) p4a = new_array(2, descr=arraydescr2) @@ -2723,7 +2687,7 @@ """ expected = """ [i1, ia, iv, pnull, i2] - guard_true(i1, descr=fdescr) [ia, iv, i2] + guard_true(i1) [ia, iv, i2] jump(1, 1, i2, NULL, i2) """ py.test.skip("XXX") @@ -2749,14 +2713,14 @@ p2 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(p1, p2, descr=nextdescr) - guard_true(i3, descr=fdescr) [] + guard_true(i3) [] i4 = int_neg(i2) setfield_gc(p1, NULL, descr=nextdescr) jump(p1, i2, i4) """ expected = """ [p1, i2, i3] - guard_true(i3, descr=fdescr) [p1, i2] + guard_true(i3) [p1, i2] i4 = int_neg(i2) setfield_gc(p1, NULL, descr=nextdescr) jump(p1, i2, i4) @@ -2774,14 +2738,14 @@ p2 = new_with_vtable(ConstClass(node_vtable)) setfield_gc(p2, i2, descr=valuedescr) setfield_gc(ConstPtr(myptr), p2, descr=nextdescr) - guard_true(i3, descr=fdescr) [] + guard_true(i3) [] i4 = int_neg(i2) setfield_gc(ConstPtr(myptr), NULL, descr=nextdescr) jump(i2, i4) """ expected = """ [i2, i3] - guard_true(i3, descr=fdescr) [i2] + guard_true(i3) [i2] i4 = int_neg(i2) setfield_gc(ConstPtr(myptr), NULL, descr=nextdescr) jump(i2, i4) @@ -3096,7 +3060,7 @@ p2 = virtual_ref(p1, 2) setfield_gc(p0, p2, descr=nextdescr) call_may_force(i1, descr=mayforcevirtdescr) - guard_not_forced(descr=fdescr) [p2, p1] + guard_not_forced() [p2, p1] virtual_ref_finish(p2, p1) setfield_gc(p0, NULL, descr=nextdescr) jump(p0, i1) @@ -3111,7 +3075,7 @@ setfield_gc(p0, p2, descr=nextdescr) # call_may_force(i1, descr=mayforcevirtdescr) - guard_not_forced(descr=fdescr) [p2, i1] + guard_not_forced() [p2, i1] # setfield_gc(p0, NULL, descr=nextdescr) p1 = new_with_vtable(ConstClass(node_vtable)) @@ -3142,7 +3106,7 @@ p2 = virtual_ref(p1, 2) setfield_gc(p0, p2, descr=refdescr) call(i1, descr=nonwritedescr) - guard_no_exception(descr=fdescr) [p2, p1] + guard_no_exception() [p2, p1] virtual_ref_finish(p2, p1) setfield_gc(p0, NULL, descr=refdescr) jump(p0, i1) @@ -3151,7 +3115,7 @@ [p0, i1] p3 = force_token() call(i1, descr=nonwritedescr) - guard_no_exception(descr=fdescr) [p3, i1, p0] + guard_no_exception() [p3, i1, p0] setfield_gc(p0, NULL, descr=refdescr) jump(p0, i1) """ diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -45,7 +45,7 @@ def optimize_loop(self, ops, expected, expected_preamble=None, call_pure_results=None, expected_short=None): - loop = self.parse(ops) + loop = self.parse(ops, postprocess=self.postprocess) if expected != "crash!": expected = self.parse(expected) if expected_preamble: @@ -96,41 +96,6 @@ class OptimizeOptTest(BaseTestWithUnroll): - def setup_method(self, meth=None): - class FailDescr(compile.ResumeGuardDescr): - oparse = None - def _oparser_uses_descr_of_guard(self, oparse, fail_args): - # typically called 3 times: once when parsing 'ops', - # once when parsing 'preamble', once when parsing 'expected'. - self.oparse = oparse - self.rd_frame_info_list, self.rd_snapshot = snapshot(fail_args) - def _clone_if_mutable(self): - assert self is fdescr - return fdescr2 - def __repr__(self): - if self is fdescr: - return 'fdescr' - if self is fdescr2: - return 'fdescr2' - return compile.ResumeGuardDescr.__repr__(self) - # - def snapshot(fail_args, got=[]): - if not got: # only the first time, i.e. when parsing 'ops' - rd_frame_info_list = resume.FrameInfo(None, "code", 11) - rd_snapshot = resume.Snapshot(None, fail_args) - got.append(rd_frame_info_list) - got.append(rd_snapshot) - return got - # - fdescr = instantiate(FailDescr) - self.namespace['fdescr'] = fdescr - fdescr2 = instantiate(FailDescr) - self.namespace['fdescr2'] = fdescr2 - - def teardown_method(self, meth): - self.namespace.pop('fdescr', None) - self.namespace.pop('fdescr2', None) - def test_simple(self): ops = """ [] @@ -3004,20 +2969,20 @@ def test_merge_guard_nonnull_guard_class(self): ops = """ [p1, i0, i1, i2, p2] - guard_nonnull(p1, descr=fdescr) [i0] + guard_nonnull(p1) [i0] i3 = int_add(i1, i2) guard_class(p1, ConstClass(node_vtable)) [i1] jump(p2, i0, i1, i3, p2) """ preamble = """ [p1, i0, i1, i2, p2] - guard_nonnull_class(p1, ConstClass(node_vtable), descr=fdescr) [i0] + guard_nonnull_class(p1, ConstClass(node_vtable)) [i0] i3 = int_add(i1, i2) jump(p2, i0, i1, i3) """ expected = """ [p2, i0, i1, i2] - guard_nonnull_class(p2, ConstClass(node_vtable), descr=fdescr2) [i0] + guard_nonnull_class(p2, ConstClass(node_vtable)) [i0] i3 = int_add(i1, i2) jump(p2, i0, i1, i3) """ @@ -3027,20 +2992,20 @@ def test_merge_guard_nonnull_guard_value(self): ops = """ [p1, i0, i1, i2, p2] - guard_nonnull(p1, descr=fdescr) [i0] + guard_nonnull(p1) [i0] i3 = int_add(i1, i2) guard_value(p1, ConstPtr(myptr)) [i1] jump(p2, i0, i1, i3, p2) """ preamble = """ [p1, i0, i1, i2, p2] - guard_value(p1, ConstPtr(myptr), descr=fdescr) [i0] + guard_value(p1, ConstPtr(myptr)) [i0] i3 = int_add(i1, i2) jump(p2, i0, i1, i3) """ expected = """ [p2, i0, i1, i2] - guard_value(p2, ConstPtr(myptr), descr=fdescr2) [i0] + guard_value(p2, ConstPtr(myptr)) [i0] i3 = int_add(i1, i2) jump(ConstPtr(myptr), i0, i1, i3) """ @@ -3050,7 +3015,7 @@ def test_merge_guard_nonnull_guard_class_guard_value(self): ops = """ [p1, i0, i1, i2, p2] - guard_nonnull(p1, descr=fdescr) [i0] + guard_nonnull(p1) [i0] i3 = int_add(i1, i2) guard_class(p1, ConstClass(node_vtable)) [i2] i4 = int_sub(i3, 1) @@ -3059,14 +3024,14 @@ """ preamble = """ [p1, i0, i1, i2, p2] - guard_value(p1, ConstPtr(myptr), descr=fdescr) [i0] + guard_value(p1, ConstPtr(myptr)) [i0] i3 = int_add(i1, i2) i4 = int_sub(i3, 1) jump(p2, i0, i1, i4) """ expected = """ [p2, i0, i1, i2] - guard_value(p2, ConstPtr(myptr), descr=fdescr2) [i0] + guard_value(p2, ConstPtr(myptr)) [i0] i3 = int_add(i1, i2) i4 = int_sub(i3, 1) jump(ConstPtr(myptr), i0, i1, i4) @@ -3860,7 +3825,7 @@ p2 = virtual_ref(p1, 2) setfield_gc(p0, p2, descr=nextdescr) call_may_force(i1, descr=mayforcevirtdescr) - guard_not_forced(descr=fdescr) [p2, p1] + guard_not_forced() [p2, p1] virtual_ref_finish(p2, p1) setfield_gc(p0, NULL, descr=nextdescr) jump(p0, i1) @@ -3875,7 +3840,7 @@ setfield_gc(p0, p2, descr=nextdescr) # call_may_force(i1, descr=mayforcevirtdescr) - guard_not_forced(descr=fdescr2) [p2, i1] + guard_not_forced() [p2, i1] # setfield_gc(p0, NULL, descr=nextdescr) p1 = new_with_vtable(ConstClass(node_vtable)) @@ -3906,7 +3871,7 @@ p2 = virtual_ref(p1, 2) setfield_gc(p0, p2, descr=refdescr) call(i1, descr=nonwritedescr) - guard_no_exception(descr=fdescr) [p2, p1] + guard_no_exception() [p2, p1] virtual_ref_finish(p2, p1) setfield_gc(p0, NULL, descr=refdescr) escape() @@ -3916,7 +3881,7 @@ [p0, i1] p3 = force_token() call(i1, descr=nonwritedescr) - guard_no_exception(descr=fdescr) [p3, i1, p0] + guard_no_exception() [p3, i1, p0] setfield_gc(p0, NULL, descr=refdescr) escape() jump(p0, i1) @@ -3925,7 +3890,7 @@ [p0, i1] p3 = force_token() call(i1, descr=nonwritedescr) - guard_no_exception(descr=fdescr2) [p3, i1, p0] + guard_no_exception() [p3, i1, p0] setfield_gc(p0, NULL, descr=refdescr) escape() jump(p0, i1) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -8,12 +8,13 @@ from rpython.jit.backend.llgraph import runner from rpython.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, Const, TreeLoop, AbstractDescr, - JitCellToken, TargetToken) + JitCellToken, TargetToken, + BasicFinalDescr) from rpython.jit.metainterp.optimizeopt.util import sort_descrs, equaloplists from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.codewriter.heaptracker import register_known_gctype, adr2int -from rpython.jit.tool.oparser import parse, pure_parse +from rpython.jit.tool.oparser import OpParser, pure_parse from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr from rpython.jit.metainterp import compile, resume, history from rpython.jit.metainterp.jitprof import EmptyProfiler @@ -348,42 +349,35 @@ def store_final_boxes(self, op, boxes, metainterp_sd): op.setfailargs(boxes) def __eq__(self, other): - return type(self) is type(other) # xxx obscure - def clone_if_mutable(self): - res = Storage(self.metainterp_sd, self.original_greenkey) - self.copy_all_attributes_into(res) - return res + return True # screw this + #return type(self) is type(other) # xxx obscure def _sortboxes(boxes): _kind2count = {history.INT: 1, history.REF: 2, history.FLOAT: 3} return sorted(boxes, key=lambda box: _kind2count[box.type]) +final_descr = BasicFinalDescr() + class BaseTest(object): - def parse(self, s, boxkinds=None, want_fail_descr=True): - if want_fail_descr: - invent_fail_descr = self.invent_fail_descr - else: - invent_fail_descr = lambda *args: None - return parse(s, self.cpu, self.namespace, - type_system=self.type_system, - boxkinds=boxkinds, - invent_fail_descr=invent_fail_descr) + def parse(self, s, boxkinds=None, want_fail_descr=True, postprocess=None): + self.oparse = OpParser(s, self.cpu, self.namespace, 'lltype', + boxkinds, + None, False, postprocess) + return self.oparse.parse() + + def postprocess(self, op): + if op.is_guard(): + op.rd_snapshot = resume.Snapshot(None, op.getfailargs()) + op.rd_frame_info_list = resume.FrameInfo(None, "code", 11) def add_guard_future_condition(self, res): # invent a GUARD_FUTURE_CONDITION to not have to change all tests if res.operations[-1].getopnum() == rop.JUMP: - guard = ResOperation(rop.GUARD_FUTURE_CONDITION, [], None, descr=self.invent_fail_descr(None, -1, [])) + guard = ResOperation(rop.GUARD_FUTURE_CONDITION, [], None) + guard.rd_snapshot = resume.Snapshot(None, []) res.operations.insert(-1, guard) - def invent_fail_descr(self, model, opnum, fail_args): - if fail_args is None: - return None - descr = Storage() - descr.rd_frame_info_list = resume.FrameInfo(None, "code", 11) - descr.rd_snapshot = resume.Snapshot(None, _sortboxes(fail_args)) - return descr - def assert_equal(self, optimized, expected, text_right=None): from rpython.jit.metainterp.optimizeopt.util import equaloplists assert len(optimized.inputargs) == len(expected.inputargs) @@ -410,7 +404,8 @@ if hasattr(self, 'callinfocollection'): metainterp_sd.callinfocollection = self.callinfocollection # - return optimize_trace(metainterp_sd, loop, self.enable_opts, + return optimize_trace(metainterp_sd, None, loop, + self.enable_opts, start_state=start_state, export_state=export_state) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py @@ -15,6 +15,7 @@ from rpython.jit.metainterp.history import TreeLoop, JitCellToken from rpython.jit.metainterp.optimizeopt.test.test_optimizeopt import FakeMetaInterpStaticData from rpython.jit.metainterp.resoperation import ResOperation, rop +from rpython.jit.metainterp import resume class BaseTestGenerateGuards(BaseTest): @@ -798,14 +799,15 @@ if hasattr(self, 'callinfocollection'): metainterp_sd.callinfocollection = self.callinfocollection # - optimize_trace(metainterp_sd, bridge, self.enable_opts) + optimize_trace(metainterp_sd, None, bridge, self.enable_opts) def optimize_bridge(self, loops, bridge, expected, expected_target='Loop', **boxvalues): if isinstance(loops, str): loops = (loops, ) - loops = [self.parse(loop) for loop in loops] - bridge = self.parse(bridge) + loops = [self.parse(loop, postprocess=self.postprocess) + for loop in loops] + bridge = self.parse(bridge, postprocess=self.postprocess) self.add_guard_future_condition(bridge) for loop in loops: loop.preamble = self.unroll_and_optimize(loop) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_zdisable_opts.py b/rpython/jit/metainterp/optimizeopt/test/test_zdisable_opts.py --- a/rpython/jit/metainterp/optimizeopt/test/test_zdisable_opts.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_zdisable_opts.py @@ -13,7 +13,7 @@ def optimize_loop(self, ops, expected, expected_preamble=None, call_pure_results=None, expected_short=None): - loop = self.parse(ops) + loop = self.parse(ops, postprocess=self.postprocess) if expected != "crash!": expected = self.parse(expected) if expected_preamble: diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py --- a/rpython/jit/metainterp/optimizeopt/unroll.py +++ b/rpython/jit/metainterp/optimizeopt/unroll.py @@ -1,6 +1,5 @@ import sys -from rpython.jit.metainterp.compile import ResumeGuardDescr from rpython.jit.metainterp.history import TargetToken, JitCellToken, Const from rpython.jit.metainterp.inliner import Inliner from rpython.jit.metainterp.optimize import InvalidLoop @@ -8,17 +7,18 @@ from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer, Optimization from rpython.jit.metainterp.optimizeopt.virtualstate import (VirtualStateConstructor, ShortBoxes, BadVirtualState, VirtualStatesCantMatch) -from rpython.jit.metainterp.resoperation import rop, ResOperation +from rpython.jit.metainterp.resoperation import rop, ResOperation, GuardResOp from rpython.jit.metainterp.resume import Snapshot +from rpython.jit.metainterp import compile from rpython.rlib.debug import debug_print, debug_start, debug_stop # FIXME: Introduce some VirtualOptimizer super class instead -def optimize_unroll(metainterp_sd, loop, optimizations, +def optimize_unroll(metainterp_sd, jitdriver_sd, loop, optimizations, inline_short_preamble=True, start_state=None, export_state=True): - opt = UnrollOptimizer(metainterp_sd, loop, optimizations) + opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, loop, optimizations) opt.inline_short_preamble = inline_short_preamble return opt.propagate_all_forward(start_state, export_state) @@ -52,8 +52,9 @@ inline_short_preamble = True - def __init__(self, metainterp_sd, loop, optimizations): - self.optimizer = UnrollableOptimizer(metainterp_sd, loop, optimizations) + def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations): + self.optimizer = UnrollableOptimizer(metainterp_sd, jitdriver_sd, + loop, optimizations) self.boxes_created_this_iteration = None def get_virtual_state(self, args): @@ -560,8 +561,11 @@ for guard in extra_guards: if guard.is_guard(): - descr = patchguardop.getdescr().clone_if_mutable() - guard.setdescr(descr) + assert isinstance(patchguardop, GuardResOp) + assert isinstance(guard, GuardResOp) + guard.rd_snapshot = patchguardop.rd_snapshot + guard.rd_frame_info_list = patchguardop.rd_frame_info_list + guard.setdescr(compile.ResumeAtPositionDescr()) self.optimizer.send_extra_operation(guard) try: @@ -590,8 +594,11 @@ if newop.is_guard(): if not patchguardop: raise InvalidLoop("would like to have short preamble, but it has a guard and there's no guard_future_condition") - descr = patchguardop.getdescr().clone_if_mutable() - newop.setdescr(descr) + assert isinstance(newop, GuardResOp) + assert isinstance(patchguardop, GuardResOp) + newop.rd_snapshot = patchguardop.rd_snapshot + newop.rd_frame_info_list = patchguardop.rd_frame_info_list + newop.setdescr(compile.ResumeAtPositionDescr()) self.optimizer.send_extra_operation(newop) if shop.result in assumed_classes: classbox = self.getvalue(newop.result).get_constant_class(self.optimizer.cpu) diff --git a/rpython/jit/metainterp/optimizeopt/util.py b/rpython/jit/metainterp/optimizeopt/util.py --- a/rpython/jit/metainterp/optimizeopt/util.py +++ b/rpython/jit/metainterp/optimizeopt/util.py @@ -164,8 +164,6 @@ assert op1.result.same_box(remap[op2.result]) else: remap[op2.result] = op1.result - if op1.getopnum() not in (rop.JUMP, rop.LABEL): # xxx obscure - assert op1.getdescr() == op2.getdescr() if op1.getfailargs() or op2.getfailargs(): assert len(op1.getfailargs()) == len(op2.getfailargs()) if strict_fail_args: diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -12,7 +12,7 @@ from rpython.jit.metainterp.jitprof import EmptyProfiler from rpython.jit.metainterp.logger import Logger from rpython.jit.metainterp.optimizeopt.util import args_dict -from rpython.jit.metainterp.resoperation import rop +from rpython.jit.metainterp.resoperation import rop, GuardResOp from rpython.rlib import nonconst, rstack from rpython.rlib.debug import debug_start, debug_stop, debug_print from rpython.rlib.debug import have_debug_prints, make_sure_not_resized @@ -1874,23 +1874,15 @@ moreargs = [box] + extraargs else: moreargs = list(extraargs) - if opnum == rop.GUARD_NOT_FORCED or opnum == rop.GUARD_NOT_FORCED_2: - resumedescr = compile.ResumeGuardForcedDescr(self.staticdata, - self.jitdriver_sd) - elif opnum == rop.GUARD_NOT_INVALIDATED: - resumedescr = compile.ResumeGuardNotInvalidated() - elif opnum == rop.GUARD_FUTURE_CONDITION: - resumedescr = compile.ResumeAtPositionDescr() - else: - resumedescr = compile.ResumeGuardDescr() - guard_op = self.history.record(opnum, moreargs, None, descr=resumedescr) - self.capture_resumedata(resumedescr, resumepc) + guard_op = self.history.record(opnum, moreargs, None) + assert isinstance(guard_op, GuardResOp) + self.capture_resumedata(guard_op, resumepc) self.staticdata.profiler.count_ops(opnum, Counters.GUARDS) # count self.attach_debug_info(guard_op) return guard_op - def capture_resumedata(self, resumedescr, resumepc=-1): + def capture_resumedata(self, guard_op, resumepc=-1): virtualizable_boxes = None if (self.jitdriver_sd.virtualizable_info is not None or self.jitdriver_sd.greenfield_info is not None): @@ -1902,7 +1894,7 @@ if resumepc >= 0: frame.pc = resumepc resume.capture_resumedata(self.framestack, virtualizable_boxes, - self.virtualref_boxes, resumedescr) + self.virtualref_boxes, guard_op) if self.framestack: self.framestack[-1].pc = saved_pc @@ -2147,7 +2139,9 @@ assert isinstance(key, compile.ResumeGuardDescr) # store the resumekey.wref_original_loop_token() on 'self' to make # sure that it stays alive as long as this MetaInterp - self.resumekey_original_loop_token = key.wref_original_loop_token() + self.resumekey_original_loop_token = key.rd_loop_token.loop_token_wref() + if self.resumekey_original_loop_token is None: + raise compile.giveup() # should be rare self.staticdata.try_to_free_some_loops() self.initialize_state_from_guard_failure(key, deadframe) try: @@ -2163,13 +2157,8 @@ self.seen_loop_header_for_jdindex = -1 if isinstance(key, compile.ResumeAtPositionDescr): self.seen_loop_header_for_jdindex = self.jitdriver_sd.index - dont_change_position = True - else: - dont_change_position = False try: - self.prepare_resume_from_failure(key.guard_opnum, - dont_change_position, - deadframe) + self.prepare_resume_from_failure(key.guard_opnum, deadframe) if self.resumekey_original_loop_token is None: # very rare case raise SwitchToBlackhole(Counters.ABORT_BRIDGE) self.interpret() @@ -2312,12 +2301,12 @@ else: assert 0 self.jitdriver_sd.warmstate.execute_assembler(loop_token, *args) - def prepare_resume_from_failure(self, opnum, dont_change_position, - deadframe): + def prepare_resume_from_failure(self, opnum, deadframe): frame = self.framestack[-1] - if opnum == rop.GUARD_TRUE: # a goto_if_not that jumps only now - if not dont_change_position: - frame.pc = frame.jitcode.follow_jump(frame.pc) + if opnum == rop.GUARD_FUTURE_CONDITION: + pass + elif opnum == rop.GUARD_TRUE: # a goto_if_not that jumps only now + frame.pc = frame.jitcode.follow_jump(frame.pc) elif opnum == rop.GUARD_FALSE: # a goto_if_not that stops jumping; pass # or a switch that was in its "default" case elif opnum == rop.GUARD_VALUE or opnum == rop.GUARD_CLASS: @@ -2341,12 +2330,11 @@ pass # XXX we want to do something special in resume descr, # but not now elif opnum == rop.GUARD_NO_OVERFLOW: # an overflow now detected - if not dont_change_position: - self.execute_raised(OverflowError(), constant=True) - try: - self.finishframe_exception() - except ChangeFrame: - pass + self.execute_raised(OverflowError(), constant=True) + try: + self.finishframe_exception() + except ChangeFrame: + pass elif opnum == rop.GUARD_OVERFLOW: # no longer overflowing self.clear_exception() else: diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -91,8 +91,6 @@ def clone(self): args = self.getarglist() descr = self.getdescr() - if descr is not None: - descr = descr.clone_if_mutable() op = ResOperation(self.getopnum(), args[:], self.result, descr) if not we_are_translated(): op.name = self.name @@ -217,6 +215,9 @@ _fail_args = None + rd_snapshot = None + rd_frame_info_list = None + def getfailargs(self): return self._fail_args @@ -225,12 +226,18 @@ def copy_and_change(self, opnum, args=None, result=None, descr=None): newop = AbstractResOp.copy_and_change(self, opnum, args, result, descr) + assert isinstance(newop, GuardResOp) newop.setfailargs(self.getfailargs()) + newop.rd_snapshot = self.rd_snapshot + newop.rd_frame_info_list = self.rd_frame_info_list return newop def clone(self): newop = AbstractResOp.clone(self) + assert isinstance(newop, GuardResOp) newop.setfailargs(self.getfailargs()) + newop.rd_snapshot = self.rd_snapshot + newop.rd_frame_info_list = self.rd_frame_info_list return newop # ============ diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py --- a/rpython/jit/metainterp/resume.py +++ b/rpython/jit/metainterp/resume.py @@ -55,7 +55,7 @@ back.get_list_of_active_boxes(True)) def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, - storage): + snapshot_storage): n = len(framestack) - 1 if virtualizable_boxes is not None: boxes = virtualref_boxes + virtualizable_boxes @@ -66,14 +66,14 @@ _ensure_parent_resumedata(framestack, n) frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list, top.jitcode, top.pc) - storage.rd_frame_info_list = frame_info_list + snapshot_storage.rd_frame_info_list = frame_info_list snapshot = Snapshot(top.parent_resumedata_snapshot, top.get_list_of_active_boxes(False)) snapshot = Snapshot(snapshot, boxes) - storage.rd_snapshot = snapshot + snapshot_storage.rd_snapshot = snapshot else: - storage.rd_frame_info_list = None - storage.rd_snapshot = Snapshot(None, boxes) + snapshot_storage.rd_frame_info_list = None + snapshot_storage.rd_snapshot = Snapshot(None, boxes) # # The following is equivalent to the RPython-level declaration: @@ -270,8 +270,9 @@ class ResumeDataVirtualAdder(VirtualVisitor): - def __init__(self, storage, memo): + def __init__(self, storage, snapshot_storage, memo): self.storage = storage + self.snapshot_storage = snapshot_storage self.memo = memo def make_virtual_info(self, value, fieldnums): @@ -357,13 +358,14 @@ storage = self.storage # make sure that nobody attached resume data to this guard yet assert not storage.rd_numb - snapshot = storage.rd_snapshot + snapshot = self.snapshot_storage.rd_snapshot assert snapshot is not None # is that true? numb, liveboxes_from_env, v = self.memo.number(optimizer, snapshot) self.liveboxes_from_env = liveboxes_from_env self.liveboxes = {} storage.rd_numb = numb - storage.rd_snapshot = None + self.snapshot_storage.rd_snapshot = None + storage.rd_frame_info_list = self.snapshot_storage.rd_frame_info_list # collect liveboxes and virtuals n = len(liveboxes_from_env) - v diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -2764,7 +2764,8 @@ return i # seen = [] - def my_optimize_trace(metainterp_sd, loop, enable_opts, *args, **kwds): + def my_optimize_trace(metainterp_sd, jitdriver_sd, loop, enable_opts, + *args, **kwds): seen.append('unroll' in enable_opts) raise InvalidLoop old_optimize_trace = optimizeopt.optimize_trace diff --git a/rpython/jit/metainterp/test/test_compile.py b/rpython/jit/metainterp/test/test_compile.py --- a/rpython/jit/metainterp/test/test_compile.py +++ b/rpython/jit/metainterp/test/test_compile.py @@ -10,6 +10,9 @@ from rpython.jit.metainterp.optimizeopt import ALL_OPTS_DICT class FakeCPU(object): + class Storage: + pass + class tracker: pass @@ -18,6 +21,7 @@ self.seen = [] def compile_loop(self, inputargs, operations, token, log=True, name='', logger=None): + token.compiled_loop_token = self.Storage() self.seen.append((inputargs, operations, token)) class FakeLogger(object): diff --git a/rpython/jit/metainterp/test/test_resume.py b/rpython/jit/metainterp/test/test_resume.py --- a/rpython/jit/metainterp/test/test_resume.py +++ b/rpython/jit/metainterp/test/test_resume.py @@ -123,7 +123,7 @@ class FakeVirtualValue(AbstractVirtualValue): def visitor_dispatch_virtual_type(self, *args): return FakeVInfo() - modifier = ResumeDataVirtualAdder(None, None) + modifier = ResumeDataVirtualAdder(None, None, None) v1 = FakeVirtualValue(None, None) vinfo1 = modifier.make_virtual_info(v1, [1, 2, 4]) vinfo2 = modifier.make_virtual_info(v1, [1, 2, 4]) @@ -618,7 +618,7 @@ FakeFrame("code2", 9, c3, b2)] capture_resumedata(fs, None, [], storage) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) liveboxes = modifier.finish(FakeOptimizer({})) metainterp = MyMetaInterp() @@ -1022,7 +1022,7 @@ def test_register_virtual_fields(): b1, b2 = BoxInt(), BoxInt() vbox = BoxPtr() - modifier = ResumeDataVirtualAdder(None, None) + modifier = ResumeDataVirtualAdder(None, None, None) modifier.liveboxes_from_env = {} modifier.liveboxes = {} modifier.vfieldboxes = {} @@ -1031,7 +1031,7 @@ b2: UNASSIGNED} assert modifier.vfieldboxes == {vbox: [b1, b2]} - modifier = ResumeDataVirtualAdder(None, None) + modifier = ResumeDataVirtualAdder(None, None, None) modifier.liveboxes_from_env = {vbox: tag(0, TAGVIRTUAL)} modifier.liveboxes = {} modifier.vfieldboxes = {} @@ -1061,7 +1061,7 @@ b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**16), ConstInt(-65)] storage = make_storage(b1s, b2s, b3s) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) liveboxes = modifier.finish(FakeOptimizer({})) assert storage.rd_snapshot is None cpu = MyCPU([]) @@ -1075,14 +1075,14 @@ b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**16), ConstInt(-65)] storage = make_storage(b1s, b2s, b3s) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) modifier.finish(FakeOptimizer({})) assert len(memo.consts) == 2 assert storage.rd_consts is memo.consts b1s, b2s, b3s = [ConstInt(sys.maxint), ConstInt(2**17), ConstInt(-65)] storage2 = make_storage(b1s, b2s, b3s) - modifier2 = ResumeDataVirtualAdder(storage2, memo) + modifier2 = ResumeDataVirtualAdder(storage2, storage2, memo) modifier2.finish(FakeOptimizer({})) assert len(memo.consts) == 3 assert storage2.rd_consts is memo.consts @@ -1137,7 +1137,7 @@ b1s, b2s, b3s = [BoxInt(1), BoxInt(2), BoxInt(3)] storage = make_storage(b1s, b2s, b3s) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) b1_2 = BoxInt() class FakeValue(object): @@ -1169,7 +1169,7 @@ b1s = ConstInt(111) storage = make_storage(b1s, b2s, b3s) memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) liveboxes = modifier.finish(FakeOptimizer({})) b2t, b3t = [BoxPtr(demo55o), BoxInt(33)] newboxes = _resume_remap(liveboxes, [b2s, b3s], b2t, b3t) @@ -1190,7 +1190,7 @@ c1s = ConstInt(111) storage = Storage() memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) modifier.liveboxes_from_env = {} modifier.liveboxes = {} modifier.vfieldboxes = {} @@ -1273,7 +1273,7 @@ c1s = ConstInt(111) storage = Storage() memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) modifier.liveboxes_from_env = {} modifier.liveboxes = {} modifier.vfieldboxes = {} @@ -1321,7 +1321,7 @@ c1s = ConstInt(111) storage = Storage() memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) modifier.liveboxes_from_env = {} modifier.liveboxes = {} modifier.vfieldboxes = {} @@ -1364,7 +1364,7 @@ b2s, b4s = [BoxPtr(), BoxPtr()] storage = Storage() memo = ResumeDataLoopMemo(FakeMetaInterpStaticData()) - modifier = ResumeDataVirtualAdder(storage, memo) + modifier = ResumeDataVirtualAdder(storage, storage, memo) modifier.liveboxes_from_env = {} modifier.liveboxes = {} modifier.vfieldboxes = {} @@ -1403,7 +1403,7 @@ class Storage(object): pass storage = Storage() - modifier = ResumeDataVirtualAdder(storage, None) + modifier = ResumeDataVirtualAdder(storage, storage, None) modifier._add_pending_fields([]) assert not storage.rd_pendingfields # @@ -1411,7 +1411,7 @@ pass field_a = FieldDescr() storage = Storage() - modifier = ResumeDataVirtualAdder(storage, None) + modifier = ResumeDataVirtualAdder(storage, storage, None) modifier.liveboxes_from_env = {42: rffi.cast(rffi.SHORT, 1042), 61: rffi.cast(rffi.SHORT, 1061)} modifier._add_pending_fields([(field_a, 42, 61, -1)]) @@ -1425,7 +1425,7 @@ # array_a = FieldDescr() storage = Storage() - modifier = ResumeDataVirtualAdder(storage, None) + modifier = ResumeDataVirtualAdder(storage, storage, None) modifier.liveboxes_from_env = {42: rffi.cast(rffi.SHORT, 1042), 61: rffi.cast(rffi.SHORT, 1061), 62: rffi.cast(rffi.SHORT, 1062), @@ -1506,7 +1506,7 @@ metainterp_sd = FakeMetaInterpStaticData() metainterp_sd.options = options memo = ResumeDataLoopMemo(metainterp_sd) - modifier = ResumeDataVirtualAdder(None, memo) + modifier = ResumeDataVirtualAdder(None, None, memo) for i in range(5): assert not modifier._invalidation_needed(5, i) diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py --- a/rpython/jit/tool/oparser.py +++ b/rpython/jit/tool/oparser.py @@ -61,9 +61,10 @@ def __init__(self, input, cpu, namespace, type_system, boxkinds, invent_fail_descr=default_fail_descr, - nonstrict=False): + nonstrict=False, postproces=None): self.input = input self.vars = {} + self._postproces = postproces self.cpu = cpu self._consts = namespace self.type_system = type_system @@ -237,8 +238,6 @@ fail_args.append(fail_arg) if descr is None and self.invent_fail_descr: descr = self.invent_fail_descr(self.model, opnum, fail_args) - if hasattr(descr, '_oparser_uses_descr_of_guard'): - descr._oparser_uses_descr_of_guard(self, fail_args) else: fail_args = None if opnum == rop.FINISH: @@ -250,7 +249,7 @@ return opnum, args, descr, fail_args - def create_op(self, opnum, args, result, descr): + def create_op(self, opnum, args, result, descr, fail_args): if opnum == ESCAPE_OP.OPNUM: op = ESCAPE_OP(result) op.initarglist(args) @@ -262,7 +261,12 @@ assert descr is None return op else: - return ResOperation(opnum, args, result, descr) + res = ResOperation(opnum, args, result, descr) + if fail_args is not None: + res.setfailargs(fail_args) + if self._postproces: + self._postproces(res) + return res def parse_result_op(self, line): res, op = line.split("=", 1) @@ -273,16 +277,12 @@ raise ParseError("Double assign to var %s in line: %s" % (res, line)) rvar = self.box_for_var(res) self.vars[res] = rvar - res = self.create_op(opnum, args, rvar, descr) - if fail_args is not None: - res.setfailargs(fail_args) + res = self.create_op(opnum, args, rvar, descr, fail_args) return res def parse_op_no_result(self, line): opnum, args, descr, fail_args = self.parse_op(line) - res = self.create_op(opnum, args, None, descr) - if fail_args is not None: - res.setfailargs(fail_args) + res = self.create_op(opnum, args, None, descr, fail_args) return res def parse_next_op(self, line): @@ -377,11 +377,12 @@ def parse(input, cpu=None, namespace=None, type_system='lltype', boxkinds=None, invent_fail_descr=default_fail_descr, - no_namespace=False, nonstrict=False, OpParser=OpParser): + no_namespace=False, nonstrict=False, OpParser=OpParser, + postprocess=None): if namespace is None and not no_namespace: namespace = {} return OpParser(input, cpu, namespace, type_system, boxkinds, - invent_fail_descr, nonstrict).parse() + invent_fail_descr, nonstrict, postprocess).parse() def pure_parse(*args, **kwds): kwds['invent_fail_descr'] = None _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit