PageRenderTime 188ms CodeModel.GetById 101ms app.highlight 66ms RepoModel.GetById 11ms app.codeStats 0ms

/pypy/jit/metainterp/resume.py

http://github.com/pypy/pypy
Python | 1316 lines | 1026 code | 184 blank | 106 comment | 189 complexity | 4a4f50fad1fed7ca24bf14832a779e15 MD5 | raw file

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

   1import sys, os
   2from pypy.jit.metainterp.history import Box, Const, ConstInt, getkind
   3from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat
   4from pypy.jit.metainterp.history import INT, REF, FLOAT, HOLE
   5from pypy.jit.metainterp.history import AbstractDescr
   6from pypy.jit.metainterp.resoperation import rop
   7from pypy.jit.metainterp import jitprof
   8from pypy.jit.codewriter.effectinfo import EffectInfo
   9from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rstr
  10from pypy.rpython import annlowlevel
  11from pypy.rlib import rarithmetic, rstack
  12from pypy.rlib.objectmodel import we_are_translated, specialize
  13from pypy.rlib.debug import have_debug_prints, ll_assert
  14from pypy.rlib.debug import debug_start, debug_stop, debug_print
  15from pypy.jit.metainterp.optimize import InvalidLoop
  16
  17# Logic to encode the chain of frames and the state of the boxes at a
  18# guard operation, and to decode it again.  This is a bit advanced,
  19# because it needs to support optimize.py which encodes virtuals with
  20# arbitrary cycles and also to compress the information
  21
  22class Snapshot(object):
  23    __slots__ = ('prev', 'boxes')
  24
  25    def __init__(self, prev, boxes):
  26        self.prev = prev
  27        self.boxes = boxes
  28
  29class FrameInfo(object):
  30    __slots__ = ('prev', 'jitcode', 'pc')
  31
  32    def __init__(self, prev, jitcode, pc):
  33        self.prev = prev
  34        self.jitcode = jitcode
  35        self.pc = pc
  36
  37def _ensure_parent_resumedata(framestack, n):
  38    target = framestack[n]
  39    if n == 0:
  40        return
  41    back = framestack[n-1]
  42    if target.parent_resumedata_frame_info_list is not None:
  43        assert target.parent_resumedata_frame_info_list.pc == back.pc
  44        return
  45    _ensure_parent_resumedata(framestack, n-1)
  46    target.parent_resumedata_frame_info_list = FrameInfo(
  47                                         back.parent_resumedata_frame_info_list,
  48                                         back.jitcode,
  49                                         back.pc)
  50    target.parent_resumedata_snapshot = Snapshot(
  51                                         back.parent_resumedata_snapshot,
  52                                         back.get_list_of_active_boxes(True))
  53
  54def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes,
  55                       storage):
  56    n = len(framestack)-1
  57    top = framestack[n]
  58    _ensure_parent_resumedata(framestack, n)
  59    frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list,
  60                                top.jitcode, top.pc)
  61    storage.rd_frame_info_list = frame_info_list
  62    snapshot = Snapshot(top.parent_resumedata_snapshot,
  63                        top.get_list_of_active_boxes(False))
  64    if virtualizable_boxes is not None:
  65        boxes = virtualref_boxes + virtualizable_boxes
  66    else:
  67        boxes = virtualref_boxes[:]
  68    snapshot = Snapshot(snapshot, boxes)
  69    storage.rd_snapshot = snapshot
  70
  71#
  72# The following is equivalent to the RPython-level declaration:
  73#
  74#     class Numbering: __slots__ = ['prev', 'nums']
  75#
  76# except that it is more compact in translated programs, because the
  77# array 'nums' is inlined in the single NUMBERING object.  This is
  78# important because this is often the biggest single consumer of memory
  79# in a pypy-c-jit.
  80#
  81NUMBERINGP = lltype.Ptr(lltype.GcForwardReference())
  82NUMBERING = lltype.GcStruct('Numbering',
  83                            ('prev', NUMBERINGP),
  84                            ('nums', lltype.Array(rffi.SHORT)))
  85NUMBERINGP.TO.become(NUMBERING)
  86
  87PENDINGFIELDSTRUCT = lltype.Struct('PendingField',
  88                                   ('lldescr', annlowlevel.base_ptr_lltype()),
  89                                   ('num', rffi.SHORT),
  90                                   ('fieldnum', rffi.SHORT),
  91                                   ('itemindex', rffi.INT))
  92PENDINGFIELDSP = lltype.Ptr(lltype.GcArray(PENDINGFIELDSTRUCT))
  93
  94TAGMASK = 3
  95
  96class TagOverflow(Exception):
  97    pass
  98
  99def tag(value, tagbits):
 100    assert 0 <= tagbits <= 3
 101    sx = value >> 13
 102    if sx != 0 and sx != -1:
 103        raise TagOverflow
 104    return rffi.r_short(value<<2|tagbits)
 105
 106def untag(value):
 107    value = rarithmetic.widen(value)
 108    tagbits = value&TAGMASK
 109    return value>>2, tagbits
 110
 111def tagged_eq(x, y):
 112    # please rpython :(
 113    return rarithmetic.widen(x) == rarithmetic.widen(y)
 114
 115def tagged_list_eq(tl1, tl2):
 116    if len(tl1) != len(tl2):
 117        return False
 118    for i in range(len(tl1)):
 119        if not tagged_eq(tl1[i], tl2[i]):
 120            return False
 121    return True
 122
 123TAGCONST    = 0
 124TAGINT      = 1
 125TAGBOX      = 2
 126TAGVIRTUAL  = 3
 127
 128UNASSIGNED = tag(-1<<13, TAGBOX)
 129UNASSIGNEDVIRTUAL = tag(-1<<13, TAGVIRTUAL)
 130NULLREF = tag(-1, TAGCONST)
 131UNINITIALIZED = tag(-2, TAGCONST)   # used for uninitialized string characters
 132
 133
 134class ResumeDataLoopMemo(object):
 135
 136    def __init__(self, metainterp_sd):
 137        self.metainterp_sd = metainterp_sd
 138        self.cpu = metainterp_sd.cpu
 139        self.consts = []
 140        self.large_ints = {}
 141        self.refs = self.cpu.ts.new_ref_dict_2()
 142        self.numberings = {}
 143        self.cached_boxes = {}
 144        self.cached_virtuals = {}
 145
 146        self.nvirtuals = 0
 147        self.nvholes = 0
 148        self.nvreused = 0
 149
 150    def getconst(self, const):
 151        if const.type == INT:
 152            val = const.getint()
 153            if not we_are_translated() and not isinstance(val, int):
 154                # unhappiness, probably a symbolic
 155                return self._newconst(const)
 156            try:
 157                return tag(val, TAGINT)
 158            except TagOverflow:
 159                pass
 160            tagged = self.large_ints.get(val, UNASSIGNED)
 161            if not tagged_eq(tagged, UNASSIGNED):
 162                return tagged
 163            tagged = self._newconst(const)
 164            self.large_ints[val] = tagged
 165            return tagged
 166        elif const.type == REF:
 167            val = const.getref_base()
 168            if not val:
 169                return NULLREF
 170            tagged = self.refs.get(val, UNASSIGNED)
 171            if not tagged_eq(tagged, UNASSIGNED):
 172                return tagged
 173            tagged = self._newconst(const)
 174            self.refs[val] = tagged
 175            return tagged
 176        return self._newconst(const)
 177
 178    def _newconst(self, const):
 179        result = tag(len(self.consts), TAGCONST)
 180        self.consts.append(const)
 181        return result
 182
 183    # env numbering
 184
 185    def number(self, optimizer, snapshot):
 186        if snapshot is None:
 187            return lltype.nullptr(NUMBERING), {}, 0
 188        if snapshot in self.numberings:
 189             numb, liveboxes, v = self.numberings[snapshot]
 190             return numb, liveboxes.copy(), v
 191
 192        numb1, liveboxes, v = self.number(optimizer, snapshot.prev)
 193        n = len(liveboxes)-v
 194        boxes = snapshot.boxes
 195        length = len(boxes)
 196        numb = lltype.malloc(NUMBERING, length)
 197        for i in range(length):
 198            box = boxes[i]
 199            value = optimizer.getvalue(box)
 200            box = value.get_key_box()
 201
 202            if isinstance(box, Const):
 203                tagged = self.getconst(box)
 204            elif box in liveboxes:
 205                tagged = liveboxes[box]
 206            else:
 207                if value is not None and value.is_virtual():
 208                    tagged = tag(v, TAGVIRTUAL)
 209                    v += 1
 210                else:
 211                    tagged = tag(n, TAGBOX)
 212                    n += 1
 213                liveboxes[box] = tagged
 214            numb.nums[i] = tagged
 215        #
 216        numb.prev = numb1
 217        self.numberings[snapshot] = numb, liveboxes, v
 218        return numb, liveboxes.copy(), v
 219
 220    def forget_numberings(self, virtualbox):
 221        # XXX ideally clear only the affected numberings
 222        self.numberings.clear()
 223        self.clear_box_virtual_numbers()
 224
 225    # caching for virtuals and boxes inside them
 226
 227    def num_cached_boxes(self):
 228        return len(self.cached_boxes)
 229
 230    def assign_number_to_box(self, box, boxes):
 231        # returns a negative number
 232        if box in self.cached_boxes:
 233            num = self.cached_boxes[box]
 234            boxes[-num-1] = box
 235        else:
 236            boxes.append(box)
 237            num = -len(boxes)
 238            self.cached_boxes[box] = num
 239        return num
 240
 241    def num_cached_virtuals(self):
 242        return len(self.cached_virtuals)
 243
 244    def assign_number_to_virtual(self, box):
 245        # returns a negative number
 246        if box in self.cached_virtuals:
 247            num = self.cached_virtuals[box]
 248        else:
 249            num = self.cached_virtuals[box] = -len(self.cached_virtuals) - 1
 250        return num
 251
 252    def clear_box_virtual_numbers(self):
 253        self.cached_boxes.clear()
 254        self.cached_virtuals.clear()
 255
 256    def update_counters(self, profiler):
 257        profiler.count(jitprof.NVIRTUALS, self.nvirtuals)
 258        profiler.count(jitprof.NVHOLES, self.nvholes)
 259        profiler.count(jitprof.NVREUSED, self.nvreused)
 260
 261_frame_info_placeholder = (None, 0, 0)
 262
 263class ResumeDataVirtualAdder(object):
 264
 265    def __init__(self, storage, memo):
 266        self.storage = storage
 267        self.memo = memo
 268
 269    def make_virtual(self, known_class, fielddescrs):
 270        return VirtualInfo(known_class, fielddescrs)
 271
 272    def make_vstruct(self, typedescr, fielddescrs):
 273        return VStructInfo(typedescr, fielddescrs)
 274
 275    def make_varray(self, arraydescr):
 276        return VArrayInfo(arraydescr)
 277
 278    def make_varraystruct(self, arraydescr, fielddescrs):
 279        return VArrayStructInfo(arraydescr, fielddescrs)
 280
 281    def make_vstrplain(self, is_unicode=False):
 282        if is_unicode:
 283            return VUniPlainInfo()
 284        return VStrPlainInfo()
 285
 286    def make_vstrconcat(self, is_unicode=False):
 287        if is_unicode:
 288            return VUniConcatInfo()
 289        return VStrConcatInfo()
 290
 291    def make_vstrslice(self, is_unicode=False):
 292        if is_unicode:
 293            return VUniSliceInfo()
 294        return VStrSliceInfo()
 295
 296    def register_virtual_fields(self, virtualbox, fieldboxes):
 297        tagged = self.liveboxes_from_env.get(virtualbox, UNASSIGNEDVIRTUAL)
 298        self.liveboxes[virtualbox] = tagged
 299        self.vfieldboxes[virtualbox] = fieldboxes
 300        self._register_boxes(fieldboxes)
 301
 302    def register_box(self, box):
 303        if (isinstance(box, Box) and box not in self.liveboxes_from_env
 304                                 and box not in self.liveboxes):
 305            self.liveboxes[box] = UNASSIGNED
 306
 307    def _register_boxes(self, boxes):
 308        for box in boxes:
 309            self.register_box(box)
 310
 311    def already_seen_virtual(self, virtualbox):
 312        if virtualbox not in self.liveboxes:
 313            assert virtualbox in self.liveboxes_from_env
 314            assert untag(self.liveboxes_from_env[virtualbox])[1] == TAGVIRTUAL
 315            return False
 316        tagged = self.liveboxes[virtualbox]
 317        _, tagbits = untag(tagged)
 318        return tagbits == TAGVIRTUAL
 319
 320    def finish(self, optimizer, pending_setfields=[]):
 321        # compute the numbering
 322        storage = self.storage
 323        # make sure that nobody attached resume data to this guard yet
 324        assert not storage.rd_numb
 325        snapshot = storage.rd_snapshot
 326        assert snapshot is not None # is that true?
 327        numb, liveboxes_from_env, v = self.memo.number(optimizer, snapshot)
 328        self.liveboxes_from_env = liveboxes_from_env
 329        self.liveboxes = {}
 330        storage.rd_numb = numb
 331        storage.rd_snapshot = None
 332
 333        # collect liveboxes and virtuals
 334        n = len(liveboxes_from_env) - v
 335        liveboxes = [None]*n
 336        self.vfieldboxes = {}
 337        for box, tagged in liveboxes_from_env.iteritems():
 338            i, tagbits = untag(tagged)
 339            if tagbits == TAGBOX:
 340                liveboxes[i] = box
 341            else:
 342                assert tagbits == TAGVIRTUAL
 343                value = optimizer.getvalue(box)
 344                value.get_args_for_fail(self)
 345
 346        for _, box, fieldbox, _ in pending_setfields:
 347            self.register_box(box)
 348            self.register_box(fieldbox)
 349            value = optimizer.getvalue(fieldbox)
 350            value.get_args_for_fail(self)
 351
 352        self._number_virtuals(liveboxes, optimizer, v)
 353        self._add_pending_fields(pending_setfields)
 354
 355        storage.rd_consts = self.memo.consts
 356        dump_storage(storage, liveboxes)
 357        return liveboxes[:]
 358
 359    def _number_virtuals(self, liveboxes, optimizer, num_env_virtuals):
 360        # !! 'liveboxes' is a list that is extend()ed in-place !!
 361        memo = self.memo
 362        new_liveboxes = [None] * memo.num_cached_boxes()
 363        count = 0
 364        # So far, self.liveboxes should contain 'tagged' values that are
 365        # either UNASSIGNED, UNASSIGNEDVIRTUAL, or a *non-negative* value
 366        # with the TAGVIRTUAL.  The following loop removes the UNASSIGNED
 367        # and UNASSIGNEDVIRTUAL entries, and replaces them with real
 368        # negative values.
 369        for box, tagged in self.liveboxes.iteritems():
 370            i, tagbits = untag(tagged)
 371            if tagbits == TAGBOX:
 372                assert box not in self.liveboxes_from_env
 373                assert tagged_eq(tagged, UNASSIGNED)
 374                index = memo.assign_number_to_box(box, new_liveboxes)
 375                self.liveboxes[box] = tag(index, TAGBOX)
 376                count += 1
 377            else:
 378                assert tagbits == TAGVIRTUAL
 379                if tagged_eq(tagged, UNASSIGNEDVIRTUAL):
 380                    assert box not in self.liveboxes_from_env
 381                    index = memo.assign_number_to_virtual(box)
 382                    self.liveboxes[box] = tag(index, TAGVIRTUAL)
 383                else:
 384                    assert i >= 0
 385        new_liveboxes.reverse()
 386        liveboxes.extend(new_liveboxes)
 387        nholes = len(new_liveboxes) - count
 388
 389        storage = self.storage
 390        storage.rd_virtuals = None
 391        vfieldboxes = self.vfieldboxes
 392        if vfieldboxes:
 393            length = num_env_virtuals + memo.num_cached_virtuals()
 394            virtuals = storage.rd_virtuals = [None] * length
 395            memo.nvirtuals += length
 396            memo.nvholes += length - len(vfieldboxes)
 397            for virtualbox, fieldboxes in vfieldboxes.iteritems():
 398                num, _ = untag(self.liveboxes[virtualbox])
 399                value = optimizer.getvalue(virtualbox)
 400                fieldnums = [self._gettagged(box)
 401                             for box in fieldboxes]
 402                vinfo = value.make_virtual_info(self, fieldnums)
 403                # if a new vinfo instance is made, we get the fieldnums list we
 404                # pass in as an attribute. hackish.
 405                if vinfo.fieldnums is not fieldnums:
 406                    memo.nvreused += 1
 407                virtuals[num] = vinfo
 408
 409        if self._invalidation_needed(len(liveboxes), nholes):
 410            memo.clear_box_virtual_numbers()
 411
 412    def _invalidation_needed(self, nliveboxes, nholes):
 413        memo = self.memo
 414        # xxx heuristic a bit out of thin air
 415        failargs_limit = memo.metainterp_sd.options.failargs_limit
 416        if nliveboxes > (failargs_limit // 2):
 417            if nholes > nliveboxes//3:
 418                return True
 419        return False
 420
 421    def _add_pending_fields(self, pending_setfields):
 422        rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO)
 423        if pending_setfields:
 424            n = len(pending_setfields)
 425            rd_pendingfields = lltype.malloc(PENDINGFIELDSP.TO, n)
 426            for i in range(n):
 427                descr, box, fieldbox, itemindex = pending_setfields[i]
 428                lldescr = annlowlevel.cast_instance_to_base_ptr(descr)
 429                num = self._gettagged(box)
 430                fieldnum = self._gettagged(fieldbox)
 431                # the index is limited to 2147483647 (64-bit machines only)
 432                if itemindex > 2147483647:
 433                    raise TagOverflow
 434                itemindex = rffi.cast(rffi.INT, itemindex)
 435                #
 436                rd_pendingfields[i].lldescr  = lldescr
 437                rd_pendingfields[i].num      = num
 438                rd_pendingfields[i].fieldnum = fieldnum
 439                rd_pendingfields[i].itemindex= itemindex
 440        self.storage.rd_pendingfields = rd_pendingfields
 441
 442    def _gettagged(self, box):
 443        if box is None:
 444            return UNINITIALIZED
 445        if isinstance(box, Const):
 446            return self.memo.getconst(box)
 447        else:
 448            if box in self.liveboxes_from_env:
 449                return self.liveboxes_from_env[box]
 450            return self.liveboxes[box]
 451
 452
 453class AbstractVirtualInfo(object):
 454    #def allocate(self, decoder, index):
 455    #    raise NotImplementedError
 456    def equals(self, fieldnums):
 457        return tagged_list_eq(self.fieldnums, fieldnums)
 458
 459    def set_content(self, fieldnums):
 460        self.fieldnums = fieldnums
 461
 462    def debug_prints(self):
 463        raise NotImplementedError
 464
 465class AbstractVirtualStructInfo(AbstractVirtualInfo):
 466    def __init__(self, fielddescrs):
 467        self.fielddescrs = fielddescrs
 468        #self.fieldnums = ...
 469
 470    @specialize.argtype(1)
 471    def setfields(self, decoder, struct):
 472        for i in range(len(self.fielddescrs)):
 473            descr = self.fielddescrs[i]
 474            decoder.setfield(descr, struct, self.fieldnums[i])
 475        return struct
 476
 477    def debug_prints(self):
 478        assert len(self.fielddescrs) == len(self.fieldnums)
 479        for i in range(len(self.fielddescrs)):
 480            debug_print("\t\t",
 481                        str(self.fielddescrs[i]),
 482                        str(untag(self.fieldnums[i])))
 483
 484class VirtualInfo(AbstractVirtualStructInfo):
 485    def __init__(self, known_class, fielddescrs):
 486        AbstractVirtualStructInfo.__init__(self, fielddescrs)
 487        self.known_class = known_class
 488
 489    @specialize.argtype(1)
 490    def allocate(self, decoder, index):
 491        struct = decoder.allocate_with_vtable(self.known_class)
 492        decoder.virtuals_cache[index] = struct
 493        return self.setfields(decoder, struct)
 494
 495    def debug_prints(self):
 496        debug_print("\tvirtualinfo", self.known_class.repr_rpython())
 497        AbstractVirtualStructInfo.debug_prints(self)
 498
 499
 500class VStructInfo(AbstractVirtualStructInfo):
 501    def __init__(self, typedescr, fielddescrs):
 502        AbstractVirtualStructInfo.__init__(self, fielddescrs)
 503        self.typedescr = typedescr
 504
 505    @specialize.argtype(1)
 506    def allocate(self, decoder, index):
 507        struct = decoder.allocate_struct(self.typedescr)
 508        decoder.virtuals_cache[index] = struct
 509        return self.setfields(decoder, struct)
 510
 511    def debug_prints(self):
 512        debug_print("\tvstructinfo", self.typedescr.repr_rpython())
 513        AbstractVirtualStructInfo.debug_prints(self)
 514
 515class VArrayInfo(AbstractVirtualInfo):
 516    def __init__(self, arraydescr):
 517        self.arraydescr = arraydescr
 518        #self.fieldnums = ...
 519
 520    @specialize.argtype(1)
 521    def allocate(self, decoder, index):
 522        length = len(self.fieldnums)
 523        arraydescr = self.arraydescr
 524        array = decoder.allocate_array(arraydescr, length)
 525        decoder.virtuals_cache[index] = array
 526        # NB. the check for the kind of array elements is moved out of the loop
 527        if arraydescr.is_array_of_pointers():
 528            for i in range(length):
 529                decoder.setarrayitem_ref(arraydescr, array, i,
 530                                         self.fieldnums[i])
 531        elif arraydescr.is_array_of_floats():
 532            for i in range(length):
 533                decoder.setarrayitem_float(arraydescr, array, i,
 534                                           self.fieldnums[i])
 535        else:
 536            for i in range(length):
 537                decoder.setarrayitem_int(arraydescr, array, i,
 538                                         self.fieldnums[i])
 539        return array
 540
 541    def debug_prints(self):
 542        debug_print("\tvarrayinfo", self.arraydescr)
 543        for i in self.fieldnums:
 544            debug_print("\t\t", str(untag(i)))
 545
 546
 547class VArrayStructInfo(AbstractVirtualInfo):
 548    def __init__(self, arraydescr, fielddescrs):
 549        self.arraydescr = arraydescr
 550        self.fielddescrs = fielddescrs
 551
 552    def debug_prints(self):
 553        debug_print("\tvarraystructinfo", self.arraydescr)
 554        for i in self.fieldnums:
 555            debug_print("\t\t", str(untag(i)))
 556
 557    @specialize.argtype(1)
 558    def allocate(self, decoder, index):
 559        array = decoder.allocate_array(self.arraydescr, len(self.fielddescrs))
 560        decoder.virtuals_cache[index] = array
 561        p = 0
 562        for i in range(len(self.fielddescrs)):
 563            for j in range(len(self.fielddescrs[i])):
 564                decoder.setinteriorfield(i, self.fielddescrs[i][j], array, self.fieldnums[p])
 565                p += 1
 566        return array
 567
 568
 569class VStrPlainInfo(AbstractVirtualInfo):
 570    """Stands for the string made out of the characters of all fieldnums."""
 571
 572    @specialize.argtype(1)
 573    def allocate(self, decoder, index):
 574        length = len(self.fieldnums)
 575        string = decoder.allocate_string(length)
 576        decoder.virtuals_cache[index] = string
 577        for i in range(length):
 578            charnum = self.fieldnums[i]
 579            if not tagged_eq(charnum, UNINITIALIZED):
 580                decoder.string_setitem(string, i, charnum)
 581        return string
 582
 583    def debug_prints(self):
 584        debug_print("\tvstrplaininfo length", len(self.fieldnums))
 585
 586
 587class VStrConcatInfo(AbstractVirtualInfo):
 588    """Stands for the string made out of the concatenation of two
 589    other strings."""
 590
 591    @specialize.argtype(1)
 592    def allocate(self, decoder, index):
 593        # xxx for blackhole resuming, this will build all intermediate
 594        # strings and throw them away immediately, which is a bit sub-
 595        # efficient.  Not sure we care.
 596        left, right = self.fieldnums
 597        string = decoder.concat_strings(left, right)
 598        decoder.virtuals_cache[index] = string
 599        return string
 600
 601    def debug_prints(self):
 602        debug_print("\tvstrconcatinfo")
 603        for i in self.fieldnums:
 604            debug_print("\t\t", str(untag(i)))
 605
 606
 607class VStrSliceInfo(AbstractVirtualInfo):
 608    """Stands for the string made out of slicing another string."""
 609
 610    @specialize.argtype(1)
 611    def allocate(self, decoder, index):
 612        largerstr, start, length = self.fieldnums
 613        string = decoder.slice_string(largerstr, start, length)
 614        decoder.virtuals_cache[index] = string
 615        return string
 616
 617    def debug_prints(self):
 618        debug_print("\tvstrsliceinfo")
 619        for i in self.fieldnums:
 620            debug_print("\t\t", str(untag(i)))
 621
 622
 623class VUniPlainInfo(AbstractVirtualInfo):
 624    """Stands for the unicode string made out of the characters of all
 625    fieldnums."""
 626
 627    @specialize.argtype(1)
 628    def allocate(self, decoder, index):
 629        length = len(self.fieldnums)
 630        string = decoder.allocate_unicode(length)
 631        decoder.virtuals_cache[index] = string
 632        for i in range(length):
 633            charnum = self.fieldnums[i]
 634            if not tagged_eq(charnum, UNINITIALIZED):
 635                decoder.unicode_setitem(string, i, charnum)
 636        return string
 637
 638    def debug_prints(self):
 639        debug_print("\tvuniplaininfo length", len(self.fieldnums))
 640
 641
 642class VUniConcatInfo(AbstractVirtualInfo):
 643    """Stands for the unicode string made out of the concatenation of two
 644    other unicode strings."""
 645
 646    @specialize.argtype(1)
 647    def allocate(self, decoder, index):
 648        # xxx for blackhole resuming, this will build all intermediate
 649        # strings and throw them away immediately, which is a bit sub-
 650        # efficient.  Not sure we care.
 651        left, right = self.fieldnums
 652        string = decoder.concat_unicodes(left, right)
 653        decoder.virtuals_cache[index] = string
 654        return string
 655
 656    def debug_prints(self):
 657        debug_print("\tvuniconcatinfo")
 658        for i in self.fieldnums:
 659            debug_print("\t\t", str(untag(i)))
 660
 661
 662class VUniSliceInfo(AbstractVirtualInfo):
 663    """Stands for the unicode string made out of slicing another
 664    unicode string."""
 665
 666    @specialize.argtype(1)
 667    def allocate(self, decoder, index):
 668        largerstr, start, length = self.fieldnums
 669        string = decoder.slice_unicode(largerstr, start, length)
 670        decoder.virtuals_cache[index] = string
 671        return string
 672
 673    def debug_prints(self):
 674        debug_print("\tvunisliceinfo")
 675        for i in self.fieldnums:
 676            debug_print("\t\t", str(untag(i)))
 677
 678# ____________________________________________________________
 679
 680class AbstractResumeDataReader(object):
 681    """A base mixin containing the logic to reconstruct virtuals out of
 682    guard failure.  There are two implementations of this mixin:
 683    ResumeDataBoxReader for when we are compiling (i.e. when we have a
 684    metainterp), and ResumeDataDirectReader for when we are merely
 685    blackholing and want the best performance.
 686    """
 687    _mixin_ = True
 688    rd_virtuals = None
 689    virtuals_cache = None
 690    virtual_default = None
 691
 692    def _init(self, cpu, storage):
 693        self.cpu = cpu
 694        self.cur_numb = storage.rd_numb
 695        self.consts = storage.rd_consts
 696
 697    def _prepare(self, storage):
 698        self._prepare_virtuals(storage.rd_virtuals)
 699        self._prepare_pendingfields(storage.rd_pendingfields)
 700
 701    def getvirtual(self, index):
 702        # Returns the index'th virtual, building it lazily if needed.
 703        # Note that this may be called recursively; that's why the
 704        # allocate() methods must fill in the cache as soon as they
 705        # have the object, before they fill its fields.
 706        assert self.virtuals_cache is not None
 707        v = self.virtuals_cache[index]
 708        if not v:
 709            v = self.rd_virtuals[index].allocate(self, index)
 710            ll_assert(v == self.virtuals_cache[index], "resume.py: bad cache")
 711        return v
 712
 713    def force_all_virtuals(self):
 714        rd_virtuals = self.rd_virtuals
 715        if rd_virtuals:
 716            for i in range(len(rd_virtuals)):
 717                if rd_virtuals[i] is not None:
 718                    self.getvirtual(i)
 719        return self.virtuals_cache
 720
 721    def _prepare_virtuals(self, virtuals):
 722        if virtuals:
 723            self.rd_virtuals = virtuals
 724            self.virtuals_cache = [self.virtual_default] * len(virtuals)
 725
 726    def _prepare_pendingfields(self, pendingfields):
 727        if pendingfields:
 728            for i in range(len(pendingfields)):
 729                lldescr  = pendingfields[i].lldescr
 730                num      = pendingfields[i].num
 731                fieldnum = pendingfields[i].fieldnum
 732                itemindex= pendingfields[i].itemindex
 733                descr = annlowlevel.cast_base_ptr_to_instance(AbstractDescr,
 734                                                              lldescr)
 735                struct = self.decode_ref(num)
 736                itemindex = rffi.cast(lltype.Signed, itemindex)
 737                if itemindex < 0:
 738                    self.setfield(descr, struct, fieldnum)
 739                else:
 740                    self.setarrayitem(descr, struct, itemindex, fieldnum)
 741
 742    def setarrayitem(self, arraydescr, array, index, fieldnum):
 743        if arraydescr.is_array_of_pointers():
 744            self.setarrayitem_ref(arraydescr, array, index, fieldnum)
 745        elif arraydescr.is_array_of_floats():
 746            self.setarrayitem_float(arraydescr, array, index, fieldnum)
 747        else:
 748            self.setarrayitem_int(arraydescr, array, index, fieldnum)
 749
 750    def _prepare_next_section(self, info):
 751        # Use info.enumerate_vars(), normally dispatching to
 752        # pypy.jit.codewriter.jitcode.  Some tests give a different 'info'.
 753        info.enumerate_vars(self._callback_i,
 754                            self._callback_r,
 755                            self._callback_f,
 756                            self.unique_id)    # <-- annotation hack
 757        self.cur_numb = self.cur_numb.prev
 758
 759    def _callback_i(self, index, register_index):
 760        value = self.decode_int(self.cur_numb.nums[index])
 761        self.write_an_int(register_index, value)
 762
 763    def _callback_r(self, index, register_index):
 764        value = self.decode_ref(self.cur_numb.nums[index])
 765        self.write_a_ref(register_index, value)
 766
 767    def _callback_f(self, index, register_index):
 768        value = self.decode_float(self.cur_numb.nums[index])
 769        self.write_a_float(register_index, value)
 770
 771    def done(self):
 772        self.cpu.clear_latest_values(self.cpu.get_latest_value_count())
 773
 774# ---------- when resuming for pyjitpl.py, make boxes ----------
 775
 776def rebuild_from_resumedata(metainterp, storage, virtualizable_info,
 777                            greenfield_info):
 778    resumereader = ResumeDataBoxReader(storage, metainterp)
 779    boxes = resumereader.consume_vref_and_vable_boxes(virtualizable_info,
 780                                                      greenfield_info)
 781    virtualizable_boxes, virtualref_boxes = boxes
 782    frameinfo = storage.rd_frame_info_list
 783    while True:
 784        f = metainterp.newframe(frameinfo.jitcode)
 785        f.setup_resume_at_op(frameinfo.pc)
 786        resumereader.consume_boxes(f.get_current_position_info(),
 787                                   f.registers_i, f.registers_r, f.registers_f)
 788        frameinfo = frameinfo.prev
 789        if frameinfo is None:
 790            break
 791    metainterp.framestack.reverse()
 792    resumereader.done()
 793    return resumereader.liveboxes, virtualizable_boxes, virtualref_boxes
 794
 795class ResumeDataBoxReader(AbstractResumeDataReader):
 796    unique_id = lambda: None
 797
 798    def __init__(self, storage, metainterp):
 799        self._init(metainterp.cpu, storage)
 800        self.metainterp = metainterp
 801        self.liveboxes = [None] * metainterp.cpu.get_latest_value_count()
 802        self._prepare(storage)
 803
 804    def consume_boxes(self, info, boxes_i, boxes_r, boxes_f):
 805        self.boxes_i = boxes_i
 806        self.boxes_r = boxes_r
 807        self.boxes_f = boxes_f
 808        self._prepare_next_section(info)
 809
 810    def consume_virtualizable_boxes(self, vinfo, numb):
 811        # we have to ignore the initial part of 'nums' (containing vrefs),
 812        # find the virtualizable from nums[-1], and use it to know how many
 813        # boxes of which type we have to return.  This does not write
 814        # anything into the virtualizable.
 815        index = len(numb.nums) - 1
 816        virtualizablebox = self.decode_ref(numb.nums[index])
 817        virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox)
 818        return vinfo.load_list_of_boxes(virtualizable, self, numb)
 819
 820    def consume_virtualref_boxes(self, numb, end):
 821        # Returns a list of boxes, assumed to be all BoxPtrs.
 822        # We leave up to the caller to call vrefinfo.continue_tracing().
 823        assert (end & 1) == 0
 824        return [self.decode_ref(numb.nums[i]) for i in range(end)]
 825
 826    def consume_vref_and_vable_boxes(self, vinfo, ginfo):
 827        numb = self.cur_numb
 828        self.cur_numb = numb.prev
 829        if vinfo is not None:
 830            virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, numb)
 831            end = len(numb.nums) - len(virtualizable_boxes)
 832        elif ginfo is not None:
 833            index = len(numb.nums) - 1
 834            virtualizable_boxes = [self.decode_ref(numb.nums[index])]
 835            end = len(numb.nums) - 1
 836        else:
 837            virtualizable_boxes = None
 838            end = len(numb.nums)
 839        virtualref_boxes = self.consume_virtualref_boxes(numb, end)
 840        return virtualizable_boxes, virtualref_boxes
 841
 842    def allocate_with_vtable(self, known_class):
 843        return self.metainterp.execute_and_record(rop.NEW_WITH_VTABLE,
 844                                                  None, known_class)
 845
 846    def allocate_struct(self, typedescr):
 847        return self.metainterp.execute_and_record(rop.NEW, typedescr)
 848
 849    def allocate_array(self, arraydescr, length):
 850        return self.metainterp.execute_and_record(rop.NEW_ARRAY,
 851                                                  arraydescr, ConstInt(length))
 852
 853    def allocate_string(self, length):
 854        return self.metainterp.execute_and_record(rop.NEWSTR,
 855                                                  None, ConstInt(length))
 856
 857    def string_setitem(self, strbox, index, charnum):
 858        charbox = self.decode_box(charnum, INT)
 859        self.metainterp.execute_and_record(rop.STRSETITEM, None,
 860                                           strbox, ConstInt(index), charbox)
 861
 862    def concat_strings(self, str1num, str2num):
 863        cic = self.metainterp.staticdata.callinfocollection
 864        calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_STR_CONCAT)
 865        str1box = self.decode_box(str1num, REF)
 866        str2box = self.decode_box(str2num, REF)
 867        return self.metainterp.execute_and_record_varargs(
 868            rop.CALL, [ConstInt(func), str1box, str2box], calldescr)
 869
 870    def slice_string(self, strnum, startnum, lengthnum):
 871        cic = self.metainterp.staticdata.callinfocollection
 872        calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_STR_SLICE)
 873        strbox = self.decode_box(strnum, REF)
 874        startbox = self.decode_box(startnum, INT)
 875        lengthbox = self.decode_box(lengthnum, INT)
 876        stopbox = self.metainterp.execute_and_record(rop.INT_ADD, None,
 877                                                     startbox, lengthbox)
 878        return self.metainterp.execute_and_record_varargs(
 879            rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
 880
 881    def allocate_unicode(self, length):
 882        return self.metainterp.execute_and_record(rop.NEWUNICODE,
 883                                                  None, ConstInt(length))
 884
 885    def unicode_setitem(self, strbox, index, charnum):
 886        charbox = self.decode_box(charnum, INT)
 887        self.metainterp.execute_and_record(rop.UNICODESETITEM, None,
 888                                           strbox, ConstInt(index), charbox)
 889
 890    def concat_unicodes(self, str1num, str2num):
 891        cic = self.metainterp.staticdata.callinfocollection
 892        calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_UNI_CONCAT)
 893        str1box = self.decode_box(str1num, REF)
 894        str2box = self.decode_box(str2num, REF)
 895        return self.metainterp.execute_and_record_varargs(
 896            rop.CALL, [ConstInt(func), str1box, str2box], calldescr)
 897
 898    def slice_unicode(self, strnum, startnum, lengthnum):
 899        cic = self.metainterp.staticdata.callinfocollection
 900        calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_UNI_SLICE)
 901        strbox = self.decode_box(strnum, REF)
 902        startbox = self.decode_box(startnum, INT)
 903        lengthbox = self.decode_box(lengthnum, INT)
 904        stopbox = self.metainterp.execute_and_record(rop.INT_ADD, None,
 905                                                     startbox, lengthbox)
 906        return self.metainterp.execute_and_record_varargs(
 907            rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
 908
 909    def setfield(self, descr, structbox, fieldnum):
 910        if descr.is_pointer_field():
 911            kind = REF
 912        elif descr.is_float_field():
 913            kind = FLOAT
 914        else:
 915            kind = INT
 916        fieldbox = self.decode_box(fieldnum, kind)
 917        self.metainterp.execute_and_record(rop.SETFIELD_GC, descr,
 918                                           structbox, fieldbox)
 919
 920    def setinteriorfield(self, index, descr, array, fieldnum):
 921        if descr.is_pointer_field():
 922            kind = REF
 923        elif descr.is_float_field():
 924            kind = FLOAT
 925        else:
 926            kind = INT
 927        fieldbox = self.decode_box(fieldnum, kind)
 928        self.metainterp.execute_and_record(rop.SETINTERIORFIELD_GC, descr,
 929                                           array, ConstInt(index), fieldbox)
 930
 931    def setarrayitem_int(self, arraydescr, arraybox, index, fieldnum):
 932        self._setarrayitem(arraydescr, arraybox, index, fieldnum, INT)
 933
 934    def setarrayitem_ref(self, arraydescr, arraybox, index, fieldnum):
 935        self._setarrayitem(arraydescr, arraybox, index, fieldnum, REF)
 936
 937    def setarrayitem_float(self, arraydescr, arraybox, index, fieldnum):
 938        self._setarrayitem(arraydescr, arraybox, index, fieldnum, FLOAT)
 939
 940    def _setarrayitem(self, arraydescr, arraybox, index, fieldnum, kind):
 941        itembox = self.decode_box(fieldnum, kind)
 942        self.metainterp.execute_and_record(rop.SETARRAYITEM_GC,
 943                                           arraydescr, arraybox,
 944                                           ConstInt(index), itembox)
 945
 946    def decode_int(self, tagged):
 947        return self.decode_box(tagged, INT)
 948    def decode_ref(self, tagged):
 949        return self.decode_box(tagged, REF)
 950    def decode_float(self, tagged):
 951        return self.decode_box(tagged, FLOAT)
 952
 953    def decode_box(self, tagged, kind):
 954        num, tag = untag(tagged)
 955        if tag == TAGCONST:
 956            if tagged_eq(tagged, NULLREF):
 957                box = self.cpu.ts.CONST_NULL
 958            else:
 959                box = self.consts[num]
 960        elif tag == TAGVIRTUAL:
 961            box = self.getvirtual(num)
 962        elif tag == TAGINT:
 963            box = ConstInt(num)
 964        else:
 965            assert tag == TAGBOX
 966            box = self.liveboxes[num]
 967            if box is None:
 968                box = self.load_box_from_cpu(num, kind)
 969        assert box.type == kind
 970        return box
 971
 972    def load_box_from_cpu(self, num, kind):
 973        if num < 0:
 974            num += len(self.liveboxes)
 975            assert num >= 0
 976        if kind == INT:
 977            box = BoxInt(self.cpu.get_latest_value_int(num))
 978        elif kind == REF:
 979            box = BoxPtr(self.cpu.get_latest_value_ref(num))
 980        elif kind == FLOAT:
 981            box = BoxFloat(self.cpu.get_latest_value_float(num))
 982        else:
 983            assert 0, "bad kind: %d" % ord(kind)
 984        self.liveboxes[num] = box
 985        return box
 986
 987    def decode_box_of_type(self, TYPE, tagged):
 988        kind = getkind(TYPE)
 989        if kind == 'int':     kind = INT
 990        elif kind == 'ref':   kind = REF
 991        elif kind == 'float': kind = FLOAT
 992        else: raise AssertionError(kind)
 993        return self.decode_box(tagged, kind)
 994    decode_box_of_type._annspecialcase_ = 'specialize:arg(1)'
 995
 996    def write_an_int(self, index, box):
 997        self.boxes_i[index] = box
 998    def write_a_ref(self, index, box):
 999        self.boxes_r[index] = box
1000    def write_a_float(self, index, box):
1001        self.boxes_f[index] = box
1002
1003# ---------- when resuming for blackholing, get direct values ----------
1004
1005def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage,
1006                              all_virtuals=None):
1007    # The initialization is stack-critical code: it must not be interrupted by
1008    # StackOverflow, otherwise the jit_virtual_refs are left in a dangling state.
1009    rstack._stack_criticalcode_start()
1010    try:
1011        resumereader = ResumeDataDirectReader(blackholeinterpbuilder.metainterp_sd,
1012                                              storage, all_virtuals)
1013        vinfo = jitdriver_sd.virtualizable_info
1014        ginfo = jitdriver_sd.greenfield_info
1015        vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info
1016        resumereader.consume_vref_and_vable(vrefinfo, vinfo, ginfo)
1017    finally:
1018        rstack._stack_criticalcode_stop()
1019    #
1020    # First get a chain of blackhole interpreters whose length is given
1021    # by the depth of rd_frame_info_list.  The first one we get must be
1022    # the bottom one, i.e. the last one in the chain, in order to make
1023    # the comment in BlackholeInterpreter.setposition() valid.
1024    nextbh = None
1025    frameinfo = storage.rd_frame_info_list
1026    while True:
1027        curbh = blackholeinterpbuilder.acquire_interp()
1028        curbh.nextblackholeinterp = nextbh
1029        nextbh = curbh
1030        frameinfo = frameinfo.prev
1031        if frameinfo is None:
1032            break
1033    firstbh = nextbh
1034    #
1035    # Now fill the blackhole interpreters with resume data.
1036    curbh = firstbh
1037    frameinfo = storage.rd_frame_info_list
1038    while True:
1039        curbh.setposition(frameinfo.jitcode, frameinfo.pc)
1040        resumereader.consume_one_section(curbh)
1041        curbh = curbh.nextblackholeinterp
1042        frameinfo = frameinfo.prev
1043        if frameinfo is None:
1044            break
1045    resumereader.done()
1046    return firstbh
1047
1048def force_from_resumedata(metainterp_sd, storage, vinfo, ginfo):
1049    resumereader = ResumeDataDirectReader(metainterp_sd, storage)
1050    resumereader.handling_async_forcing()
1051    vrefinfo = metainterp_sd.virtualref_info
1052    resumereader.consume_vref_and_vable(vrefinfo, vinfo, ginfo)
1053    return resumereader.force_all_virtuals()
1054
1055class ResumeDataDirectReader(AbstractResumeDataReader):
1056    unique_id = lambda: None
1057    virtual_default = lltype.nullptr(llmemory.GCREF.TO)
1058    resume_after_guard_not_forced = 0
1059    #             0: not a GUARD_NOT_FORCED
1060    #             1: in handle_async_forcing
1061    #             2: resuming from the GUARD_NOT_FORCED
1062
1063    def __init__(self, metainterp_sd, storage, all_virtuals=None):
1064        self._init(metainterp_sd.cpu, storage)
1065        self.callinfocollection = metainterp_sd.callinfocollection
1066        if all_virtuals is None:        # common case
1067            self._prepare(storage)
1068        else:
1069            # special case for resuming after a GUARD_NOT_FORCED: we already
1070            # have the virtuals
1071            self.resume_after_guard_not_forced = 2
1072            self.virtuals_cache = all_virtuals
1073            # self.rd_virtuals can remain None, because virtuals_cache is
1074            # already filled
1075
1076    def handling_async_forcing(self):
1077        self.resume_after_guard_not_forced = 1
1078
1079    def consume_one_section(self, blackholeinterp):
1080        self.blackholeinterp = blackholeinterp
1081        info = blackholeinterp.get_current_position_info()
1082        self._prepare_next_section(info)
1083
1084    def consume_virtualref_info(self, vrefinfo, numb, end):
1085        # we have to decode a list of references containing pairs
1086        # [..., virtual, vref, ...]  stopping at 'end'
1087        assert (end & 1) == 0
1088        for i in range(0, end, 2):
1089            virtual = self.decode_ref(numb.nums[i])
1090            vref = self.decode_ref(numb.nums[i+1])
1091            # For each pair, we store the virtual inside the vref.
1092            vrefinfo.continue_tracing(vref, virtual)
1093
1094    def consume_vable_info(self, vinfo, numb):
1095        # we have to ignore the initial part of 'nums' (containing vrefs),
1096        # find the virtualizable from nums[-1], load all other values
1097        # from the CPU stack, and copy them into the virtualizable
1098        if vinfo is None:
1099            return len(numb.nums)
1100        index = len(numb.nums) - 1
1101        virtualizable = self.decode_ref(numb.nums[index])
1102        if self.resume_after_guard_not_forced == 1:
1103            # in the middle of handle_async_forcing()
1104            assert vinfo.is_token_nonnull_gcref(virtualizable)
1105            vinfo.reset_token_gcref(virtualizable)
1106        else:
1107            # just jumped away from assembler (case 4 in the comment in
1108            # virtualizable.py) into tracing (case 2); check that vable_token
1109            # is and stays 0.  Note the call to reset_vable_token() in
1110            # warmstate.py.
1111            assert not vinfo.is_token_nonnull_gcref(virtualizable)
1112        return vinfo.write_from_resume_data_partial(virtualizable, self, numb)
1113
1114    def load_value_of_type(self, TYPE, tagged):
1115        from pypy.jit.metainterp.warmstate import specialize_value
1116        kind = getkind(TYPE)
1117        if kind == 'int':
1118            x = self.decode_int(tagged)
1119        elif kind == 'ref':
1120            x = self.decode_ref(tagged)
1121        elif kind == 'float':
1122            x = self.decode_float(tagged)
1123        else:
1124            raise AssertionError(kind)
1125        return specialize_value(TYPE, x)
1126    load_value_of_type._annspecialcase_ = 'specialize:arg(1)'
1127
1128    def consume_vref_and_vable(self, vrefinfo, vinfo, ginfo):
1129        numb = self.cur_numb
1130        self.cur_numb = numb.prev
1131        if self.resume_after_guard_not_forced != 2:
1132            end_vref = self.consume_vable_info(vinfo, numb)
1133            if ginfo is not None: end_vref -= 1
1134            self.consume_virtualref_info(vrefinfo, numb, end_vref)
1135
1136    def allocate_with_vtable(self, known_class):
1137        from pypy.jit.metainterp.executor import exec_new_with_vtable
1138        return exec_new_with_vtable(self.cpu, known_class)
1139
1140    def allocate_struct(self, typedescr):
1141        return self.cpu.bh_new(typedescr)
1142
1143    def allocate_array(self, arraydescr, length):
1144        return self.cpu.bh_new_array(arraydescr, length)
1145
1146    def allocate_string(self, length):
1147        return self.cpu.bh_newstr(length)
1148
1149    def string_setitem(self, str, index, charnum):
1150        char = self.decode_int(charnum)
1151        self.cpu.bh_strsetitem(str, index, char)
1152
1153    def concat_strings(self, str1num, str2num):
1154        str1 = self.decode_ref(str1num)
1155        str2 = self.decode_ref(str2num)
1156        str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str1)
1157        str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str2)
1158        cic = self.callinfocollection
1159        funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_STR_CONCAT)
1160        result = funcptr(str1, str2)
1161        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
1162
1163    def slice_string(self, strnum, startnum, lengthnum):
1164        str = self.decode_ref(strnum)
1165        start = self.decode_int(startnum)
1166        length = self.decode_int(lengthnum)
1167        str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), str)
1168        cic = self.callinfocollection
1169        funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_STR_SLICE)
1170        result = funcptr(str, start, start + length)
1171        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
1172
1173    def allocate_unicode(self, length):
1174        return self.cpu.bh_newunicode(length)
1175
1176    def unicode_setitem(self, str, index, charnum):
1177        char = self.decode_int(charnum)
1178        self.cpu.bh_unicodesetitem(str, index, char)
1179
1180    def concat_unicodes(self, str1num, str2num):
1181        str1 = self.decode_ref(str1num)
1182        str2 = self.decode_ref(str2num)
1183        str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str1)
1184        str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str2)
1185        cic = self.callinfocollection
1186        funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT)
1187        result = funcptr(str1, str2)
1188        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
1189
1190    def slice_unicode(self, strnum, startnum, lengthnum):
1191        str = self.decode_ref(strnum)
1192        start = self.decode_int(startnum)
1193        length = self.decode_int(lengthnum)
1194        str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str)
1195        cic = self.callinfocollection
1196        funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_UNI_SLICE)
1197        result = funcptr(str, start, start + length)
1198        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
1199
1200    def setfield(self, descr, struct, fieldnum):
1201        if descr.is_pointer_field():
1202            newvalue = self.decode_ref(fieldnum)
1203            self.cpu.bh_setfield_gc_r(struct, descr, newvalue)
1204        elif descr.is_float_field():
1205            newvalue = self.decode_float(fieldnum)
1206            self.cpu.bh_setfield_gc_f(struct, descr, newvalue)
1207        else:
1208            newvalue = self.decode_int(fieldnum)
1209            self.cpu.bh_setfield_gc_i(struct, descr, newvalue)
1210
1211    def setinteriorfield(self, index, descr, array, fieldnum):
1212        if descr.is_pointer_field():
1213            newvalue = self.decode_ref(fieldnum)
1214            self.cpu.bh_setinteriorfield_gc_r(array, index, descr, newvalue)
1215        elif descr.is_float_field():
1216            newvalue = self.decode_float(fieldnum)
1217            self.cpu.bh_setinteriorfield_gc_f(array, index, descr, newvalue)
1218        else:
1219            newvalue = self.decode_int(fieldnum)
1220            self.cpu.bh_setinteriorfield_gc_i(array, index, descr, newvalue)
1221
1222    def setarrayitem_int(self, arraydescr, array, index, fieldnum):
1223        newvalue = self.decode_int(fieldnum)
1224        self.cpu.bh_setarrayitem_gc_i(arraydescr, array, index, newvalue)
1225
1226    def setarrayitem_ref(self, arraydescr, array, index, fieldnum):
1227        newvalue = self.decode_ref(fieldnum)
1228        self.cpu.bh_setarrayitem_gc_r(arraydescr, array, index, newvalue)
1229
1230    def setarrayitem_float(self, arraydescr, array, index, fieldnum):
1231        newvalue = self.decode_float(fieldnum)
1232        self.cpu.bh_setarrayitem_gc_f(arraydescr, array, index, newvalue)
1233
1234    def decode_int(self, tagged):
1235        num, tag = untag(tagged)
1236        if tag == TAGCONST:
1237            return self.consts[num].getint()
1238        elif tag == TAGINT:
1239            return num
1240        else:
1241            assert tag == TAGBOX
1242            if num < 0:
1243                num += self.cpu.get_latest_value_count()
1244            return self.cpu.get_latest_value_int(num)
1245
1246    def decode_ref(self, tagged):
1247        num, tag = untag(tagged)
1248        if tag == TAGCONST:
1249            if tagged_eq(tagged, NULLREF):
1250                return self.cpu.ts.NULLREF
1251            return self.consts[num].getref_base()
1252        elif tag == TAGVIRTUAL:
1253            return self.getvirtual(num)
1254        else:
1255            assert tag == TAGBOX
1256            if num < 0:
1257                num += self.cpu.get_latest_value_count()
1258            return self.cpu.get_latest_value_ref(num)
1259
1260    def decode_float(self, tagged):
1261        num, tag = untag(tagged)
1262        if tag == TAGCONST:
1263            return self.consts[num].getfloatstorage()
1264        else:
1265            assert tag == TAGBOX
1266            if num < 0:
1267                num += self.cpu.get_latest_value_count()
1268            return self.cpu.get_latest_value_float(num)
1269
1270    def write_an_int(self, index, int):
1271        self.blackholeinterp.setarg_i(index, int)
1272
1273    def write_a_ref(self, index, ref):
1274        self.blackholeinterp.setarg_r(index, ref)
1275
1276    def write_a_float(self, index, float):
1277        self.blackholeinterp.setarg_f(index, float)
1278
1279# ____________________________________________________________
1280
1281def dump_storage(storage, liveboxes):
1282    "For profiling only."
1283    from pypy.rlib.objectmodel import compute_unique_id
1284    debug_start("jit-resume")
1285    if have_debug_prints():
1286        d

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