/pypy/jit/metainterp/pyjitpl.py
Python | 2768 lines | 2564 code | 94 blank | 110 comment | 86 complexity | 182a7b68d48228744dfa87dd71e2e069 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- import py, sys
- from pypy.rpython.lltypesystem import lltype, rclass
- from pypy.rlib.objectmodel import we_are_translated
- from pypy.rlib.unroll import unrolling_iterable
- from pypy.rlib.debug import debug_start, debug_stop, debug_print
- from pypy.rlib.debug import make_sure_not_resized
- from pypy.rlib import nonconst, rstack
- from pypy.jit.metainterp import history, compile, resume
- from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat
- from pypy.jit.metainterp.history import Box, TargetToken
- from pypy.jit.metainterp.resoperation import rop
- from pypy.jit.metainterp import executor
- from pypy.jit.metainterp.logger import Logger
- from pypy.jit.metainterp.jitprof import EmptyProfiler
- from pypy.rlib.jit import Counters
- from pypy.jit.metainterp.jitexc import JitException, get_llexception
- from pypy.jit.metainterp.heapcache import HeapCache
- from pypy.rlib.objectmodel import specialize
- from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr
- from pypy.jit.codewriter import heaptracker
- from pypy.jit.metainterp.optimizeopt.util import args_dict_box
- # ____________________________________________________________
- def arguments(*args):
- def decorate(func):
- func.argtypes = args
- return func
- return decorate
- # ____________________________________________________________
- class MIFrame(object):
- debug = False
- def __init__(self, metainterp):
- self.metainterp = metainterp
- self.registers_i = [None] * 256
- self.registers_r = [None] * 256
- self.registers_f = [None] * 256
- def setup(self, jitcode, greenkey=None):
- assert isinstance(jitcode, JitCode)
- self.jitcode = jitcode
- self.bytecode = jitcode.code
- # this is not None for frames that are recursive portal calls
- self.greenkey = greenkey
- # copy the constants in place
- self.copy_constants(self.registers_i, jitcode.constants_i, ConstInt)
- self.copy_constants(self.registers_r, jitcode.constants_r, ConstPtr)
- self.copy_constants(self.registers_f, jitcode.constants_f, ConstFloat)
- self._result_argcode = 'v'
- # for resume.py operation
- self.parent_resumedata_snapshot = None
- self.parent_resumedata_frame_info_list = None
- # counter for unrolling inlined loops
- self.unroll_iterations = 1
- @specialize.arg(3)
- def copy_constants(self, registers, constants, ConstClass):
- """Copy jitcode.constants[0] to registers[255],
- jitcode.constants[1] to registers[254],
- jitcode.constants[2] to registers[253], etc."""
- if nonconst.NonConstant(0): # force the right type
- constants[0] = ConstClass.value # (useful for small tests)
- i = len(constants) - 1
- while i >= 0:
- j = 255 - i
- assert j >= 0
- registers[j] = ConstClass(constants[i])
- i -= 1
- def cleanup_registers(self):
- # To avoid keeping references alive, this cleans up the registers_r.
- # It does not clear the references set by copy_constants(), but
- # these are all prebuilt constants anyway.
- for i in range(self.jitcode.num_regs_r()):
- self.registers_r[i] = None
- # ------------------------------
- # Decoding of the JitCode
- @specialize.arg(4)
- def prepare_list_of_boxes(self, outvalue, startindex, position, argcode):
- assert argcode in 'IRF'
- code = self.bytecode
- length = ord(code[position])
- position += 1
- for i in range(length):
- index = ord(code[position+i])
- if argcode == 'I': reg = self.registers_i[index]
- elif argcode == 'R': reg = self.registers_r[index]
- elif argcode == 'F': reg = self.registers_f[index]
- else: raise AssertionError(argcode)
- outvalue[startindex+i] = reg
- def _put_back_list_of_boxes(self, outvalue, startindex, position):
- code = self.bytecode
- length = ord(code[position])
- position += 1
- for i in range(length):
- index = ord(code[position+i])
- box = outvalue[startindex+i]
- if box.type == history.INT: self.registers_i[index] = box
- elif box.type == history.REF: self.registers_r[index] = box
- elif box.type == history.FLOAT: self.registers_f[index] = box
- else: raise AssertionError(box.type)
- def get_current_position_info(self):
- return self.jitcode.get_live_vars_info(self.pc)
- def get_list_of_active_boxes(self, in_a_call):
- if in_a_call:
- # If we are not the topmost frame, self._result_argcode contains
- # the type of the result of the call instruction in the bytecode.
- # We use it to clear the box that will hold the result: this box
- # is not defined yet.
- argcode = self._result_argcode
- index = ord(self.bytecode[self.pc - 1])
- if argcode == 'i': self.registers_i[index] = history.CONST_FALSE
- elif argcode == 'r': self.registers_r[index] = history.CONST_NULL
- elif argcode == 'f': self.registers_f[index] = history.CONST_FZERO
- self._result_argcode = '?' # done
- #
- info = self.get_current_position_info()
- start_i = 0
- start_r = start_i + info.get_register_count_i()
- start_f = start_r + info.get_register_count_r()
- total = start_f + info.get_register_count_f()
- # allocate a list of the correct size
- env = [None] * total
- make_sure_not_resized(env)
- # fill it now
- for i in range(info.get_register_count_i()):
- index = info.get_register_index_i(i)
- env[start_i + i] = self.registers_i[index]
- for i in range(info.get_register_count_r()):
- index = info.get_register_index_r(i)
- env[start_r + i] = self.registers_r[index]
- for i in range(info.get_register_count_f()):
- index = info.get_register_index_f(i)
- env[start_f + i] = self.registers_f[index]
- return env
- def replace_active_box_in_frame(self, oldbox, newbox):
- if isinstance(oldbox, history.BoxInt):
- count = self.jitcode.num_regs_i()
- registers = self.registers_i
- elif isinstance(oldbox, history.BoxPtr):
- count = self.jitcode.num_regs_r()
- registers = self.registers_r
- elif isinstance(oldbox, history.BoxFloat):
- count = self.jitcode.num_regs_f()
- registers = self.registers_f
- else:
- assert 0, oldbox
- for i in range(count):
- if registers[i] is oldbox:
- registers[i] = newbox
- if not we_are_translated():
- for b in registers[count:]:
- assert not oldbox.same_box(b)
- def make_result_of_lastop(self, resultbox):
- got_type = resultbox.type
- # XXX disabled for now, conflicts with str_guard_value
- #if not we_are_translated():
- # typeof = {'i': history.INT,
- # 'r': history.REF,
- # 'f': history.FLOAT}
- # assert typeof[self.jitcode._resulttypes[self.pc]] == got_type
- target_index = ord(self.bytecode[self.pc-1])
- if got_type == history.INT:
- self.registers_i[target_index] = resultbox
- elif got_type == history.REF:
- #debug_print(' ->',
- # llmemory.cast_ptr_to_adr(resultbox.getref_base()))
- self.registers_r[target_index] = resultbox
- elif got_type == history.FLOAT:
- self.registers_f[target_index] = resultbox
- else:
- raise AssertionError("bad result box type")
- # ------------------------------
- for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
- 'int_lt', 'int_le', 'int_eq',
- 'int_ne', 'int_gt', 'int_ge',
- 'int_and', 'int_or', 'int_xor',
- 'int_rshift', 'int_lshift', 'uint_rshift',
- 'uint_lt', 'uint_le', 'uint_gt', 'uint_ge',
- 'uint_floordiv',
- 'float_add', 'float_sub', 'float_mul', 'float_truediv',
- 'float_lt', 'float_le', 'float_eq',
- 'float_ne', 'float_gt', 'float_ge',
- 'ptr_eq', 'ptr_ne', 'instance_ptr_eq', 'instance_ptr_ne',
- ]:
- exec py.code.Source('''
- @arguments("box", "box")
- def opimpl_%s(self, b1, b2):
- return self.execute(rop.%s, b1, b2)
- ''' % (_opimpl, _opimpl.upper())).compile()
- for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']:
- exec py.code.Source('''
- @arguments("box", "box")
- def opimpl_%s(self, b1, b2):
- self.metainterp.clear_exception()
- resbox = self.execute(rop.%s, b1, b2)
- self.make_result_of_lastop(resbox) # same as execute_varargs()
- if not isinstance(resbox, Const):
- self.metainterp.handle_possible_overflow_error()
- return resbox
- ''' % (_opimpl, _opimpl.upper())).compile()
- for _opimpl in ['int_is_true', 'int_is_zero', 'int_neg', 'int_invert',
- 'cast_float_to_int', 'cast_int_to_float',
- 'cast_float_to_singlefloat', 'cast_singlefloat_to_float',
- 'float_neg', 'float_abs',
- 'cast_ptr_to_int', 'cast_int_to_ptr',
- 'convert_float_bytes_to_longlong',
- 'convert_longlong_bytes_to_float', 'int_force_ge_zero',
- ]:
- exec py.code.Source('''
- @arguments("box")
- def opimpl_%s(self, b):
- return self.execute(rop.%s, b)
- ''' % (_opimpl, _opimpl.upper())).compile()
- @arguments("box")
- def opimpl_ptr_nonzero(self, box):
- return self.execute(rop.PTR_NE, box, history.CONST_NULL)
- @arguments("box")
- def opimpl_ptr_iszero(self, box):
- return self.execute(rop.PTR_EQ, box, history.CONST_NULL)
- @arguments("box")
- def opimpl_mark_opaque_ptr(self, box):
- return self.execute(rop.MARK_OPAQUE_PTR, box)
- @arguments("box", "box")
- def opimpl_record_known_class(self, box, clsbox):
- from pypy.rpython.lltypesystem import llmemory
- if self.metainterp.heapcache.is_class_known(box):
- return
- adr = clsbox.getaddr()
- bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE)
- if bounding_class.subclassrange_max - bounding_class.subclassrange_min == 1:
- # precise class knowledge, this can be used
- self.execute(rop.RECORD_KNOWN_CLASS, box, clsbox)
- self.metainterp.heapcache.class_now_known(box)
- @arguments("box")
- def _opimpl_any_return(self, box):
- self.metainterp.finishframe(box)
- opimpl_int_return = _opimpl_any_return
- opimpl_ref_return = _opimpl_any_return
- opimpl_float_return = _opimpl_any_return
- @arguments()
- def opimpl_void_return(self):
- self.metainterp.finishframe(None)
- @arguments("box")
- def _opimpl_any_copy(self, box):
- return box
- opimpl_int_copy = _opimpl_any_copy
- opimpl_ref_copy = _opimpl_any_copy
- opimpl_float_copy = _opimpl_any_copy
- @arguments("box")
- def _opimpl_any_push(self, box):
- self.pushed_box = box
- opimpl_int_push = _opimpl_any_push
- opimpl_ref_push = _opimpl_any_push
- opimpl_float_push = _opimpl_any_push
- @arguments()
- def _opimpl_any_pop(self):
- box = self.pushed_box
- self.pushed_box = None
- return box
- opimpl_int_pop = _opimpl_any_pop
- opimpl_ref_pop = _opimpl_any_pop
- opimpl_float_pop = _opimpl_any_pop
- @arguments("label")
- def opimpl_catch_exception(self, target):
- """This is a no-op when run normally. We can check that
- last_exc_value_box is None; it should have been set to None
- by the previous instruction. If the previous instruction
- raised instead, finishframe_exception() should have been
- called and we would not be there."""
- assert self.metainterp.last_exc_value_box is None
- @arguments("label")
- def opimpl_goto(self, target):
- self.pc = target
- @arguments("box", "label")
- def opimpl_goto_if_not(self, box, target):
- switchcase = box.getint()
- if switchcase:
- opnum = rop.GUARD_TRUE
- else:
- opnum = rop.GUARD_FALSE
- self.generate_guard(opnum, box)
- if not switchcase:
- self.pc = target
- @arguments("box", "label")
- def opimpl_goto_if_not_int_is_true(self, box, target):
- condbox = self.execute(rop.INT_IS_TRUE, box)
- self.opimpl_goto_if_not(condbox, target)
- @arguments("box", "label")
- def opimpl_goto_if_not_int_is_zero(self, box, target):
- condbox = self.execute(rop.INT_IS_ZERO, box)
- self.opimpl_goto_if_not(condbox, target)
- for _opimpl in ['int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge',
- 'ptr_eq', 'ptr_ne']:
- exec py.code.Source('''
- @arguments("box", "box", "label")
- def opimpl_goto_if_not_%s(self, b1, b2, target):
- condbox = self.execute(rop.%s, b1, b2)
- self.opimpl_goto_if_not(condbox, target)
- ''' % (_opimpl, _opimpl.upper())).compile()
- def _establish_nullity(self, box, orgpc):
- value = box.nonnull()
- if value:
- if not self.metainterp.heapcache.is_class_known(box):
- self.generate_guard(rop.GUARD_NONNULL, box, resumepc=orgpc)
- else:
- if not isinstance(box, Const):
- self.generate_guard(rop.GUARD_ISNULL, box, resumepc=orgpc)
- promoted_box = box.constbox()
- self.metainterp.replace_box(box, promoted_box)
- return value
- @arguments("box", "label", "orgpc")
- def opimpl_goto_if_not_ptr_nonzero(self, box, target, orgpc):
- if not self._establish_nullity(box, orgpc):
- self.pc = target
- @arguments("box", "label", "orgpc")
- def opimpl_goto_if_not_ptr_iszero(self, box, target, orgpc):
- if self._establish_nullity(box, orgpc):
- self.pc = target
- @arguments("box", "box", "box")
- def opimpl_int_between(self, b1, b2, b3):
- b5 = self.execute(rop.INT_SUB, b3, b1)
- if isinstance(b5, ConstInt) and b5.getint() == 1:
- # the common case of int_between(a, b, a+1) turns into just INT_EQ
- return self.execute(rop.INT_EQ, b2, b1)
- else:
- b4 = self.execute(rop.INT_SUB, b2, b1)
- return self.execute(rop.UINT_LT, b4, b5)
- @arguments("box", "descr", "orgpc")
- def opimpl_switch(self, valuebox, switchdict, orgpc):
- box = self.implement_guard_value(valuebox, orgpc)
- search_value = box.getint()
- assert isinstance(switchdict, SwitchDictDescr)
- try:
- self.pc = switchdict.dict[search_value]
- except KeyError:
- pass
- @arguments()
- def opimpl_unreachable(self):
- raise AssertionError("unreachable")
- @arguments("descr")
- def opimpl_new(self, sizedescr):
- resbox = self.execute_with_descr(rop.NEW, sizedescr)
- self.metainterp.heapcache.new(resbox)
- return resbox
- @arguments("descr")
- def opimpl_new_with_vtable(self, sizedescr):
- cpu = self.metainterp.cpu
- cls = heaptracker.descr2vtable(cpu, sizedescr)
- resbox = self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
- self.metainterp.heapcache.new(resbox)
- self.metainterp.heapcache.class_now_known(resbox)
- return resbox
- @arguments("box", "descr")
- def opimpl_new_array(self, lengthbox, itemsizedescr):
- resbox = self.execute_with_descr(rop.NEW_ARRAY, itemsizedescr, lengthbox)
- self.metainterp.heapcache.new_array(resbox, lengthbox)
- return resbox
- @specialize.arg(1)
- def _do_getarrayitem_gc_any(self, op, arraybox, indexbox, arraydescr):
- tobox = self.metainterp.heapcache.getarrayitem(
- arraybox, indexbox, arraydescr)
- if tobox:
- # sanity check: see whether the current array value
- # corresponds to what the cache thinks the value is
- resbox = executor.execute(self.metainterp.cpu, self.metainterp, op,
- arraydescr, arraybox, indexbox)
- assert resbox.constbox().same_constant(tobox.constbox())
- return tobox
- resbox = self.execute_with_descr(op, arraydescr, arraybox, indexbox)
- self.metainterp.heapcache.getarrayitem_now_known(
- arraybox, indexbox, resbox, arraydescr)
- return resbox
- @arguments("box", "box", "descr")
- def _opimpl_getarrayitem_gc_any(self, arraybox, indexbox, arraydescr):
- return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC, arraybox,
- indexbox, arraydescr)
- opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any
- opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any
- opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any
- @arguments("box", "box", "descr")
- def _opimpl_getarrayitem_raw_any(self, arraybox, indexbox, arraydescr):
- return self.execute_with_descr(rop.GETARRAYITEM_RAW,
- arraydescr, arraybox, indexbox)
- opimpl_getarrayitem_raw_i = _opimpl_getarrayitem_raw_any
- opimpl_getarrayitem_raw_f = _opimpl_getarrayitem_raw_any
- @arguments("box", "box", "descr")
- def _opimpl_getarrayitem_raw_pure_any(self, arraybox, indexbox,
- arraydescr):
- return self.execute_with_descr(rop.GETARRAYITEM_RAW_PURE,
- arraydescr, arraybox, indexbox)
- opimpl_getarrayitem_raw_i_pure = _opimpl_getarrayitem_raw_pure_any
- opimpl_getarrayitem_raw_f_pure = _opimpl_getarrayitem_raw_pure_any
- @arguments("box", "box", "descr")
- def _opimpl_getarrayitem_gc_pure_any(self, arraybox, indexbox, arraydescr):
- if isinstance(arraybox, ConstPtr) and isinstance(indexbox, ConstInt):
- # if the arguments are directly constants, bypass the heapcache
- # completely
- resbox = executor.execute(self.metainterp.cpu, self.metainterp,
- rop.GETARRAYITEM_GC_PURE, arraydescr,
- arraybox, indexbox)
- return resbox.constbox()
- return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_PURE, arraybox,
- indexbox, arraydescr)
- opimpl_getarrayitem_gc_i_pure = _opimpl_getarrayitem_gc_pure_any
- opimpl_getarrayitem_gc_r_pure = _opimpl_getarrayitem_gc_pure_any
- opimpl_getarrayitem_gc_f_pure = _opimpl_getarrayitem_gc_pure_any
- @arguments("box", "box", "box", "descr")
- def _opimpl_setarrayitem_gc_any(self, arraybox, indexbox, itembox,
- arraydescr):
- self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox,
- indexbox, itembox)
- self.metainterp.heapcache.setarrayitem(
- arraybox, indexbox, itembox, arraydescr)
- opimpl_setarrayitem_gc_i = _opimpl_setarrayitem_gc_any
- opimpl_setarrayitem_gc_r = _opimpl_setarrayitem_gc_any
- opimpl_setarrayitem_gc_f = _opimpl_setarrayitem_gc_any
- @arguments("box", "box", "box", "descr")
- def _opimpl_setarrayitem_raw_any(self, arraybox, indexbox, itembox,
- arraydescr):
- self.execute_with_descr(rop.SETARRAYITEM_RAW, arraydescr, arraybox,
- indexbox, itembox)
- opimpl_setarrayitem_raw_i = _opimpl_setarrayitem_raw_any
- opimpl_setarrayitem_raw_f = _opimpl_setarrayitem_raw_any
- @arguments("box", "descr")
- def opimpl_arraylen_gc(self, arraybox, arraydescr):
- lengthbox = self.metainterp.heapcache.arraylen(arraybox)
- if lengthbox is None:
- lengthbox = self.execute_with_descr(
- rop.ARRAYLEN_GC, arraydescr, arraybox)
- self.metainterp.heapcache.arraylen_now_known(arraybox, lengthbox)
- return lengthbox
- @arguments("box", "box", "descr", "orgpc")
- def opimpl_check_neg_index(self, arraybox, indexbox, arraydescr, orgpc):
- negbox = self.metainterp.execute_and_record(
- rop.INT_LT, None, indexbox, history.CONST_FALSE)
- negbox = self.implement_guard_value(negbox, orgpc)
- if negbox.getint():
- # the index is < 0; add the array length to it
- lengthbox = self.opimpl_arraylen_gc(arraybox, arraydescr)
- indexbox = self.metainterp.execute_and_record(
- rop.INT_ADD, None, indexbox, lengthbox)
- return indexbox
- @arguments("box", "descr", "descr", "descr", "descr")
- def opimpl_newlist(self, sizebox, structdescr, lengthdescr,
- itemsdescr, arraydescr):
- sbox = self.opimpl_new(structdescr)
- self._opimpl_setfield_gc_any(sbox, sizebox, lengthdescr)
- abox = self.opimpl_new_array(sizebox, arraydescr)
- self._opimpl_setfield_gc_any(sbox, abox, itemsdescr)
- return sbox
- @arguments("box", "descr", "descr", "descr", "descr")
- def opimpl_newlist_hint(self, sizehintbox, structdescr, lengthdescr,
- itemsdescr, arraydescr):
- sbox = self.opimpl_new(structdescr)
- self._opimpl_setfield_gc_any(sbox, history.CONST_FALSE, lengthdescr)
- abox = self.opimpl_new_array(sizehintbox, arraydescr)
- self._opimpl_setfield_gc_any(sbox, abox, itemsdescr)
- return sbox
- @arguments("box", "box", "descr", "descr")
- def _opimpl_getlistitem_gc_any(self, listbox, indexbox,
- itemsdescr, arraydescr):
- arraybox = self._opimpl_getfield_gc_any(listbox, itemsdescr)
- return self._opimpl_getarrayitem_gc_any(arraybox, indexbox, arraydescr)
- opimpl_getlistitem_gc_i = _opimpl_getlistitem_gc_any
- opimpl_getlistitem_gc_r = _opimpl_getlistitem_gc_any
- opimpl_getlistitem_gc_f = _opimpl_getlistitem_gc_any
- @arguments("box", "box", "box", "descr", "descr")
- def _opimpl_setlistitem_gc_any(self, listbox, indexbox, valuebox,
- itemsdescr, arraydescr):
- arraybox = self._opimpl_getfield_gc_any(listbox, itemsdescr)
- self._opimpl_setarrayitem_gc_any(arraybox, indexbox, valuebox,
- arraydescr)
- opimpl_setlistitem_gc_i = _opimpl_setlistitem_gc_any
- opimpl_setlistitem_gc_r = _opimpl_setlistitem_gc_any
- opimpl_setlistitem_gc_f = _opimpl_setlistitem_gc_any
- @arguments("box", "box", "descr", "orgpc")
- def opimpl_check_resizable_neg_index(self, listbox, indexbox,
- lengthdescr, orgpc):
- negbox = self.metainterp.execute_and_record(
- rop.INT_LT, None, indexbox, history.CONST_FALSE)
- negbox = self.implement_guard_value(negbox, orgpc)
- if negbox.getint():
- # the index is < 0; add the array length to it
- lenbox = self.metainterp.execute_and_record(
- rop.GETFIELD_GC, lengthdescr, listbox)
- indexbox = self.metainterp.execute_and_record(
- rop.INT_ADD, None, indexbox, lenbox)
- return indexbox
- @arguments("box", "descr")
- def _opimpl_getfield_gc_any(self, box, fielddescr):
- return self._opimpl_getfield_gc_any_pureornot(
- rop.GETFIELD_GC, box, fielddescr)
- opimpl_getfield_gc_i = _opimpl_getfield_gc_any
- opimpl_getfield_gc_r = _opimpl_getfield_gc_any
- opimpl_getfield_gc_f = _opimpl_getfield_gc_any
- @arguments("box", "descr")
- def _opimpl_getfield_gc_pure_any(self, box, fielddescr):
- if isinstance(box, ConstPtr):
- # if 'box' is directly a ConstPtr, bypass the heapcache completely
- resbox = executor.execute(self.metainterp.cpu, self.metainterp,
- rop.GETFIELD_GC_PURE, fielddescr, box)
- return resbox.constbox()
- return self._opimpl_getfield_gc_any_pureornot(
- rop.GETFIELD_GC_PURE, box, fielddescr)
- opimpl_getfield_gc_i_pure = _opimpl_getfield_gc_pure_any
- opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any
- opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any
- @arguments("box", "box", "descr")
- def _opimpl_getinteriorfield_gc_any(self, array, index, descr):
- return self.execute_with_descr(rop.GETINTERIORFIELD_GC, descr,
- array, index)
- opimpl_getinteriorfield_gc_i = _opimpl_getinteriorfield_gc_any
- opimpl_getinteriorfield_gc_f = _opimpl_getinteriorfield_gc_any
- opimpl_getinteriorfield_gc_r = _opimpl_getinteriorfield_gc_any
- @specialize.arg(1)
- def _opimpl_getfield_gc_any_pureornot(self, opnum, box, fielddescr):
- tobox = self.metainterp.heapcache.getfield(box, fielddescr)
- if tobox is not None:
- # sanity check: see whether the current struct value
- # corresponds to what the cache thinks the value is
- #resbox = executor.execute(self.metainterp.cpu, self.metainterp,
- # rop.GETFIELD_GC, fielddescr, box)
- # XXX the sanity check does not seem to do anything, remove?
- return tobox
- resbox = self.execute_with_descr(opnum, fielddescr, box)
- self.metainterp.heapcache.getfield_now_known(box, fielddescr, resbox)
- return resbox
- @arguments("box", "descr", "orgpc")
- def _opimpl_getfield_gc_greenfield_any(self, box, fielddescr, pc):
- ginfo = self.metainterp.jitdriver_sd.greenfield_info
- if (ginfo is not None and fielddescr in ginfo.green_field_descrs
- and not self._nonstandard_virtualizable(pc, box)):
- # fetch the result, but consider it as a Const box and don't
- # record any operation
- resbox = executor.execute(self.metainterp.cpu, self.metainterp,
- rop.GETFIELD_GC_PURE, fielddescr, box)
- return resbox.constbox()
- # fall-back
- return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box)
- opimpl_getfield_gc_i_greenfield = _opimpl_getfield_gc_greenfield_any
- opimpl_getfield_gc_r_greenfield = _opimpl_getfield_gc_greenfield_any
- opimpl_getfield_gc_f_greenfield = _opimpl_getfield_gc_greenfield_any
- @arguments("box", "box", "descr")
- def _opimpl_setfield_gc_any(self, box, valuebox, fielddescr):
- tobox = self.metainterp.heapcache.getfield(box, fielddescr)
- if tobox is valuebox:
- return
- self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
- self.metainterp.heapcache.setfield(box, valuebox, fielddescr)
- opimpl_setfield_gc_i = _opimpl_setfield_gc_any
- opimpl_setfield_gc_r = _opimpl_setfield_gc_any
- opimpl_setfield_gc_f = _opimpl_setfield_gc_any
- @arguments("box", "box", "box", "descr")
- def _opimpl_setinteriorfield_gc_any(self, array, index, value, descr):
- self.execute_with_descr(rop.SETINTERIORFIELD_GC, descr,
- array, index, value)
- opimpl_setinteriorfield_gc_i = _opimpl_setinteriorfield_gc_any
- opimpl_setinteriorfield_gc_f = _opimpl_setinteriorfield_gc_any
- opimpl_setinteriorfield_gc_r = _opimpl_setinteriorfield_gc_any
- @arguments("box", "descr")
- def _opimpl_getfield_raw_any(self, box, fielddescr):
- return self.execute_with_descr(rop.GETFIELD_RAW, fielddescr, box)
- opimpl_getfield_raw_i = _opimpl_getfield_raw_any
- opimpl_getfield_raw_r = _opimpl_getfield_raw_any
- opimpl_getfield_raw_f = _opimpl_getfield_raw_any
- @arguments("box", "descr")
- def _opimpl_getfield_raw_pure_any(self, box, fielddescr):
- return self.execute_with_descr(rop.GETFIELD_RAW_PURE, fielddescr, box)
- opimpl_getfield_raw_i_pure = _opimpl_getfield_raw_pure_any
- opimpl_getfield_raw_r_pure = _opimpl_getfield_raw_pure_any
- opimpl_getfield_raw_f_pure = _opimpl_getfield_raw_pure_any
- @arguments("box", "box", "descr")
- def _opimpl_setfield_raw_any(self, box, valuebox, fielddescr):
- self.execute_with_descr(rop.SETFIELD_RAW, fielddescr, box, valuebox)
- opimpl_setfield_raw_i = _opimpl_setfield_raw_any
- opimpl_setfield_raw_r = _opimpl_setfield_raw_any
- opimpl_setfield_raw_f = _opimpl_setfield_raw_any
- @arguments("box", "box", "box", "descr")
- def _opimpl_raw_store(self, addrbox, offsetbox, valuebox, arraydescr):
- self.execute_with_descr(rop.RAW_STORE, arraydescr,
- addrbox, offsetbox, valuebox)
- opimpl_raw_store_i = _opimpl_raw_store
- opimpl_raw_store_f = _opimpl_raw_store
- @arguments("box", "box", "descr")
- def _opimpl_raw_load(self, addrbox, offsetbox, arraydescr):
- return self.execute_with_descr(rop.RAW_LOAD, arraydescr,
- addrbox, offsetbox)
- opimpl_raw_load_i = _opimpl_raw_load
- opimpl_raw_load_f = _opimpl_raw_load
- @arguments("box", "descr", "descr", "orgpc")
- def opimpl_record_quasiimmut_field(self, box, fielddescr,
- mutatefielddescr, orgpc):
- from pypy.jit.metainterp.quasiimmut import QuasiImmutDescr
- cpu = self.metainterp.cpu
- descr = QuasiImmutDescr(cpu, box, fielddescr, mutatefielddescr)
- self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box],
- None, descr=descr)
- self.generate_guard(rop.GUARD_NOT_INVALIDATED, resumepc=orgpc)
- @arguments("box", "descr", "orgpc")
- def opimpl_jit_force_quasi_immutable(self, box, mutatefielddescr, orgpc):
- # During tracing, a 'jit_force_quasi_immutable' usually turns into
- # the operations that check that the content of 'mutate_xxx' is null.
- # If it is actually not null already now, then we abort tracing.
- # The idea is that if we use 'jit_force_quasi_immutable' on a freshly
- # allocated object, then the GETFIELD_GC will know that the answer is
- # null, and the guard will be removed. So the fact that the field is
- # quasi-immutable will have no effect, and instead it will work as a
- # regular, probably virtual, structure.
- mutatebox = self.execute_with_descr(rop.GETFIELD_GC,
- mutatefielddescr, box)
- if mutatebox.nonnull():
- from pypy.jit.metainterp.quasiimmut import do_force_quasi_immutable
- do_force_quasi_immutable(self.metainterp.cpu, box.getref_base(),
- mutatefielddescr)
- raise SwitchToBlackhole(Counters.ABORT_FORCE_QUASIIMMUT)
- self.generate_guard(rop.GUARD_ISNULL, mutatebox, resumepc=orgpc)
- def _nonstandard_virtualizable(self, pc, box):
- # returns True if 'box' is actually not the "standard" virtualizable
- # that is stored in metainterp.virtualizable_boxes[-1]
- if (self.metainterp.jitdriver_sd.virtualizable_info is None and
- self.metainterp.jitdriver_sd.greenfield_info is None):
- return True # can occur in case of multiple JITs
- standard_box = self.metainterp.virtualizable_boxes[-1]
- if standard_box is box:
- return False
- if self.metainterp.heapcache.is_nonstandard_virtualizable(box):
- return True
- eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None,
- box, standard_box)
- eqbox = self.implement_guard_value(eqbox, pc)
- isstandard = eqbox.getint()
- if isstandard:
- self.metainterp.replace_box(box, standard_box)
- else:
- self.metainterp.heapcache.nonstandard_virtualizables_now_known(box)
- return not isstandard
- def _get_virtualizable_field_index(self, fielddescr):
- # Get the index of a fielddescr. Must only be called for
- # the "standard" virtualizable.
- vinfo = self.metainterp.jitdriver_sd.virtualizable_info
- return vinfo.static_field_by_descrs[fielddescr]
- @arguments("box", "descr", "orgpc")
- def _opimpl_getfield_vable(self, box, fielddescr, pc):
- if self._nonstandard_virtualizable(pc, box):
- return self._opimpl_getfield_gc_any(box, fielddescr)
- self.metainterp.check_synchronized_virtualizable()
- index = self._get_virtualizable_field_index(fielddescr)
- return self.metainterp.virtualizable_boxes[index]
- opimpl_getfield_vable_i = _opimpl_getfield_vable
- opimpl_getfield_vable_r = _opimpl_getfield_vable
- opimpl_getfield_vable_f = _opimpl_getfield_vable
- @arguments("box", "box", "descr", "orgpc")
- def _opimpl_setfield_vable(self, box, valuebox, fielddescr, pc):
- if self._nonstandard_virtualizable(pc, box):
- return self._opimpl_setfield_gc_any(box, valuebox, fielddescr)
- index = self._get_virtualizable_field_index(fielddescr)
- self.metainterp.virtualizable_boxes[index] = valuebox
- self.metainterp.synchronize_virtualizable()
- # XXX only the index'th field needs to be synchronized, really
- opimpl_setfield_vable_i = _opimpl_setfield_vable
- opimpl_setfield_vable_r = _opimpl_setfield_vable
- opimpl_setfield_vable_f = _opimpl_setfield_vable
- def _get_arrayitem_vable_index(self, pc, arrayfielddescr, indexbox):
- # Get the index of an array item: the index'th of the array
- # described by arrayfielddescr. Must only be called for
- # the "standard" virtualizable.
- indexbox = self.implement_guard_value(indexbox, pc)
- vinfo = self.metainterp.jitdriver_sd.virtualizable_info
- virtualizable_box = self.metainterp.virtualizable_boxes[-1]
- virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
- arrayindex = vinfo.array_field_by_descrs[arrayfielddescr]
- index = indexbox.getint()
- # Support for negative index: disabled
- # (see codewriter/jtransform.py, _check_no_vable_array).
- #if index < 0:
- # index += vinfo.get_array_length(virtualizable, arrayindex)
- assert 0 <= index < vinfo.get_array_length(virtualizable, arrayindex)
- return vinfo.get_index_in_array(virtualizable, arrayindex, index)
- @arguments("box", "box", "descr", "descr", "orgpc")
- def _opimpl_getarrayitem_vable(self, box, indexbox, fdescr, adescr, pc):
- if self._nonstandard_virtualizable(pc, box):
- arraybox = self._opimpl_getfield_gc_any(box, fdescr)
- return self._opimpl_getarrayitem_gc_any(arraybox, indexbox, adescr)
- self.metainterp.check_synchronized_virtualizable()
- index = self._get_arrayitem_vable_index(pc, fdescr, indexbox)
- return self.metainterp.virtualizable_boxes[index]
- opimpl_getarrayitem_vable_i = _opimpl_getarrayitem_vable
- opimpl_getarrayitem_vable_r = _opimpl_getarrayitem_vable
- opimpl_getarrayitem_vable_f = _opimpl_getarrayitem_vable
- @arguments("box", "box", "box", "descr", "descr", "orgpc")
- def _opimpl_setarrayitem_vable(self, box, indexbox, valuebox,
- fdescr, adescr, pc):
- if self._nonstandard_virtualizable(pc, box):
- arraybox = self._opimpl_getfield_gc_any(box, fdescr)
- self._opimpl_setarrayitem_gc_any(arraybox, indexbox, valuebox,
- adescr)
- return
- index = self._get_arrayitem_vable_index(pc, fdescr, indexbox)
- self.metainterp.virtualizable_boxes[index] = valuebox
- self.metainterp.synchronize_virtualizable()
- # XXX only the index'th field needs to be synchronized, really
- opimpl_setarrayitem_vable_i = _opimpl_setarrayitem_vable
- opimpl_setarrayitem_vable_r = _opimpl_setarrayitem_vable
- opimpl_setarrayitem_vable_f = _opimpl_setarrayitem_vable
- @arguments("box", "descr", "descr", "orgpc")
- def opimpl_arraylen_vable(self, box, fdescr, adescr, pc):
- if self._nonstandard_virtualizable(pc, box):
- arraybox = self._opimpl_getfield_gc_any(box, fdescr)
- return self.opimpl_arraylen_gc(arraybox, adescr)
- vinfo = self.metainterp.jitdriver_sd.virtualizable_info
- virtualizable_box = self.metainterp.virtualizable_boxes[-1]
- virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
- arrayindex = vinfo.array_field_by_descrs[fdescr]
- result = vinfo.get_array_length(virtualizable, arrayindex)
- return ConstInt(result)
- @arguments("jitcode", "boxes")
- def _opimpl_inline_call1(self, jitcode, argboxes):
- return self.metainterp.perform_call(jitcode, argboxes)
- @arguments("jitcode", "boxes2")
- def _opimpl_inline_call2(self, jitcode, argboxes):
- return self.metainterp.perform_call(jitcode, argboxes)
- @arguments("jitcode", "boxes3")
- def _opimpl_inline_call3(self, jitcode, argboxes):
- return self.metainterp.perform_call(jitcode, argboxes)
- opimpl_inline_call_r_i = _opimpl_inline_call1
- opimpl_inline_call_r_r = _opimpl_inline_call1
- opimpl_inline_call_r_v = _opimpl_inline_call1
- opimpl_inline_call_ir_i = _opimpl_inline_call2
- opimpl_inline_call_ir_r = _opimpl_inline_call2
- opimpl_inline_call_ir_v = _opimpl_inline_call2
- opimpl_inline_call_irf_i = _opimpl_inline_call3
- opimpl_inline_call_irf_r = _opimpl_inline_call3
- opimpl_inline_call_irf_f = _opimpl_inline_call3
- opimpl_inline_call_irf_v = _opimpl_inline_call3
- @arguments("box", "boxes", "descr")
- def _opimpl_residual_call1(self, funcbox, argboxes, calldescr):
- return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
- @arguments("box", "boxes2", "descr")
- def _opimpl_residual_call2(self, funcbox, argboxes, calldescr):
- return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
- @arguments("box", "boxes3", "descr")
- def _opimpl_residual_call3(self, funcbox, argboxes, calldescr):
- return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr)
- opimpl_residual_call_r_i = _opimpl_residual_call1
- opimpl_residual_call_r_r = _opimpl_residual_call1
- opimpl_residual_call_r_v = _opimpl_residual_call1
- opimpl_residual_call_ir_i = _opimpl_residual_call2
- opimpl_residual_call_ir_r = _opimpl_residual_call2
- opimpl_residual_call_ir_v = _opimpl_residual_call2
- opimpl_residual_call_irf_i = _opimpl_residual_call3
- opimpl_residual_call_irf_r = _opimpl_residual_call3
- opimpl_residual_call_irf_f = _opimpl_residual_call3
- opimpl_residual_call_irf_v = _opimpl_residual_call3
- @arguments("int", "boxes3", "boxes3")
- def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes):
- targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
- allboxes = greenboxes + redboxes
- warmrunnerstate = targetjitdriver_sd.warmstate
- assembler_call = False
- if warmrunnerstate.inlining:
- if warmrunnerstate.can_inline_callable(greenboxes):
- portal_code = targetjitdriver_sd.mainjitcode
- return self.metainterp.perform_call(portal_code, allboxes,
- greenkey=greenboxes)
- assembler_call = True
- # verify that we have all green args, needed to make sure
- # that assembler that we call is still correct
- self.verify_green_args(targetjitdriver_sd, greenboxes)
- #
- return self.do_recursive_call(targetjitdriver_sd, allboxes,
- assembler_call)
- def do_recursive_call(self, targetjitdriver_sd, allboxes,
- assembler_call=False):
- portal_code = targetjitdriver_sd.mainjitcode
- k = targetjitdriver_sd.portal_runner_adr
- funcbox = ConstInt(heaptracker.adr2int(k))
- return self.do_residual_call(funcbox, allboxes, portal_code.calldescr,
- assembler_call=assembler_call,
- assembler_call_jd=targetjitdriver_sd)
- opimpl_recursive_call_i = _opimpl_recursive_call
- opimpl_recursive_call_r = _opimpl_recursive_call
- opimpl_recursive_call_f = _opimpl_recursive_call
- opimpl_recursive_call_v = _opimpl_recursive_call
- @arguments("box")
- def opimpl_strlen(self, strbox):
- return self.execute(rop.STRLEN, strbox)
- @arguments("box")
- def opimpl_unicodelen(self, unicodebox):
- return self.execute(rop.UNICODELEN, unicodebox)
- @arguments("box", "box")
- def opimpl_strgetitem(self, strbox, indexbox):
- return self.execute(rop.STRGETITEM, strbox, indexbox)
- @arguments("box", "box")
- def opimpl_unicodegetitem(self, unicodebox, indexbox):
- return self.execute(rop.UNICODEGETITEM, unicodebox, indexbox)
- @arguments("box", "box", "box")
- def opimpl_strsetitem(self, strbox, indexbox, newcharbox):
- return self.execute(rop.STRSETITEM, strbox, indexbox, newcharbox)
- @arguments("box", "box", "box")
- def opimpl_unicodesetitem(self, unicodebox, indexbox, newcharbox):
- self.execute(rop.UNICODESETITEM, unicodebox, indexbox, newcharbox)
- @arguments("box")
- def opimpl_newstr(self, lengthbox):
- return self.execute(rop.NEWSTR, lengthbox)
- @arguments("box")
- def opimpl_newunicode(self, lengthbox):
- return self.execute(rop.NEWUNICODE, lengthbox)
- @arguments("box", "box", "box", "box", "box")
- def opimpl_copystrcontent(self, srcbox, dstbox, srcstartbox, dststartbox, lengthbox):
- return self.execute(rop.COPYSTRCONTENT, srcbox, dstbox, srcstartbox, dststartbox, lengthbox)
- @arguments("box", "box", "box", "box", "box")
- def opimpl_copyunicodecontent(self, srcbox, dstbox, srcstartbox, dststartbox, lengthbox):
- return self.execute(rop.COPYUNICODECONTENT, srcbox, dstbox, srcstartbox, dststartbox, lengthbox)
- @arguments("box", "orgpc")
- def _opimpl_guard_value(self, box, orgpc):
- self.implement_guard_value(box, orgpc)
- @arguments("box", "box", "descr", "orgpc")
- def opimpl_str_guard_value(self, box, funcbox, descr, orgpc):
- if isinstance(box, Const):
- return box # no promotion needed, already a Const
- else:
- constbox = box.constbox()
- resbox = self.do_residual_call(funcbox, [box, constbox], descr)
- promoted_box = resbox.constbox()
- # This is GUARD_VALUE because GUARD_TRUE assumes the existance
- # of a label when computing resumepc
- self.generate_guard(rop.GUARD_VALUE, resbox, [promoted_box],
- resumepc=orgpc)
- self.metainterp.replace_box(box, constbox)
- return constbox
- opimpl_int_guard_value = _opimpl_guard_value
- opimpl_ref_guard_value = _opimpl_guard_value
- opimpl_float_guard_value = _opimpl_guard_value
- @arguments("box", "orgpc")
- def opimpl_guard_class(self, box, orgpc):
- clsbox = self.cls_of_box(box)
- if not self.metainterp.heapcache.is_class_known(box):
- self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
- self.metainterp.heapcache.class_now_known(box)
- return clsbox
- @arguments("int", "orgpc")
- def opimpl_loop_header(self, jdindex, orgpc):
- self.metainterp.seen_loop_header_for_jdindex = jdindex
- def verify_green_args(self, jitdriver_sd, varargs):
- num_green_args = jitdriver_sd.num_green_args
- assert len(varargs) == num_green_args
- for i in range(num_green_args):
- assert isinstance(varargs[i], Const)
- @arguments("int", "boxes3", "jitcode_position", "boxes3", "orgpc")
- def opimpl_jit_merge_point(self, jdindex, greenboxes,
- jcposition, redboxes, orgpc):
- resumedescr = compile.ResumeAtPositionDescr()
- self.capture_resumedata(resumedescr, orgpc)
- any_operation = len(self.metainterp.history.operations) > 0
- jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex]
- self.verify_green_args(jitdriver_sd, greenboxes)
- self.debug_merge_point(jitdriver_sd, jdindex,
- self.metainterp.portal_call_depth,
- self.metainterp.call_ids[-1],
- greenboxes)
- if self.metainterp.seen_loop_header_for_jdindex < 0:
- if not any_operation:
- return
- if self.metainterp.portal_call_depth or not self.metainterp.get_procedure_token(greenboxes, True):
- if not jitdriver_sd.no_loop_header:
- return
- # automatically add a loop_header if there is none
- self.metainterp.seen_loop_header_for_jdindex = jdindex
- #
- assert self.metainterp.seen_loop_header_for_jdindex == jdindex, (
- "found a loop_header for a JitDriver that does not match "
- "the following jit_merge_point's")
- self.metainterp.seen_loop_header_for_jdindex = -1
- #
- if not self.metainterp.portal_call_depth:
- assert jitdriver_sd is self.metainterp.jitdriver_sd
- # Set self.pc to point to jit_merge_point instead of just after:
- # if reached_loop_header() raises SwitchToBlackhole, then the
- # pc is still at the jit_merge_point, which is a point that is
- # much less expensive to blackhole out of.
- saved_pc = self.pc
- self.pc = orgpc
- self.metainterp.reached_loop_header(greenboxes, redboxes, resumedescr)
- self.pc = saved_pc
- # no exception, which means that the jit_merge_point did not
- # close the loop. We have to put the possibly-modified list
- # 'redboxes' back into the registers where it comes from.
- put_back_list_of_boxes3(self, jcposition, redboxes)
- else:
- if jitdriver_sd.warmstate.should_unroll_one_iteration(greenboxes):
- if self.unroll_iterations > 0:
- self.unroll_iterations -= 1
- return
- # warning! careful here. We have to return from the current
- # frame containing the jit_merge_point, and then use
- # do_recursive_call() to follow the recursive call. This is
- # needed because do_recursive_call() will write its result
- # with make_result_of_lastop(), so the lastop must be right:
- # it must be the call to 'self', and not the jit_merge_point
- # itself, which has no result at all.
- assert len(self.metainterp.framestack) >= 2
- try:
- self.metainterp.finishframe(None)
- except ChangeFrame:
- pass
- frame = self.metainterp.framestack[-1]
- frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes,
- assembler_call=True)
- raise ChangeFrame
- def debug_merge_point(self, jitdriver_sd, jd_index, portal_call_depth, current_call_id, greenkey):
- # debugging: produce a DEBUG_MERGE_POINT operation
- loc = jitdriver_sd.warmstate.get_location_str(greenkey)
- debug_print(loc)
- args = [ConstInt(jd_index), ConstInt(portal_call_depth), ConstInt(current_call_id)] + greenkey
- self.metainterp.history.record(rop.DEBUG_MERGE_POINT, args, None)
- @arguments("box", "label")
- def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target):
- metainterp = self.metainterp
- last_exc_value_box = metainterp.last_exc_value_box
- assert last_exc_value_box is not None
- assert metainterp.class_of_last_exc_is_const
- if not metainterp.cpu.ts.instanceOf(last_exc_value_box, vtablebox):
- self.pc = next_exc_target
- @arguments("box", "orgpc")
- def opimpl_raise(self, exc_value_box, orgpc):
- # xxx hack
- clsbox = self.cls_of_box(exc_value_box)
- self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox],
- resumepc=orgpc)
- self.metainterp.class_of_last_exc_is_const = True
- self.metainterp.last_exc_value_box = exc_value_box
- self.metainterp.popframe()
- self.metainterp.finishframe_exception()
- @arguments()
- def opimpl_reraise(self):
- assert self.metainterp.last_exc_value_box is not None
- self.metainterp.popframe()
- self.metainterp.finishframe_exception()
- @arguments()
- def opimpl_last_exception(self):
- # Same comment as in opimpl_goto_if_exception_mismatch().
- exc_value_box = self.metainterp.last_exc_value_box
- assert exc_value_box is not None
- assert self.metainterp.class_of_last_exc_is_const
- return self.metainterp.cpu.ts.cls_of_box(exc_value_box)
- @arguments()
- def opimpl_last_exc_value(self):
- exc_value_box = self.metainterp.last_exc_value_box
- assert exc_value_box is not None
- return exc_value_box
- @arguments("box")
- def opimpl_debug_fatalerror(self, box):
- from pypy.rpython.lltypesystem import rstr, lloperation
- msg = box.getref(lltype.Ptr(rstr.STR))
- lloperation.llop.debug_fatalerror(msg)
- @arguments("box", "box", "box", "box", "box")
- def opimpl_jit_debug(self, stringbox, arg1box, arg2box, arg3box, arg4box):
- from pypy.rpython.lltypesystem import rstr
- from pypy.rpython.annlowlevel import hlstr
- msg = stringbox.getref(lltype.Ptr(rstr.STR))
- debug_print('jit_debug:', hlstr(msg),
- arg1box.getint(),…
Large files files are truncated, but you can click here to view the full file