Author: Jeremy Thurgood <fir...@gmail.com> Branch: unrecursive-opt Changeset: r79956:9c9cd68a9013 Date: 2015-10-03 17:38 +0200 http://bitbucket.org/pypy/pypy/changeset/9c9cd68a9013/
Log: Move intbounds into non-recursive model. diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py --- a/rpython/jit/metainterp/optimizeopt/heap.py +++ b/rpython/jit/metainterp/optimizeopt/heap.py @@ -500,6 +500,9 @@ # default case: produce the operation self.make_nonnull(op.getarg(0)) self.emit_operation(op) + self.optimize_GETFIELD_GC_I_callback(op, structinfo, cf) + + def optimize_GETFIELD_GC_I_callback(self, op, structinfo, cf): # then remember the result of reading the field structinfo.setfield(op.getdescr(), op.getarg(0), op, self, cf) optimize_GETFIELD_GC_R = optimize_GETFIELD_GC_I @@ -552,6 +555,9 @@ # default case: produce the operation self.make_nonnull(op.getarg(0)) self.emit_operation(op) + self.optimize_GETARRAYITEM_GC_I_callback(op, cf, arrayinfo, indexb) + + def optimize_GETARRAYITEM_GC_I_callback(self, op, cf, arrayinfo, indexb): # the remember the result of reading the array item if cf is not None: arrayinfo.setitem(op.getdescr(), indexb.getint(), diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py --- a/rpython/jit/metainterp/optimizeopt/intbounds.py +++ b/rpython/jit/metainterp/optimizeopt/intbounds.py @@ -38,16 +38,27 @@ return n +class IntBoundsCallbackArgs(object): + def __init__(self, op, callback_func=None, b1=None, b2=None): + self.op = op + self.callback_func = callback_func + self.b1 = b1 + self.b2 = b2 + + def callback(self): + if self.callback_func is not None: + self.callback_func(self.op, self.b1, self.b2) + + class OptIntBounds(Optimization): """Keeps track of the bounds placed on integers by guards and remove redundant guards""" + def opt_default(self, op): + return IntBoundsCallbackArgs(op) + def propagate_forward(self, op): - dispatch_opt(self, op) - - def opt_default(self, op): - assert not op.is_ovf() - self.emit_operation(op) + return dispatch_opt(self, op) def propagate_bounds_backward(self, box): # FIXME: This takes care of the instruction where box is the reuslt @@ -61,7 +72,9 @@ dispatch_bounds_ops(self, box) def _optimize_guard_true_false_value(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self._optimize_guard_true_false_value_callback) + + def _optimize_guard_true_false_value_callback(self, op, bn1, bn2): if op.getarg(0).type == 'i': self.propagate_bounds_backward(op.getarg(0)) @@ -79,8 +92,10 @@ self.make_equal_to(op, v1) else: self.make_constant_int(op, 0) - return - self.emit_operation(op) + return None + return IntBoundsCallbackArgs(op, self.optimize_INT_OR_or_XOR_callback, b1, b2) + + def optimize_INT_OR_or_XOR_callback(self, op, b1, b2): if b1.known_ge(IntBound(0, 0)) and \ b2.known_ge(IntBound(0, 0)): r = self.getintbound(op) @@ -93,8 +108,9 @@ def optimize_INT_AND(self, op): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_AND_callback, b1, b2) + def optimize_INT_AND_callback(self, op, b1, b2): r = self.getintbound(op) if b2.is_constant(): val = b2.lower @@ -109,7 +125,9 @@ r.intersect(IntBound(0, next_pow2_m1(lesser))) def optimize_INT_SUB(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_SUB_callback) + + def optimize_INT_SUB_callback(self, op, bn1, bn2): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) b = b1.sub_bound(b2) @@ -120,8 +138,7 @@ arg1 = self.get_box_replacement(op.getarg(0)) arg2 = self.get_box_replacement(op.getarg(1)) if self.is_raw_ptr(arg1) or self.is_raw_ptr(arg2): - self.emit_operation(op) - return + return IntBoundsCallbackArgs(op) v1 = self.getintbound(arg1) v2 = self.getintbound(arg2) @@ -155,7 +172,9 @@ arg2 = ConstInt(sum) op = self.replace_op_with(op, rop.INT_ADD, args=[arg1, arg2]) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_ADD_callback) + + def optimize_INT_ADD_callback(self, op, bn1, bn2): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) r = self.getintbound(op) @@ -166,7 +185,9 @@ def optimize_INT_MUL(self, op): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_MUL_callback, b1, b2) + + def optimize_INT_MUL_callback(self, op, b1, b2): r = self.getintbound(op) b = b1.mul_bound(b2) if b.bounded(): @@ -175,7 +196,9 @@ def optimize_INT_FLOORDIV(self, op): b1 = self.getintbound(op.getarg(0)) b2 = self.getintbound(op.getarg(1)) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_FLOORDIV_callback, b1, b2) + + def optimize_INT_FLOORDIV_callback(self, op, b1, b2): r = self.getintbound(op) r.intersect(b1.div_bound(b2)) @@ -192,13 +215,15 @@ arg2 = ConstInt(val-1) op = self.replace_op_with(op, rop.INT_AND, args=[arg1, arg2]) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_MOD_callback, b2, known_nonneg) + + def optimize_INT_MOD_callback(self, op, b2, known_nonneg): if b2.is_constant(): val = b2.getint() r = self.getintbound(op) if val < 0: if val == -sys.maxint-1: - return # give up + return None # give up val = -val if known_nonneg: r.make_ge(IntBound(0, 0)) @@ -211,7 +236,11 @@ b1 = self.getintbound(arg0) arg1 = self.get_box_replacement(op.getarg(1)) b2 = self.getintbound(arg1) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_LSHIFT_callback, b1, b2) + + def optimize_INT_LSHIFT_callback(self, op, b1, b2): + arg0 = self.get_box_replacement(op.getarg(0)) + arg1 = self.get_box_replacement(op.getarg(1)) r = self.getintbound(op) b = b1.lshift_bound(b2) r.intersect(b) @@ -230,10 +259,12 @@ if b.has_lower and b.has_upper and b.lower == b.upper: # constant result (likely 0, for rshifts that kill all bits) self.make_constant_int(op, b.lower) - else: - self.emit_operation(op) - r = self.getintbound(op) - r.intersect(b) + return None + return IntBoundsCallbackArgs(op, self.optimize_INT_RSHIFT_callback, b) + + def optimize_INT_RSHIFT_callback(self, op, b, bn): + r = self.getintbound(op) + r.intersect(b) def optimize_GUARD_NO_OVERFLOW(self, op): lastop = self.last_emitted_operation @@ -259,7 +290,7 @@ self.pure_from_args(rop.INT_SUB, [args[0], result], args[1]) #elif opnum == rop.INT_MUL_OVF: # self.pure(rop.INT_MUL, args[:], result) - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_GUARD_OVERFLOW(self, op): # If INT_xxx_OVF was replaced by INT_xxx, *but* we still see @@ -272,7 +303,7 @@ raise InvalidLoop('An INT_xxx_OVF was proven not to overflow but' + 'guarded with GUARD_OVERFLOW') - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_ADD_OVF(self, op): b1 = self.getintbound(op.getarg(0)) @@ -283,7 +314,9 @@ # by optimize_GUARD_NO_OVERFLOW; if we see instead an # optimize_GUARD_OVERFLOW, then InvalidLoop. op = self.replace_op_with(op, rop.INT_ADD) - self.emit_operation(op) # emit the op + return IntBoundsCallbackArgs(op, self.optimize_INT_ADD_OVF_callback, resbound) + + def optimize_INT_ADD_OVF_callback(self, op, resbound, bn): r = self.getintbound(op) r.intersect(resbound) @@ -294,11 +327,13 @@ b1 = self.getintbound(arg1) if arg0.same_box(arg1): self.make_constant_int(op, 0) - return + return None resbound = b0.sub_bound(b1) if resbound.bounded(): op = self.replace_op_with(op, rop.INT_SUB) - self.emit_operation(op) # emit the op + return IntBoundsCallbackArgs(op, self.optimize_INT_SUB_OVF_callback, resbound) + + def optimize_INT_SUB_OVF_callback(self, op, resbound, bn): r = self.getintbound(op) r.intersect(resbound) @@ -308,7 +343,9 @@ resbound = b1.mul_bound(b2) if resbound.bounded(): op = self.replace_op_with(op, rop.INT_MUL) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_INT_MUL_OVF_callback, resbound) + + def optimize_INT_MUL_OVF_callback(self, op, resbound, bn): r = self.getintbound(op) r.intersect(resbound) @@ -322,7 +359,7 @@ elif b1.known_ge(b2) or arg1 is arg2: self.make_constant_int(op, 0) else: - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_GT(self, op): arg1 = self.get_box_replacement(op.getarg(0)) @@ -334,7 +371,7 @@ elif b1.known_le(b2) or arg1 is arg2: self.make_constant_int(op, 0) else: - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_LE(self, op): arg1 = self.get_box_replacement(op.getarg(0)) @@ -346,7 +383,7 @@ elif b1.known_gt(b2): self.make_constant_int(op, 0) else: - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_GE(self, op): arg1 = self.get_box_replacement(op.getarg(0)) @@ -358,7 +395,7 @@ elif b1.known_lt(b2): self.make_constant_int(op, 0) else: - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_EQ(self, op): arg0 = self.get_box_replacement(op.getarg(0)) @@ -372,7 +409,7 @@ elif arg0.same_box(arg1): self.make_constant_int(op, 1) else: - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_NE(self, op): arg0 = self.get_box_replacement(op.getarg(0)) @@ -386,14 +423,14 @@ elif arg0 is arg1: self.make_constant_int(op, 0) else: - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_FORCE_GE_ZERO(self, op): b = self.getintbound(op.getarg(0)) if b.known_ge(IntBound(0, 0)): self.make_equal_to(op, op.getarg(0)) else: - self.emit_operation(op) + return IntBoundsCallbackArgs(op) def optimize_INT_SIGNEXT(self, op): b = self.getintbound(op.getarg(0)) @@ -404,29 +441,39 @@ if bounds.contains_bound(b): self.make_equal_to(op, op.getarg(0)) else: - self.emit_operation(op) - bres = self.getintbound(op) - bres.intersect(bounds) + return IntBoundsCallbackArgs(op, self.optimize_INT_SIGNEXT_callback, bounds) + + def optimize_INT_SIGNEXT_callback(self, op, bounds, bn): + bres = self.getintbound(op) + bres.intersect(bounds) def optimize_ARRAYLEN_GC(self, op): array = self.ensure_ptr_info_arg0(op) - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_ARRAYLEN_GC_callback, array) + + def optimize_ARRAYLEN_GC_callback(self, op, array, bn): self.optimizer.setintbound(op, array.getlenbound(None)) def optimize_STRLEN(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_STRLEN_callback) + + def optimize_STRLEN_callback(self, op, bn1, bn2): self.make_nonnull_str(op.getarg(0), vstring.mode_string) array = self.getptrinfo(op.getarg(0)) self.optimizer.setintbound(op, array.getlenbound(vstring.mode_string)) def optimize_UNICODELEN(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_UNICODELEN_callback) + + def optimize_UNICODELEN_callback(self, op, bn1, bn2): self.make_nonnull_str(op.getarg(0), vstring.mode_unicode) array = self.getptrinfo(op.getarg(0)) self.optimizer.setintbound(op, array.getlenbound(vstring.mode_unicode)) def optimize_STRGETITEM(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_STRGETITEM_callback) + + def optimize_STRGETITEM_callback(self, op, bn1, bn2): v1 = self.getintbound(op) v2 = self.getptrinfo(op.getarg(0)) intbound = self.getintbound(op.getarg(1)) @@ -438,7 +485,9 @@ v1.make_lt(IntUpperBound(256)) def optimize_GETFIELD_RAW_I(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_GETFIELD_RAW_I_callback) + + def optimize_GETFIELD_RAW_I_callback(self, op, bn1, bn2): descr = op.getdescr() if descr.is_integer_bounded(): b1 = self.getintbound(op) @@ -456,7 +505,9 @@ optimize_GETINTERIORFIELD_GC_F = optimize_GETFIELD_RAW_I def optimize_GETARRAYITEM_RAW_I(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_GETARRAYITEM_RAW_I_callback) + + def optimize_GETARRAYITEM_RAW_I_callback(self, op, bn1, bn2): descr = op.getdescr() if descr and descr.is_item_integer_bounded(): intbound = self.getintbound(op) @@ -469,7 +520,9 @@ optimize_GETARRAYITEM_GC_R = optimize_GETARRAYITEM_RAW_I def optimize_UNICODEGETITEM(self, op): - self.emit_operation(op) + return IntBoundsCallbackArgs(op, self.optimize_UNICODEGETITEM_callback) + + def optimize_UNICODEGETITEM_callback(self, op, bn1, bn2): b1 = self.getintbound(op) b1.make_ge(IntLowerBound(0)) v2 = self.getptrinfo(op.getarg(0)) 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 @@ -272,7 +272,7 @@ def set_optimizations(self, optimizations): if optimizations: - self.first_optimization = optimizations[0] + self.first_optimization = optimizations[1] for i in range(1, len(optimizations)): optimizations[i - 1].next_optimization = optimizations[i] optimizations[-1].next_optimization = self @@ -521,14 +521,14 @@ last = len(ops) for i in range(last): self._really_emitted_operation = None - self.first_optimization.propagate_forward(ops[i]) + self.send_extra_operation(ops[i]) # accumulate counters if flush: self.flush() if extra_jump: - self.first_optimization.propagate_forward(ops[-1]) + self.send_extra_operation(ops[-1]) self.resumedata_memo.update_counters(self.metainterp_sd.profiler) - + return (BasicLoopInfo(newargs, self.quasi_immutable_deps), self._newoperations) @@ -538,7 +538,12 @@ op.set_forwarded(None) def send_extra_operation(self, op): - self.first_optimization.propagate_forward(op) + callback_args = self.optimizations[0].propagate_forward(op) + if callback_args is None: + return + self.optimizations[0].last_emitted_operation = callback_args.op + self.first_optimization.propagate_forward(callback_args.op) + callback_args.callback() def propagate_forward(self, op): dispatch_opt(self, op) diff --git a/rpython/jit/metainterp/optimizeopt/pure.py b/rpython/jit/metainterp/optimizeopt/pure.py --- a/rpython/jit/metainterp/optimizeopt/pure.py +++ b/rpython/jit/metainterp/optimizeopt/pure.py @@ -109,6 +109,9 @@ # otherwise, the operation remains self.emit_operation(op) + self.optimize_default_callback(op, save, nextop) + + def optimize_default_callback(self, op, save, nextop): if op.returns_bool_result(): self.getintbound(op).make_bool() if save: @@ -159,6 +162,9 @@ opnum = OpHelpers.call_for_descr(op.getdescr()) newop = self.optimizer.replace_op_with(op, opnum) self.emit_operation(newop) + self.optimize_CALL_PURE_I_callback(op) + + def optimize_CALL_PURE_I_callback(self, op): self.call_pure_positions.append( len(self.optimizer._newoperations) - 1) 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 @@ -123,7 +123,10 @@ self.make_constant_int(op, 0) else: self.emit_operation(op) - self.optimizer.pure_reverse(op) + self.optimize_INT_SUB_callback(op) + + def optimize_INT_SUB_callback(self, op): + self.optimizer.pure_reverse(op) def optimize_INT_ADD(self, op): if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)): @@ -141,7 +144,10 @@ self.make_equal_to(op, arg1) else: self.emit_operation(op) - self.optimizer.pure_reverse(op) + self.optimize_INT_ADD_callback(op) + + def optimize_INT_ADD_callback(self, op): + self.optimizer.pure_reverse(op) def optimize_INT_MUL(self, op): arg1 = self.get_box_replacement(op.getarg(0)) @@ -228,6 +234,9 @@ self.emit_operation(newop) return self.emit_operation(op) + self.optimize_FLOAT_MUL_callback(op) + + def optimize_FLOAT_MUL_callback(self, op): self.optimizer.pure_reverse(op) def optimize_FLOAT_TRUEDIV(self, op): @@ -253,6 +262,9 @@ def optimize_FLOAT_NEG(self, op): self.emit_operation(op) + self.optimize_FLOAT_NEG_callback(op) + + def optimize_FLOAT_NEG_callback(self, op): self.optimizer.pure_reverse(op) def optimize_guard(self, op, constbox, emit_operation=True): @@ -275,12 +287,15 @@ raise InvalidLoop('A GUARD_VALUE (%s) ' 'was proven to always fail' % r) return - + if emit_operation: self.emit_operation(op) + self.optimize_guard_callback(op, box, constbox) + else: + self.optimize_guard_callback(op, box, constbox) + + def optimize_guard_callback(self, op, box, constbox): self.make_constant(box, constbox) - #if self.optimizer.optheap: XXX - # self.optimizer.optheap.value_updated(value, self.getvalue(constbox)) def optimize_GUARD_ISNULL(self, op): info = self.getptrinfo(op.getarg(0)) @@ -292,6 +307,9 @@ raise InvalidLoop('A GUARD_ISNULL (%s) was proven to always ' 'fail' % r) self.emit_operation(op) + self.optimize_GUARD_ISNULL_callback(op) + + def optimize_GUARD_ISNULL_callback(self, op): self.make_constant(op.getarg(0), self.optimizer.cpu.ts.CONST_NULL) def optimize_GUARD_IS_OBJECT(self, op): @@ -368,6 +386,9 @@ raise InvalidLoop('A GUARD_NONNULL (%s) was proven to always ' 'fail' % r) self.emit_operation(op) + self.optimize_GUARD_NONNULL_callback(op) + + def optimize_GUARD_NONNULL_callback(self, op): self.make_nonnull(op.getarg(0)) self.getptrinfo(op.getarg(0)).mark_last_guard(self.optimizer) @@ -463,9 +484,15 @@ # on the same box. self.optimizer.replace_guard(op, info) self.emit_operation(op) - self.make_constant_class(op.getarg(0), expectedclassbox, False) + self.optimize_GUARD_CLASS_callback_1(op, expectedclassbox) return self.emit_operation(op) + self.optimize_GUARD_CLASS_callback_2(op, expectedclassbox) + + def optimize_GUARD_CLASS_callback_1(self, op, expectedclassbox): + self.make_constant_class(op.getarg(0), expectedclassbox, False) + + def optimize_GUARD_CLASS_callback_2(self, op, expectedclassbox): self.make_constant_class(op.getarg(0), expectedclassbox) def optimize_GUARD_NONNULL_CLASS(self, op): @@ -495,6 +522,9 @@ newop = self.replace_op_with(op, OpHelpers.call_for_descr(op.getdescr())) self.emit_operation(newop) + self.optimize_CALL_LOOPINVARIANT_I_callback(newop, op, key) + + def optimize_CALL_LOOPINVARIANT_I_callback(self, newop, op, key): self.loop_invariant_producer[key] = self.optimizer.getlastop() self.loop_invariant_results[key] = op optimize_CALL_LOOPINVARIANT_R = optimize_CALL_LOOPINVARIANT_I diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -69,13 +69,16 @@ if self._last_guard_not_forced_2 is not None: guard_op = self._last_guard_not_forced_2 self.emit_operation(op) - guard_op = self.optimizer.store_final_boxes_in_guard(guard_op, []) - i = len(self.optimizer._newoperations) - 1 - assert i >= 0 - self.optimizer._newoperations.insert(i, guard_op) + self.optimize_FINISH_callback(op, guard_op) else: self.emit_operation(op) + def optimize_FINISH_callback(self, op, guard_op): + guard_op = self.optimizer.store_final_boxes_in_guard(guard_op, []) + i = len(self.optimizer._newoperations) - 1 + assert i >= 0 + self.optimizer._newoperations.insert(i, guard_op) + def optimize_CALL_MAY_FORCE_I(self, op): effectinfo = op.getdescr().get_extra_info() oopspecindex = effectinfo.oopspecindex @@ -101,8 +104,6 @@ vrefinfo = self.optimizer.metainterp_sd.virtualref_info c_cls = vrefinfo.jit_virtual_ref_const_class vref_descr = vrefinfo.descr - descr_virtual_token = vrefinfo.descr_virtual_token - descr_forced = vrefinfo.descr_forced # # Replace the VIRTUAL_REF operation with a virtual structure of type # 'jit_virtual_ref'. The jit_virtual_ref structure may be forced soon, @@ -113,6 +114,12 @@ newop.set_forwarded(vrefvalue) token = ResOperation(rop.FORCE_TOKEN, []) self.emit_operation(token) + self.optimize_VIRTUAL_REF_callback(op, vrefvalue, newop, token) + + def optimize_VIRTUAL_REF_callback(self, op, vrefvalue, newop, token): + vrefinfo = self.optimizer.metainterp_sd.virtualref_info + descr_virtual_token = vrefinfo.descr_virtual_token + descr_forced = vrefinfo.descr_forced vrefvalue.setfield(descr_virtual_token, newop, token) vrefvalue.setfield(descr_forced, newop, self.optimizer.cpu.ts.CONST_NULLREF) diff --git a/rpython/jit/metainterp/optimizeopt/vstring.py b/rpython/jit/metainterp/optimizeopt/vstring.py --- a/rpython/jit/metainterp/optimizeopt/vstring.py +++ b/rpython/jit/metainterp/optimizeopt/vstring.py @@ -453,7 +453,10 @@ else: self.make_nonnull_str(op, mode) self.emit_operation(op) - self.pure_from_args(mode.STRLEN, [op], op.getarg(0)) + self._optimize_NEWSTR_callback(op, mode) + + def _optimize_NEWSTR_callback(self, op, mode): + self.pure_from_args(mode.STRLEN, [op], op.getarg(0)) def optimize_STRSETITEM(self, op): opinfo = self.getptrinfo(op.getarg(0)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit