PageRenderTime 407ms CodeModel.GetById 141ms app.highlight 180ms RepoModel.GetById 40ms app.codeStats 2ms

/rpython/jit/metainterp/pyjitpl.py

https://bitbucket.org/kcr/pypy
Python | 2788 lines | 2584 code | 94 blank | 110 comment | 88 complexity | 66d59713339bae352d9c3b056ff06f53 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1import py, sys
   2from rpython.rtyper.lltypesystem import lltype, rclass
   3from rpython.rlib.objectmodel import we_are_translated
   4from rpython.rlib.unroll import unrolling_iterable
   5from rpython.rlib.debug import debug_start, debug_stop, debug_print
   6from rpython.rlib.debug import make_sure_not_resized
   7from rpython.rlib import nonconst, rstack
   8
   9from rpython.jit.metainterp import history, compile, resume
  10from rpython.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat
  11from rpython.jit.metainterp.history import Box, TargetToken
  12from rpython.jit.metainterp.resoperation import rop
  13from rpython.jit.metainterp import executor
  14from rpython.jit.metainterp.logger import Logger
  15from rpython.jit.metainterp.jitprof import EmptyProfiler
  16from rpython.rlib.jit import Counters
  17from rpython.jit.metainterp.jitexc import JitException, get_llexception
  18from rpython.jit.metainterp.heapcache import HeapCache
  19from rpython.rlib.objectmodel import specialize
  20from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr
  21from rpython.jit.codewriter import heaptracker
  22from rpython.jit.metainterp.optimizeopt.util import args_dict_box
  23
  24# ____________________________________________________________
  25
  26def arguments(*args):
  27    def decorate(func):
  28        func.argtypes = args
  29        return func
  30    return decorate
  31
  32# ____________________________________________________________
  33
  34
  35class MIFrame(object):
  36    debug = False
  37
  38    def __init__(self, metainterp):
  39        self.metainterp = metainterp
  40        self.registers_i = [None] * 256
  41        self.registers_r = [None] * 256
  42        self.registers_f = [None] * 256
  43
  44    def setup(self, jitcode, greenkey=None):
  45        assert isinstance(jitcode, JitCode)
  46        self.jitcode = jitcode
  47        self.bytecode = jitcode.code
  48        # this is not None for frames that are recursive portal calls
  49        self.greenkey = greenkey
  50        # copy the constants in place
  51        self.copy_constants(self.registers_i, jitcode.constants_i, ConstInt)
  52        self.copy_constants(self.registers_r, jitcode.constants_r, ConstPtr)
  53        self.copy_constants(self.registers_f, jitcode.constants_f, ConstFloat)
  54        self._result_argcode = 'v'
  55        # for resume.py operation
  56        self.parent_resumedata_snapshot = None
  57        self.parent_resumedata_frame_info_list = None
  58        # counter for unrolling inlined loops
  59        self.unroll_iterations = 1
  60
  61    @specialize.arg(3)
  62    def copy_constants(self, registers, constants, ConstClass):
  63        """Copy jitcode.constants[0] to registers[255],
  64                jitcode.constants[1] to registers[254],
  65                jitcode.constants[2] to registers[253], etc."""
  66        if nonconst.NonConstant(0):             # force the right type
  67            constants[0] = ConstClass.value     # (useful for small tests)
  68        i = len(constants) - 1
  69        while i >= 0:
  70            j = 255 - i
  71            assert j >= 0
  72            registers[j] = ConstClass(constants[i])
  73            i -= 1
  74
  75    def cleanup_registers(self):
  76        # To avoid keeping references alive, this cleans up the registers_r.
  77        # It does not clear the references set by copy_constants(), but
  78        # these are all prebuilt constants anyway.
  79        for i in range(self.jitcode.num_regs_r()):
  80            self.registers_r[i] = None
  81
  82    # ------------------------------
  83    # Decoding of the JitCode
  84
  85    @specialize.arg(4)
  86    def prepare_list_of_boxes(self, outvalue, startindex, position, argcode):
  87        assert argcode in 'IRF'
  88        code = self.bytecode
  89        length = ord(code[position])
  90        position += 1
  91        for i in range(length):
  92            index = ord(code[position+i])
  93            if   argcode == 'I': reg = self.registers_i[index]
  94            elif argcode == 'R': reg = self.registers_r[index]
  95            elif argcode == 'F': reg = self.registers_f[index]
  96            else: raise AssertionError(argcode)
  97            outvalue[startindex+i] = reg
  98
  99    def _put_back_list_of_boxes(self, outvalue, startindex, position):
 100        code = self.bytecode
 101        length = ord(code[position])
 102        position += 1
 103        for i in range(length):
 104            index = ord(code[position+i])
 105            box = outvalue[startindex+i]
 106            if   box.type == history.INT:   self.registers_i[index] = box
 107            elif box.type == history.REF:   self.registers_r[index] = box
 108            elif box.type == history.FLOAT: self.registers_f[index] = box
 109            else: raise AssertionError(box.type)
 110
 111    def get_current_position_info(self):
 112        return self.jitcode.get_live_vars_info(self.pc)
 113
 114    def get_list_of_active_boxes(self, in_a_call):
 115        if in_a_call:
 116            # If we are not the topmost frame, self._result_argcode contains
 117            # the type of the result of the call instruction in the bytecode.
 118            # We use it to clear the box that will hold the result: this box
 119            # is not defined yet.
 120            argcode = self._result_argcode
 121            index = ord(self.bytecode[self.pc - 1])
 122            if   argcode == 'i': self.registers_i[index] = history.CONST_FALSE
 123            elif argcode == 'r': self.registers_r[index] = history.CONST_NULL
 124            elif argcode == 'f': self.registers_f[index] = history.CONST_FZERO
 125            self._result_argcode = '?'     # done
 126        #
 127        info = self.get_current_position_info()
 128        start_i = 0
 129        start_r = start_i + info.get_register_count_i()
 130        start_f = start_r + info.get_register_count_r()
 131        total   = start_f + info.get_register_count_f()
 132        # allocate a list of the correct size
 133        env = [None] * total
 134        make_sure_not_resized(env)
 135        # fill it now
 136        for i in range(info.get_register_count_i()):
 137            index = info.get_register_index_i(i)
 138            env[start_i + i] = self.registers_i[index]
 139        for i in range(info.get_register_count_r()):
 140            index = info.get_register_index_r(i)
 141            env[start_r + i] = self.registers_r[index]
 142        for i in range(info.get_register_count_f()):
 143            index = info.get_register_index_f(i)
 144            env[start_f + i] = self.registers_f[index]
 145        return env
 146
 147    def replace_active_box_in_frame(self, oldbox, newbox):
 148        if isinstance(oldbox, history.BoxInt):
 149            count = self.jitcode.num_regs_i()
 150            registers = self.registers_i
 151        elif isinstance(oldbox, history.BoxPtr):
 152            count = self.jitcode.num_regs_r()
 153            registers = self.registers_r
 154        elif isinstance(oldbox, history.BoxFloat):
 155            count = self.jitcode.num_regs_f()
 156            registers = self.registers_f
 157        else:
 158            assert 0, oldbox
 159        for i in range(count):
 160            if registers[i] is oldbox:
 161                registers[i] = newbox
 162        if not we_are_translated():
 163            for b in registers[count:]:
 164                assert not oldbox.same_box(b)
 165
 166
 167    def make_result_of_lastop(self, resultbox):
 168        got_type = resultbox.type
 169        # XXX disabled for now, conflicts with str_guard_value
 170        #if not we_are_translated():
 171        #    typeof = {'i': history.INT,
 172        #              'r': history.REF,
 173        #              'f': history.FLOAT}
 174        #    assert typeof[self.jitcode._resulttypes[self.pc]] == got_type
 175        target_index = ord(self.bytecode[self.pc-1])
 176        if got_type == history.INT:
 177            self.registers_i[target_index] = resultbox
 178        elif got_type == history.REF:
 179            #debug_print(' ->',
 180            #            llmemory.cast_ptr_to_adr(resultbox.getref_base()))
 181            self.registers_r[target_index] = resultbox
 182        elif got_type == history.FLOAT:
 183            self.registers_f[target_index] = resultbox
 184        else:
 185            raise AssertionError("bad result box type")
 186
 187    # ------------------------------
 188
 189    for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
 190                    'int_lt', 'int_le', 'int_eq',
 191                    'int_ne', 'int_gt', 'int_ge',
 192                    'int_and', 'int_or', 'int_xor',
 193                    'int_rshift', 'int_lshift', 'uint_rshift',
 194                    'uint_lt', 'uint_le', 'uint_gt', 'uint_ge',
 195                    'uint_floordiv',
 196                    'float_add', 'float_sub', 'float_mul', 'float_truediv',
 197                    'float_lt', 'float_le', 'float_eq',
 198                    'float_ne', 'float_gt', 'float_ge',
 199                    'ptr_eq', 'ptr_ne', 'instance_ptr_eq', 'instance_ptr_ne',
 200                    ]:
 201        exec py.code.Source('''
 202            @arguments("box", "box")
 203            def opimpl_%s(self, b1, b2):
 204                return self.execute(rop.%s, b1, b2)
 205        ''' % (_opimpl, _opimpl.upper())).compile()
 206
 207    for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']:
 208        exec py.code.Source('''
 209            @arguments("box", "box")
 210            def opimpl_%s(self, b1, b2):
 211                self.metainterp.clear_exception()
 212                resbox = self.execute(rop.%s, b1, b2)
 213                self.make_result_of_lastop(resbox)  # same as execute_varargs()
 214                if not isinstance(resbox, Const):
 215                    self.metainterp.handle_possible_overflow_error()
 216                return resbox
 217        ''' % (_opimpl, _opimpl.upper())).compile()
 218
 219    for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert',
 220                    'cast_float_to_int', 'cast_int_to_float',
 221                    'cast_float_to_singlefloat', 'cast_singlefloat_to_float',
 222                    'float_neg', 'float_abs',
 223                    'cast_ptr_to_int', 'cast_int_to_ptr',
 224                    'convert_float_bytes_to_longlong',
 225                    'convert_longlong_bytes_to_float', 'int_force_ge_zero',
 226                    ]:
 227        exec py.code.Source('''
 228            @arguments("box")
 229            def opimpl_%s(self, b):
 230                return self.execute(rop.%s, b)
 231        ''' % (_opimpl, _opimpl.upper())).compile()
 232
 233    @arguments("box")
 234    def opimpl_ptr_nonzero(self, box):
 235        return self.execute(rop.PTR_NE, box, history.CONST_NULL)
 236
 237    @arguments("box")
 238    def opimpl_ptr_iszero(self, box):
 239        return self.execute(rop.PTR_EQ, box, history.CONST_NULL)
 240
 241    @arguments("box")
 242    def opimpl_mark_opaque_ptr(self, box):
 243        return self.execute(rop.MARK_OPAQUE_PTR, box)
 244
 245    @arguments("box", "box")
 246    def opimpl_record_known_class(self, box, clsbox):
 247        from rpython.rtyper.lltypesystem import llmemory
 248        if self.metainterp.heapcache.is_class_known(box):
 249            return
 250        adr = clsbox.getaddr()
 251        bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE)
 252        if bounding_class.subclassrange_max - bounding_class.subclassrange_min == 1:
 253            # precise class knowledge, this can be used
 254            self.execute(rop.RECORD_KNOWN_CLASS, box, clsbox)
 255            self.metainterp.heapcache.class_now_known(box)
 256
 257    @arguments("box")
 258    def _opimpl_any_return(self, box):
 259        self.metainterp.finishframe(box)
 260
 261    opimpl_int_return = _opimpl_any_return
 262    opimpl_ref_return = _opimpl_any_return
 263    opimpl_float_return = _opimpl_any_return
 264
 265    @arguments()
 266    def opimpl_void_return(self):
 267        self.metainterp.finishframe(None)
 268
 269    @arguments("box")
 270    def _opimpl_any_copy(self, box):
 271        return box
 272
 273    opimpl_int_copy   = _opimpl_any_copy
 274    opimpl_ref_copy   = _opimpl_any_copy
 275    opimpl_float_copy = _opimpl_any_copy
 276
 277    @arguments("box")
 278    def _opimpl_any_push(self, box):
 279        self.pushed_box = box
 280
 281    opimpl_int_push   = _opimpl_any_push
 282    opimpl_ref_push   = _opimpl_any_push
 283    opimpl_float_push = _opimpl_any_push
 284
 285    @arguments()
 286    def _opimpl_any_pop(self):
 287        box = self.pushed_box
 288        self.pushed_box = None
 289        return box
 290
 291    opimpl_int_pop   = _opimpl_any_pop
 292    opimpl_ref_pop   = _opimpl_any_pop
 293    opimpl_float_pop = _opimpl_any_pop
 294
 295    @arguments("label")
 296    def opimpl_catch_exception(self, target):
 297        """This is a no-op when run normally.  We can check that
 298        last_exc_value_box is None; it should have been set to None
 299        by the previous instruction.  If the previous instruction
 300        raised instead, finishframe_exception() should have been
 301        called and we would not be there."""
 302        assert self.metainterp.last_exc_value_box is None
 303
 304    @arguments("label")
 305    def opimpl_goto(self, target):
 306        self.pc = target
 307
 308    @arguments("box", "label")
 309    def opimpl_goto_if_not(self, box, target):
 310        switchcase = box.getint()
 311        if switchcase:
 312            opnum = rop.GUARD_TRUE
 313        else:
 314            opnum = rop.GUARD_FALSE
 315        self.generate_guard(opnum, box)
 316        if not switchcase:
 317            self.pc = target
 318
 319    @arguments("box", "label")
 320    def opimpl_goto_if_not_int_is_true(self, box, target):
 321        condbox = self.execute(rop.INT_IS_TRUE, box)
 322        self.opimpl_goto_if_not(condbox, target)
 323
 324    @arguments("box", "label")
 325    def opimpl_goto_if_not_int_is_zero(self, box, target):
 326        condbox = self.execute(rop.INT_IS_ZERO, box)
 327        self.opimpl_goto_if_not(condbox, target)
 328
 329    for _opimpl in ['int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge',
 330                    'ptr_eq', 'ptr_ne']:
 331        exec py.code.Source('''
 332            @arguments("box", "box", "label")
 333            def opimpl_goto_if_not_%s(self, b1, b2, target):
 334                condbox = self.execute(rop.%s, b1, b2)
 335                self.opimpl_goto_if_not(condbox, target)
 336        ''' % (_opimpl, _opimpl.upper())).compile()
 337
 338
 339    def _establish_nullity(self, box, orgpc):
 340        value = box.nonnull()
 341        if value:
 342            if not self.metainterp.heapcache.is_class_known(box):
 343                self.generate_guard(rop.GUARD_NONNULL, box, resumepc=orgpc)
 344        else:
 345            if not isinstance(box, Const):
 346                self.generate_guard(rop.GUARD_ISNULL, box, resumepc=orgpc)
 347                promoted_box = box.constbox()
 348                self.metainterp.replace_box(box, promoted_box)
 349        return value
 350
 351    @arguments("box", "label", "orgpc")
 352    def opimpl_goto_if_not_ptr_nonzero(self, box, target, orgpc):
 353        if not self._establish_nullity(box, orgpc):
 354            self.pc = target
 355
 356    @arguments("box", "label", "orgpc")
 357    def opimpl_goto_if_not_ptr_iszero(self, box, target, orgpc):
 358        if self._establish_nullity(box, orgpc):
 359            self.pc = target
 360
 361    @arguments("box", "box", "box")
 362    def opimpl_int_between(self, b1, b2, b3):
 363        b5 = self.execute(rop.INT_SUB, b3, b1)
 364        if isinstance(b5, ConstInt) and b5.getint() == 1:
 365            # the common case of int_between(a, b, a+1) turns into just INT_EQ
 366            return self.execute(rop.INT_EQ, b2, b1)
 367        else:
 368            b4 = self.execute(rop.INT_SUB, b2, b1)
 369            return self.execute(rop.UINT_LT, b4, b5)
 370
 371    @arguments("box", "descr", "orgpc")
 372    def opimpl_switch(self, valuebox, switchdict, orgpc):
 373        box = self.implement_guard_value(valuebox, orgpc)
 374        search_value = box.getint()
 375        assert isinstance(switchdict, SwitchDictDescr)
 376        try:
 377            self.pc = switchdict.dict[search_value]
 378        except KeyError:
 379            pass
 380
 381    @arguments()
 382    def opimpl_unreachable(self):
 383        raise AssertionError("unreachable")
 384
 385    @arguments("descr")
 386    def opimpl_new(self, sizedescr):
 387        resbox = self.execute_with_descr(rop.NEW, sizedescr)
 388        self.metainterp.heapcache.new(resbox)
 389        return resbox
 390
 391    @arguments("descr")
 392    def opimpl_new_with_vtable(self, sizedescr):
 393        cpu = self.metainterp.cpu
 394        cls = heaptracker.descr2vtable(cpu, sizedescr)
 395        resbox = self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
 396        self.metainterp.heapcache.new(resbox)
 397        self.metainterp.heapcache.class_now_known(resbox)
 398        return resbox
 399
 400    @arguments("box", "descr")
 401    def opimpl_new_array(self, lengthbox, itemsizedescr):
 402        resbox = self.execute_with_descr(rop.NEW_ARRAY, itemsizedescr, lengthbox)
 403        self.metainterp.heapcache.new_array(resbox, lengthbox)
 404        return resbox
 405
 406    @specialize.arg(1)
 407    def _do_getarrayitem_gc_any(self, op, arraybox, indexbox, arraydescr):
 408        tobox = self.metainterp.heapcache.getarrayitem(
 409                arraybox, indexbox, arraydescr)
 410        if tobox:
 411            # sanity check: see whether the current array value
 412            # corresponds to what the cache thinks the value is
 413            resbox = executor.execute(self.metainterp.cpu, self.metainterp, op,
 414                                      arraydescr, arraybox, indexbox)
 415            assert resbox.constbox().same_constant(tobox.constbox())
 416            return tobox
 417        resbox = self.execute_with_descr(op, arraydescr, arraybox, indexbox)
 418        self.metainterp.heapcache.getarrayitem_now_known(
 419                arraybox, indexbox, resbox, arraydescr)
 420        return resbox
 421
 422    @arguments("box", "box", "descr")
 423    def _opimpl_getarrayitem_gc_any(self, arraybox, indexbox, arraydescr):
 424        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC, arraybox,
 425                                            indexbox, arraydescr)
 426
 427    opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any
 428    opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any
 429    opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any
 430
 431    @arguments("box", "box", "descr")
 432    def _opimpl_getarrayitem_raw_any(self, arraybox, indexbox, arraydescr):
 433        return self.execute_with_descr(rop.GETARRAYITEM_RAW,
 434                                       arraydescr, arraybox, indexbox)
 435
 436    opimpl_getarrayitem_raw_i = _opimpl_getarrayitem_raw_any
 437    opimpl_getarrayitem_raw_f = _opimpl_getarrayitem_raw_any
 438
 439    @arguments("box", "box", "descr")
 440    def _opimpl_getarrayitem_raw_pure_any(self, arraybox, indexbox,
 441                                          arraydescr):
 442        return self.execute_with_descr(rop.GETARRAYITEM_RAW_PURE,
 443                                       arraydescr, arraybox, indexbox)
 444
 445    opimpl_getarrayitem_raw_i_pure = _opimpl_getarrayitem_raw_pure_any
 446    opimpl_getarrayitem_raw_f_pure = _opimpl_getarrayitem_raw_pure_any
 447
 448    @arguments("box", "box", "descr")
 449    def _opimpl_getarrayitem_gc_pure_any(self, arraybox, indexbox, arraydescr):
 450        if isinstance(arraybox, ConstPtr) and isinstance(indexbox, ConstInt):
 451            # if the arguments are directly constants, bypass the heapcache
 452            # completely
 453            resbox = executor.execute(self.metainterp.cpu, self.metainterp,
 454                                      rop.GETARRAYITEM_GC_PURE, arraydescr,
 455                                      arraybox, indexbox)
 456            return resbox.constbox()
 457        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_PURE, arraybox,
 458                                            indexbox, arraydescr)
 459
 460    opimpl_getarrayitem_gc_i_pure = _opimpl_getarrayitem_gc_pure_any
 461    opimpl_getarrayitem_gc_r_pure = _opimpl_getarrayitem_gc_pure_any
 462    opimpl_getarrayitem_gc_f_pure = _opimpl_getarrayitem_gc_pure_any
 463
 464    @arguments("box", "box", "box", "descr")
 465    def _opimpl_setarrayitem_gc_any(self, arraybox, indexbox, itembox,
 466                                    arraydescr):
 467        self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox,
 468                                indexbox, itembox)
 469        self.metainterp.heapcache.setarrayitem(
 470                arraybox, indexbox, itembox, arraydescr)
 471
 472    opimpl_setarrayitem_gc_i = _opimpl_setarrayitem_gc_any
 473    opimpl_setarrayitem_gc_r = _opimpl_setarrayitem_gc_any
 474    opimpl_setarrayitem_gc_f = _opimpl_setarrayitem_gc_any
 475
 476    @arguments("box", "box", "box", "descr")
 477    def _opimpl_setarrayitem_raw_any(self, arraybox, indexbox, itembox,
 478                                     arraydescr):
 479        self.execute_with_descr(rop.SETARRAYITEM_RAW, arraydescr, arraybox,
 480                                indexbox, itembox)
 481
 482    opimpl_setarrayitem_raw_i = _opimpl_setarrayitem_raw_any
 483    opimpl_setarrayitem_raw_f = _opimpl_setarrayitem_raw_any
 484
 485    @arguments("box", "descr")
 486    def opimpl_arraylen_gc(self, arraybox, arraydescr):
 487        lengthbox = self.metainterp.heapcache.arraylen(arraybox)
 488        if lengthbox is None:
 489            lengthbox = self.execute_with_descr(
 490                    rop.ARRAYLEN_GC, arraydescr, arraybox)
 491            self.metainterp.heapcache.arraylen_now_known(arraybox, lengthbox)
 492        return lengthbox
 493
 494    @arguments("box", "box", "descr", "orgpc")
 495    def opimpl_check_neg_index(self, arraybox, indexbox, arraydescr, orgpc):
 496        negbox = self.metainterp.execute_and_record(
 497            rop.INT_LT, None, indexbox, history.CONST_FALSE)
 498        negbox = self.implement_guard_value(negbox, orgpc)
 499        if negbox.getint():
 500            # the index is < 0; add the array length to it
 501            lengthbox = self.opimpl_arraylen_gc(arraybox, arraydescr)
 502            indexbox = self.metainterp.execute_and_record(
 503                rop.INT_ADD, None, indexbox, lengthbox)
 504        return indexbox
 505
 506    @arguments("box", "descr", "descr", "descr", "descr")
 507    def opimpl_newlist(self, sizebox, structdescr, lengthdescr,
 508                       itemsdescr, arraydescr):
 509        sbox = self.opimpl_new(structdescr)
 510        self._opimpl_setfield_gc_any(sbox, sizebox, lengthdescr)
 511        abox = self.opimpl_new_array(sizebox, arraydescr)
 512        self._opimpl_setfield_gc_any(sbox, abox, itemsdescr)
 513        return sbox
 514
 515    @arguments("box", "descr", "descr", "descr", "descr")
 516    def opimpl_newlist_hint(self, sizehintbox, structdescr, lengthdescr,
 517                            itemsdescr, arraydescr):
 518        sbox = self.opimpl_new(structdescr)
 519        self._opimpl_setfield_gc_any(sbox, history.CONST_FALSE, lengthdescr)
 520        abox = self.opimpl_new_array(sizehintbox, arraydescr)
 521        self._opimpl_setfield_gc_any(sbox, abox, itemsdescr)
 522        return sbox
 523
 524    @arguments("box", "box", "descr", "descr")
 525    def _opimpl_getlistitem_gc_any(self, listbox, indexbox,
 526                                   itemsdescr, arraydescr):
 527        arraybox = self._opimpl_getfield_gc_any(listbox, itemsdescr)
 528        return self._opimpl_getarrayitem_gc_any(arraybox, indexbox, arraydescr)
 529
 530    opimpl_getlistitem_gc_i = _opimpl_getlistitem_gc_any
 531    opimpl_getlistitem_gc_r = _opimpl_getlistitem_gc_any
 532    opimpl_getlistitem_gc_f = _opimpl_getlistitem_gc_any
 533
 534    @arguments("box", "box", "box", "descr", "descr")
 535    def _opimpl_setlistitem_gc_any(self, listbox, indexbox, valuebox,
 536                                   itemsdescr, arraydescr):
 537        arraybox = self._opimpl_getfield_gc_any(listbox, itemsdescr)
 538        self._opimpl_setarrayitem_gc_any(arraybox, indexbox, valuebox,
 539                                         arraydescr)
 540
 541    opimpl_setlistitem_gc_i = _opimpl_setlistitem_gc_any
 542    opimpl_setlistitem_gc_r = _opimpl_setlistitem_gc_any
 543    opimpl_setlistitem_gc_f = _opimpl_setlistitem_gc_any
 544
 545    @arguments("box", "box", "descr", "orgpc")
 546    def opimpl_check_resizable_neg_index(self, listbox, indexbox,
 547                                         lengthdescr, orgpc):
 548        negbox = self.metainterp.execute_and_record(
 549            rop.INT_LT, None, indexbox, history.CONST_FALSE)
 550        negbox = self.implement_guard_value(negbox, orgpc)
 551        if negbox.getint():
 552            # the index is < 0; add the array length to it
 553            lenbox = self.metainterp.execute_and_record(
 554                rop.GETFIELD_GC, lengthdescr, listbox)
 555            indexbox = self.metainterp.execute_and_record(
 556                rop.INT_ADD, None, indexbox, lenbox)
 557        return indexbox
 558
 559    @arguments("box", "descr")
 560    def _opimpl_getfield_gc_any(self, box, fielddescr):
 561        return self._opimpl_getfield_gc_any_pureornot(
 562                rop.GETFIELD_GC, box, fielddescr)
 563    opimpl_getfield_gc_i = _opimpl_getfield_gc_any
 564    opimpl_getfield_gc_r = _opimpl_getfield_gc_any
 565    opimpl_getfield_gc_f = _opimpl_getfield_gc_any
 566
 567    @arguments("box", "descr")
 568    def _opimpl_getfield_gc_pure_any(self, box, fielddescr):
 569        if isinstance(box, ConstPtr):
 570            # if 'box' is directly a ConstPtr, bypass the heapcache completely
 571            resbox = executor.execute(self.metainterp.cpu, self.metainterp,
 572                                      rop.GETFIELD_GC_PURE, fielddescr, box)
 573            return resbox.constbox()
 574        return self._opimpl_getfield_gc_any_pureornot(
 575                rop.GETFIELD_GC_PURE, box, fielddescr)
 576    opimpl_getfield_gc_i_pure = _opimpl_getfield_gc_pure_any
 577    opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any
 578    opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any
 579
 580    @arguments("box", "box", "descr")
 581    def _opimpl_getinteriorfield_gc_any(self, array, index, descr):
 582        return self.execute_with_descr(rop.GETINTERIORFIELD_GC, descr,
 583                                       array, index)
 584    opimpl_getinteriorfield_gc_i = _opimpl_getinteriorfield_gc_any
 585    opimpl_getinteriorfield_gc_f = _opimpl_getinteriorfield_gc_any
 586    opimpl_getinteriorfield_gc_r = _opimpl_getinteriorfield_gc_any
 587
 588    @specialize.arg(1)
 589    def _opimpl_getfield_gc_any_pureornot(self, opnum, box, fielddescr):
 590        tobox = self.metainterp.heapcache.getfield(box, fielddescr)
 591        if tobox is not None:
 592            # sanity check: see whether the current struct value
 593            # corresponds to what the cache thinks the value is
 594            #resbox = executor.execute(self.metainterp.cpu, self.metainterp,
 595            #                          rop.GETFIELD_GC, fielddescr, box)
 596            # XXX the sanity check does not seem to do anything, remove?
 597            return tobox
 598        resbox = self.execute_with_descr(opnum, fielddescr, box)
 599        self.metainterp.heapcache.getfield_now_known(box, fielddescr, resbox)
 600        return resbox
 601
 602    @arguments("box", "descr", "orgpc")
 603    def _opimpl_getfield_gc_greenfield_any(self, box, fielddescr, pc):
 604        ginfo = self.metainterp.jitdriver_sd.greenfield_info
 605        if (ginfo is not None and fielddescr in ginfo.green_field_descrs
 606            and not self._nonstandard_virtualizable(pc, box)):
 607            # fetch the result, but consider it as a Const box and don't
 608            # record any operation
 609            resbox = executor.execute(self.metainterp.cpu, self.metainterp,
 610                                      rop.GETFIELD_GC_PURE, fielddescr, box)
 611            return resbox.constbox()
 612        # fall-back
 613        return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box)
 614    opimpl_getfield_gc_i_greenfield = _opimpl_getfield_gc_greenfield_any
 615    opimpl_getfield_gc_r_greenfield = _opimpl_getfield_gc_greenfield_any
 616    opimpl_getfield_gc_f_greenfield = _opimpl_getfield_gc_greenfield_any
 617
 618    @arguments("box", "box", "descr")
 619    def _opimpl_setfield_gc_any(self, box, valuebox, fielddescr):
 620        tobox = self.metainterp.heapcache.getfield(box, fielddescr)
 621        if tobox is valuebox:
 622            return
 623        self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
 624        self.metainterp.heapcache.setfield(box, valuebox, fielddescr)
 625    opimpl_setfield_gc_i = _opimpl_setfield_gc_any
 626    opimpl_setfield_gc_r = _opimpl_setfield_gc_any
 627    opimpl_setfield_gc_f = _opimpl_setfield_gc_any
 628
 629    @arguments("box", "box", "box", "descr")
 630    def _opimpl_setinteriorfield_gc_any(self, array, index, value, descr):
 631        self.execute_with_descr(rop.SETINTERIORFIELD_GC, descr,
 632                                array, index, value)
 633    opimpl_setinteriorfield_gc_i = _opimpl_setinteriorfield_gc_any
 634    opimpl_setinteriorfield_gc_f = _opimpl_setinteriorfield_gc_any
 635    opimpl_setinteriorfield_gc_r = _opimpl_setinteriorfield_gc_any
 636
 637
 638    @arguments("box", "descr")
 639    def _opimpl_getfield_raw_any(self, box, fielddescr):
 640        return self.execute_with_descr(rop.GETFIELD_RAW, fielddescr, box)
 641    opimpl_getfield_raw_i = _opimpl_getfield_raw_any
 642    opimpl_getfield_raw_r = _opimpl_getfield_raw_any
 643    opimpl_getfield_raw_f = _opimpl_getfield_raw_any
 644
 645    @arguments("box", "descr")
 646    def _opimpl_getfield_raw_pure_any(self, box, fielddescr):
 647        return self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddescr, box)
 648    opimpl_getfield_raw_i_pure = _opimpl_getfield_raw_pure_any
 649    opimpl_getfield_raw_r_pure = _opimpl_getfield_raw_pure_any
 650    opimpl_getfield_raw_f_pure = _opimpl_getfield_raw_pure_any
 651
 652    @arguments("box", "box", "descr")
 653    def _opimpl_setfield_raw_any(self, box, valuebox, fielddescr):
 654        self.execute_with_descr(rop.SETFIELD_RAW, fielddescr, box, valuebox)
 655    opimpl_setfield_raw_i = _opimpl_setfield_raw_any
 656    opimpl_setfield_raw_r = _opimpl_setfield_raw_any
 657    opimpl_setfield_raw_f = _opimpl_setfield_raw_any
 658
 659    @arguments("box", "box", "box", "descr")
 660    def _opimpl_raw_store(self, addrbox, offsetbox, valuebox, arraydescr):
 661        self.execute_with_descr(rop.RAW_STORE, arraydescr,
 662                                addrbox, offsetbox, valuebox)
 663    opimpl_raw_store_i = _opimpl_raw_store
 664    opimpl_raw_store_f = _opimpl_raw_store
 665
 666    @arguments("box", "box", "descr")
 667    def _opimpl_raw_load(self, addrbox, offsetbox, arraydescr):
 668        return self.execute_with_descr(rop.RAW_LOAD, arraydescr,
 669                                       addrbox, offsetbox)
 670    opimpl_raw_load_i = _opimpl_raw_load
 671    opimpl_raw_load_f = _opimpl_raw_load
 672
 673    @arguments("box", "descr", "descr", "orgpc")
 674    def opimpl_record_quasiimmut_field(self, box, fielddescr,
 675                                       mutatefielddescr, orgpc):
 676        from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
 677        cpu = self.metainterp.cpu
 678        descr = QuasiImmutDescr(cpu, box, fielddescr, mutatefielddescr)
 679        self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box],
 680                                       None, descr=descr)
 681        self.generate_guard(rop.GUARD_NOT_INVALIDATED, resumepc=orgpc)
 682
 683    @arguments("box", "descr", "orgpc")
 684    def opimpl_jit_force_quasi_immutable(self, box, mutatefielddescr, orgpc):
 685        # During tracing, a 'jit_force_quasi_immutable' usually turns into
 686        # the operations that check that the content of 'mutate_xxx' is null.
 687        # If it is actually not null already now, then we abort tracing.
 688        # The idea is that if we use 'jit_force_quasi_immutable' on a freshly
 689        # allocated object, then the GETFIELD_GC will know that the answer is
 690        # null, and the guard will be removed.  So the fact that the field is
 691        # quasi-immutable will have no effect, and instead it will work as a
 692        # regular, probably virtual, structure.
 693        mutatebox = self.execute_with_descr(rop.GETFIELD_GC,
 694                                            mutatefielddescr, box)
 695        if mutatebox.nonnull():
 696            from rpython.jit.metainterp.quasiimmut import do_force_quasi_immutable
 697            do_force_quasi_immutable(self.metainterp.cpu, box.getref_base(),
 698                                     mutatefielddescr)
 699            raise SwitchToBlackhole(Counters.ABORT_FORCE_QUASIIMMUT)
 700        self.generate_guard(rop.GUARD_ISNULL, mutatebox, resumepc=orgpc)
 701
 702    def _nonstandard_virtualizable(self, pc, box):
 703        # returns True if 'box' is actually not the "standard" virtualizable
 704        # that is stored in metainterp.virtualizable_boxes[-1]
 705        if (self.metainterp.jitdriver_sd.virtualizable_info is None and
 706            self.metainterp.jitdriver_sd.greenfield_info is None):
 707            return True      # can occur in case of multiple JITs
 708        standard_box = self.metainterp.virtualizable_boxes[-1]
 709        if standard_box is box:
 710            return False
 711        if self.metainterp.heapcache.is_nonstandard_virtualizable(box):
 712            return True
 713        eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None,
 714                                                   box, standard_box)
 715        eqbox = self.implement_guard_value(eqbox, pc)
 716        isstandard = eqbox.getint()
 717        if isstandard:
 718            self.metainterp.replace_box(box, standard_box)
 719        else:
 720            self.metainterp.heapcache.nonstandard_virtualizables_now_known(box)
 721        return not isstandard
 722
 723    def _get_virtualizable_field_index(self, fielddescr):
 724        # Get the index of a fielddescr.  Must only be called for
 725        # the "standard" virtualizable.
 726        vinfo = self.metainterp.jitdriver_sd.virtualizable_info
 727        return vinfo.static_field_by_descrs[fielddescr]
 728
 729    @arguments("box", "descr", "orgpc")
 730    def _opimpl_getfield_vable(self, box, fielddescr, pc):
 731        if self._nonstandard_virtualizable(pc, box):
 732            return self._opimpl_getfield_gc_any(box, fielddescr)
 733        self.metainterp.check_synchronized_virtualizable()
 734        index = self._get_virtualizable_field_index(fielddescr)
 735        return self.metainterp.virtualizable_boxes[index]
 736
 737    opimpl_getfield_vable_i = _opimpl_getfield_vable
 738    opimpl_getfield_vable_r = _opimpl_getfield_vable
 739    opimpl_getfield_vable_f = _opimpl_getfield_vable
 740
 741    @arguments("box", "box", "descr", "orgpc")
 742    def _opimpl_setfield_vable(self, box, valuebox, fielddescr, pc):
 743        if self._nonstandard_virtualizable(pc, box):
 744            return self._opimpl_setfield_gc_any(box, valuebox, fielddescr)
 745        index = self._get_virtualizable_field_index(fielddescr)
 746        self.metainterp.virtualizable_boxes[index] = valuebox
 747        self.metainterp.synchronize_virtualizable()
 748        # XXX only the index'th field needs to be synchronized, really
 749
 750    opimpl_setfield_vable_i = _opimpl_setfield_vable
 751    opimpl_setfield_vable_r = _opimpl_setfield_vable
 752    opimpl_setfield_vable_f = _opimpl_setfield_vable
 753
 754    def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox):
 755        # Get the index of an array item: the index'th of the array
 756        # described by arrayfielddescr.  Must only be called for
 757        # the "standard" virtualizable.
 758        indexbox = self.implement_guard_value(indexbox, pc)
 759        vinfo = self.metainterp.jitdriver_sd.virtualizable_info
 760        virtualizable_box = self.metainterp.virtualizable_boxes[-1]
 761        virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
 762        arrayindex = vinfo.array_field_by_descrs[arrayfielddescr]
 763        index = indexbox.getint()
 764        # Support for negative index: disabled
 765        # (see codewriter/jtransform.py, _check_no_vable_array).
 766        #if index < 0:
 767        #    index += vinfo.get_array_length(virtualizable, arrayindex)
 768        assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex)
 769        return vinfo.get_index_in_array(virtualizable, arrayindex, index)
 770
 771    @arguments("box", "box", "descr", "descr", "orgpc")
 772    def _opimpl_getarrayitem_vable(self, box, indexbox, fdescr, adescr, pc):
 773        if self._nonstandard_virtualizable(pc, box):
 774            arraybox = self._opimpl_getfield_gc_any(box, fdescr)
 775            return self._opimpl_getarrayitem_gc_any(arraybox, indexbox, adescr)
 776        self.metainterp.check_synchronized_virtualizable()
 777        index = self._get_arrayitem_vable_index(pc, fdescr, indexbox)
 778        return self.metainterp.virtualizable_boxes[index]
 779
 780    opimpl_getarrayitem_vable_i = _opimpl_getarrayitem_vable
 781    opimpl_getarrayitem_vable_r = _opimpl_getarrayitem_vable
 782    opimpl_getarrayitem_vable_f = _opimpl_getarrayitem_vable
 783
 784    @arguments("box", "box", "box", "descr", "descr", "orgpc")
 785    def _opimpl_setarrayitem_vable(self, box, indexbox, valuebox,
 786                                   fdescr, adescr, pc):
 787        if self._nonstandard_virtualizable(pc, box):
 788            arraybox = self._opimpl_getfield_gc_any(box, fdescr)
 789            self._opimpl_setarrayitem_gc_any(arraybox, indexbox, valuebox,
 790                                             adescr)
 791            return
 792        index = self._get_arrayitem_vable_index(pc, fdescr, indexbox)
 793        self.metainterp.virtualizable_boxes[index] = valuebox
 794        self.metainterp.synchronize_virtualizable()
 795        # XXX only the index'th field needs to be synchronized, really
 796
 797    opimpl_setarrayitem_vable_i = _opimpl_setarrayitem_vable
 798    opimpl_setarrayitem_vable_r = _opimpl_setarrayitem_vable
 799    opimpl_setarrayitem_vable_f = _opimpl_setarrayitem_vable
 800
 801    @arguments("box", "descr", "descr", "orgpc")
 802    def opimpl_arraylen_vable(self, box, fdescr, adescr, pc):
 803        if self._nonstandard_virtualizable(pc, box):
 804            arraybox = self._opimpl_getfield_gc_any(box, fdescr)
 805            return self.opimpl_arraylen_gc(arraybox, adescr)
 806        vinfo = self.metainterp.jitdriver_sd.virtualizable_info
 807        virtualizable_box = self.metainterp.virtualizable_boxes[-1]
 808        virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
 809        arrayindex = vinfo.array_field_by_descrs[fdescr]
 810        result = vinfo.get_array_length(virtualizable, arrayindex)
 811        return ConstInt(result)
 812
 813    @arguments("jitcode", "boxes")
 814    def _opimpl_inline_call1(self, jitcode, argboxes):
 815        return self.metainterp.perform_call(jitcode, argboxes)
 816    @arguments("jitcode", "boxes2")
 817    def _opimpl_inline_call2(self, jitcode, argboxes):
 818        return self.metainterp.perform_call(jitcode, argboxes)
 819    @arguments("jitcode", "boxes3")
 820    def _opimpl_inline_call3(self, jitcode, argboxes):
 821        return self.metainterp.perform_call(jitcode, argboxes)
 822
 823    opimpl_inline_call_r_i = _opimpl_inline_call1
 824    opimpl_inline_call_r_r = _opimpl_inline_call1
 825    opimpl_inline_call_r_v = _opimpl_inline_call1
 826    opimpl_inline_call_ir_i = _opimpl_inline_call2
 827    opimpl_inline_call_ir_r = _opimpl_inline_call2
 828    opimpl_inline_call_ir_v = _opimpl_inline_call2
 829    opimpl_inline_call_irf_i = _opimpl_inline_call3
 830    opimpl_inline_call_irf_r = _opimpl_inline_call3
 831    opimpl_inline_call_irf_f = _opimpl_inline_call3
 832    opimpl_inline_call_irf_v = _opimpl_inline_call3
 833
 834    @arguments("box", "boxes", "descr")
 835    def _opimpl_residual_call1(self, funcbox, argboxes, calldescr):
 836        return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
 837    @arguments("box", "boxes2", "descr")
 838    def _opimpl_residual_call2(self, funcbox, argboxes, calldescr):
 839        return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
 840    @arguments("box", "boxes3", "descr")
 841    def _opimpl_residual_call3(self, funcbox, argboxes, calldescr):
 842        return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
 843
 844    opimpl_residual_call_r_i = _opimpl_residual_call1
 845    opimpl_residual_call_r_r = _opimpl_residual_call1
 846    opimpl_residual_call_r_v = _opimpl_residual_call1
 847    opimpl_residual_call_ir_i = _opimpl_residual_call2
 848    opimpl_residual_call_ir_r = _opimpl_residual_call2
 849    opimpl_residual_call_ir_v = _opimpl_residual_call2
 850    opimpl_residual_call_irf_i = _opimpl_residual_call3
 851    opimpl_residual_call_irf_r = _opimpl_residual_call3
 852    opimpl_residual_call_irf_f = _opimpl_residual_call3
 853    opimpl_residual_call_irf_v = _opimpl_residual_call3
 854
 855    @arguments("int", "boxes3", "boxes3")
 856    def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes):
 857        targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
 858        allboxes = greenboxes + redboxes
 859        warmrunnerstate = targetjitdriver_sd.warmstate
 860        assembler_call = False
 861        if warmrunnerstate.inlining:
 862            if warmrunnerstate.can_inline_callable(greenboxes):
 863                portal_code = targetjitdriver_sd.mainjitcode
 864                return self.metainterp.perform_call(portal_code, allboxes,
 865                                                    greenkey=greenboxes)
 866            assembler_call = True
 867            # verify that we have all green args, needed to make sure
 868            # that assembler that we call is still correct
 869            self.verify_green_args(targetjitdriver_sd, greenboxes)
 870        #
 871        return self.do_recursive_call(targetjitdriver_sd, allboxes,
 872                                      assembler_call)
 873
 874    def do_recursive_call(self, targetjitdriver_sd, allboxes,
 875                          assembler_call=False):
 876        portal_code = targetjitdriver_sd.mainjitcode
 877        k = targetjitdriver_sd.portal_runner_adr
 878        funcbox = ConstInt(heaptracker.adr2int(k))
 879        return self.do_residual_call(funcbox, allboxes, portal_code.calldescr,
 880                                     assembler_call=assembler_call,
 881                                     assembler_call_jd=targetjitdriver_sd)
 882
 883    opimpl_recursive_call_i = _opimpl_recursive_call
 884    opimpl_recursive_call_r = _opimpl_recursive_call
 885    opimpl_recursive_call_f = _opimpl_recursive_call
 886    opimpl_recursive_call_v = _opimpl_recursive_call
 887
 888    @arguments("box")
 889    def opimpl_strlen(self, strbox):
 890        return self.execute(rop.STRLEN, strbox)
 891
 892    @arguments("box")
 893    def opimpl_unicodelen(self, unicodebox):
 894        return self.execute(rop.UNICODELEN, unicodebox)
 895
 896    @arguments("box", "box")
 897    def opimpl_strgetitem(self, strbox, indexbox):
 898        return self.execute(rop.STRGETITEM, strbox, indexbox)
 899
 900    @arguments("box", "box")
 901    def opimpl_unicodegetitem(self, unicodebox, indexbox):
 902        return self.execute(rop.UNICODEGETITEM, unicodebox, indexbox)
 903
 904    @arguments("box", "box", "box")
 905    def opimpl_strsetitem(self, strbox, indexbox, newcharbox):
 906        return self.execute(rop.STRSETITEM, strbox, indexbox, newcharbox)
 907
 908    @arguments("box", "box", "box")
 909    def opimpl_unicodesetitem(self, unicodebox, indexbox, newcharbox):
 910        self.execute(rop.UNICODESETITEM, unicodebox, indexbox, newcharbox)
 911
 912    @arguments("box")
 913    def opimpl_newstr(self, lengthbox):
 914        return self.execute(rop.NEWSTR, lengthbox)
 915
 916    @arguments("box")
 917    def opimpl_newunicode(self, lengthbox):
 918        return self.execute(rop.NEWUNICODE, lengthbox)
 919
 920    @arguments("box", "box", "box", "box", "box")
 921    def opimpl_copystrcontent(self, srcbox, dstbox, srcstartbox, dststartbox, lengthbox):
 922        return self.execute(rop.COPYSTRCONTENT, srcbox, dstbox, srcstartbox, dststartbox, lengthbox)
 923
 924    @arguments("box", "box", "box", "box", "box")
 925    def opimpl_copyunicodecontent(self, srcbox, dstbox, srcstartbox, dststartbox, lengthbox):
 926        return self.execute(rop.COPYUNICODECONTENT, srcbox, dstbox, srcstartbox, dststartbox, lengthbox)
 927
 928    @arguments("box", "orgpc")
 929    def _opimpl_guard_value(self, box, orgpc):
 930        self.implement_guard_value(box, orgpc)
 931
 932    @arguments("box", "box", "descr", "orgpc")
 933    def opimpl_str_guard_value(self, box, funcbox, descr, orgpc):
 934        if isinstance(box, Const):
 935            return box     # no promotion needed, already a Const
 936        else:
 937            constbox = box.constbox()
 938            resbox = self.do_residual_call(funcbox, [box, constbox], descr)
 939            promoted_box = resbox.constbox()
 940            # This is GUARD_VALUE because GUARD_TRUE assumes the existance
 941            # of a label when computing resumepc
 942            self.generate_guard(rop.GUARD_VALUE, resbox, [promoted_box],
 943                                resumepc=orgpc)
 944            self.metainterp.replace_box(box, constbox)
 945            return constbox
 946
 947    opimpl_int_guard_value = _opimpl_guard_value
 948    opimpl_ref_guard_value = _opimpl_guard_value
 949    opimpl_float_guard_value = _opimpl_guard_value
 950
 951    @arguments("box", "orgpc")
 952    def opimpl_guard_class(self, box, orgpc):
 953        clsbox = self.cls_of_box(box)
 954        if not self.metainterp.heapcache.is_class_known(box):
 955            self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
 956            self.metainterp.heapcache.class_now_known(box)
 957        return clsbox
 958
 959    @arguments("int", "orgpc")
 960    def opimpl_loop_header(self, jdindex, orgpc):
 961        self.metainterp.seen_loop_header_for_jdindex = jdindex
 962
 963    def verify_green_args(self, jitdriver_sd, varargs):
 964        num_green_args = jitdriver_sd.num_green_args
 965        assert len(varargs) == num_green_args
 966        for i in range(num_green_args):
 967            assert isinstance(varargs[i], Const)
 968
 969    @arguments("int", "boxes3", "jitcode_position", "boxes3", "orgpc")
 970    def opimpl_jit_merge_point(self, jdindex, greenboxes,
 971                               jcposition, redboxes, orgpc):
 972        resumedescr = compile.ResumeAtPositionDescr()
 973        self.capture_resumedata(resumedescr, orgpc)
 974
 975        any_operation = len(self.metainterp.history.operations) > 0
 976        jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
 977        self.verify_green_args(jitdriver_sd, greenboxes)
 978        self.debug_merge_point(jitdriver_sd, jdindex,
 979                               self.metainterp.portal_call_depth,
 980                               self.metainterp.call_ids[-1],
 981                               greenboxes)
 982
 983        if self.metainterp.seen_loop_header_for_jdindex < 0:
 984            if not any_operation:
 985                return
 986            if self.metainterp.portal_call_depth or not self.metainterp.get_procedure_token(greenboxes, True):
 987                if not jitdriver_sd.no_loop_header:
 988                    return
 989            # automatically add a loop_header if there is none
 990            self.metainterp.seen_loop_header_for_jdindex = jdindex
 991        #
 992        assert self.metainterp.seen_loop_header_for_jdindex == jdindex, (
 993            "found a loop_header for a JitDriver that does not match "
 994            "the following jit_merge_point's")
 995        self.metainterp.seen_loop_header_for_jdindex = -1
 996
 997        #
 998        if not self.metainterp.portal_call_depth:
 999            assert jitdriver_sd is self.metainterp.jitdriver_sd
1000            # Set self.pc to point to jit_merge_point instead of just after:
1001            # if reached_loop_header() raises SwitchToBlackhole, then the
1002            # pc is still at the jit_merge_point, which is a point that is
1003            # much less expensive to blackhole out of.
1004            saved_pc = self.pc
1005            self.pc = orgpc
1006            self.metainterp.reached_loop_header(greenboxes, redboxes, resumedescr)
1007            self.pc = saved_pc
1008            # no exception, which means that the jit_merge_point did not
1009            # close the loop.  We have to put the possibly-modified list
1010            # 'redboxes' back into the registers where it comes from.
1011            put_back_list_of_boxes3(self, jcposition, redboxes)
1012        else:
1013            if jitdriver_sd.warmstate.should_unroll_one_iteration(greenboxes):
1014                if self.unroll_iterations > 0:
1015                    self.unroll_iterations -= 1
1016                    return
1017            # warning! careful here.  We have to return from the current
1018            # frame containing the jit_merge_point, and then use
1019            # do_recursive_call() to follow the recursive call.  This is
1020            # needed because do_recursive_call() will write its result
1021            # with make_result_of_lastop(), so the lastop must be right:
1022            # it must be the call to 'self', and not the jit_merge_point
1023            # itself, which has no result at all.
1024            assert len(self.metainterp.framestack) >= 2
1025            try:
1026                self.metainterp.finishframe(None)
1027            except ChangeFrame:
1028                pass
1029            frame = self.metainterp.framestack[-1]
1030            frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes,
1031                                    assembler_call=True)
1032            raise ChangeFrame
1033
1034    def debug_merge_point(self, jitdriver_sd, jd_index, portal_call_depth, current_call_id, greenkey):
1035        # debugging: produce a DEBUG_MERGE_POINT operation
1036        loc = jitdriver_sd.warmstate.get_location_str(greenkey)
1037        debug_print(loc)
1038        args = [ConstInt(jd_index), ConstInt(portal_call_depth), ConstInt(current_call_id)] + greenkey
1039        self.metainterp.history.record(rop.DEBUG_MERGE_POINT, args, None)
1040
1041    @arguments("box", "label")
1042    def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target):
1043        metainterp = self.metainterp
1044        last_exc_value_box = metainterp.last_exc_value_box
1045        assert last_exc_value_box is not None
1046        assert metainterp.class_of_last_exc_is_const
1047        if not metainterp.cpu.ts.instanceOf(last_exc_value_box, vtablebox):
1048            self.pc = next_exc_target
1049
1050    @arguments("box", "orgpc")
1051    def opimpl_raise(self, exc_value_box, orgpc):
1052        # xxx hack
1053        clsbox = self.cls_of_box(exc_value_box)
1054        self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox],
1055                            resumepc=orgpc)
1056        self.metainterp.class_of_last_exc_is_const = True
1057        self.metainterp.last_exc_value_box = exc_value_box
1058        self.metainterp.popframe()
1059        self.metainterp.finishframe_exception()
1060
1061    @arguments()
1062    def opimpl_reraise(self):
1063        assert self.metainterp.last_exc_value_box is not None
1064        self.metainterp.popframe()
1065        self.metainterp.finishframe_exception()
1066
1067    @arguments()
1068    def opimpl_last_exception(self):
1069        # Same comment as in opimpl_goto_if_exception_mismatch().
1070        exc_value_box = self.metainterp.last_exc_value_box
1071        assert exc_value_box is not None
1072        assert self.metainterp.class_of_last_exc_is_const
1073        return self.metainterp.cpu.ts.cls_of_box(exc_value_box)
1074
1075    @arguments()
1076    def opimpl_last_exc_value(self):
1077        exc_value_box = self.metainterp.last_exc_value_box
1078        assert exc_value_box is not None
1079        return exc_value_box
1080
1081    @arguments("box")
1082    def opimpl_debug_fatalerror(self, box):
1083        from rpython.rtyper.lltypesystem import rstr, lloperation
1084        msg = box.getref(lltype.Ptr(rstr.STR))
1085        lloperation.llop.debug_fatalerror(lltype.Void, msg)
1086
1087    @arguments("box", "box", "box", "box", "box")
1088    def opimpl_jit_debug(self, stringbox, arg1box, arg2box, arg3box, arg4box):
1089        from rpython.rtyper.lltypesystem import rstr
1090        from rpython.rtyper.annlowlevel import hlstr
1091        msg = stringbox.getref(lltype.Ptr(rstr.STR

Large files files are truncated, but you can click here to view the full file