/pypy/jit/backend/llgraph/llimpl.py
Python | 1832 lines | 1637 code | 124 blank | 71 comment | 98 complexity | a5fba4f317fc116a3c08710fd4d41cd7 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- """
- The non-RPythonic part of the llgraph backend.
- This contains all the code that is directly run
- when executing on top of the llinterpreter.
- """
- import weakref
- from pypy.objspace.flow.model import Variable, Constant
- from pypy.annotation import model as annmodel
- from pypy.jit.metainterp.history import REF, INT, FLOAT
- from pypy.jit.metainterp import history
- from pypy.jit.codewriter import heaptracker
- from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
- from pypy.rpython.ootypesystem import ootype
- from pypy.rpython.module.support import LLSupport, OOSupport
- from pypy.rpython.llinterp import LLException
- from pypy.rpython.extregistry import ExtRegistryEntry
- from pypy.jit.metainterp import resoperation
- from pypy.jit.metainterp.resoperation import rop
- from pypy.jit.backend.llgraph import symbolic
- from pypy.jit.codewriter import longlong
- from pypy.rlib import libffi, clibffi
- from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
- from pypy.rlib.rarithmetic import ovfcheck
- from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
- from pypy.rlib.rtimer import read_timestamp
- import py
- from pypy.tool.ansi_print import ansi_log
- log = py.log.Producer('runner')
- py.log.setconsumer('runner', ansi_log)
- IS_32_BIT = r_ulonglong is not r_uint
- def _from_opaque(opq):
- return opq._obj.externalobj
- _TO_OPAQUE = {}
- def _to_opaque(value):
- try:
- return value._the_opaque_pointer
- except AttributeError:
- op = lltype.opaqueptr(_TO_OPAQUE[value.__class__], 'opaque',
- externalobj=value)
- value._the_opaque_pointer = op
- return op
- def _normalize(value):
- if isinstance(value, lltype._ptr):
- value = lltype.top_container(value._obj)
- return value
- def from_opaque_string(s):
- if isinstance(s, str):
- return s
- elif isinstance(s, ootype._string):
- return OOSupport.from_rstr(s)
- else:
- return LLSupport.from_rstr(s)
- FLOAT_ARRAY_TP = lltype.Ptr(lltype.Array(lltype.Float, hints={"nolength": True}))
- def maybe_uncast(TP, array):
- if array._TYPE.TO._hints.get("uncast_on_llgraph"):
- array = rffi.cast(TP, array)
- return array
- # a list of argtypes of all operations - couldn't find any and it's
- # very useful. Note however that the table is half-broken here and
- # there, in ways that are sometimes a bit hard to fix; that's why
- # it is not "official".
- TYPES = {
- 'int_add' : (('int', 'int'), 'int'),
- 'int_sub' : (('int', 'int'), 'int'),
- 'int_mul' : (('int', 'int'), 'int'),
- 'int_floordiv' : (('int', 'int'), 'int'),
- 'int_mod' : (('int', 'int'), 'int'),
- 'int_and' : (('int', 'int'), 'int'),
- 'int_or' : (('int', 'int'), 'int'),
- 'int_xor' : (('int', 'int'), 'int'),
- 'int_lshift' : (('int', 'int'), 'int'),
- 'int_rshift' : (('int', 'int'), 'int'),
- 'int_lt' : (('int', 'int'), 'bool'),
- 'int_gt' : (('int', 'int'), 'bool'),
- 'int_ge' : (('int', 'int'), 'bool'),
- 'int_le' : (('int', 'int'), 'bool'),
- 'int_eq' : (('int', 'int'), 'bool'),
- 'int_ne' : (('int', 'int'), 'bool'),
- 'int_is_true' : (('int',), 'bool'),
- 'int_is_zero' : (('int',), 'bool'),
- 'int_neg' : (('int',), 'int'),
- 'int_invert' : (('int',), 'int'),
- 'int_add_ovf' : (('int', 'int'), 'int'),
- 'int_sub_ovf' : (('int', 'int'), 'int'),
- 'int_mul_ovf' : (('int', 'int'), 'int'),
- 'uint_add' : (('int', 'int'), 'int'),
- 'uint_sub' : (('int', 'int'), 'int'),
- 'uint_mul' : (('int', 'int'), 'int'),
- 'uint_lt' : (('int', 'int'), 'bool'),
- 'uint_le' : (('int', 'int'), 'bool'),
- 'uint_eq' : (('int', 'int'), 'bool'),
- 'uint_ne' : (('int', 'int'), 'bool'),
- 'uint_gt' : (('int', 'int'), 'bool'),
- 'uint_ge' : (('int', 'int'), 'bool'),
- 'uint_xor' : (('int', 'int'), 'int'),
- 'uint_rshift' : (('int', 'int'), 'int'),
- 'uint_floordiv' : (('int', 'int'), 'int'),
- 'float_add' : (('float', 'float'), 'float'),
- 'float_sub' : (('float', 'float'), 'float'),
- 'float_mul' : (('float', 'float'), 'float'),
- 'float_truediv' : (('float', 'float'), 'float'),
- 'float_lt' : (('float', 'float'), 'bool'),
- 'float_le' : (('float', 'float'), 'bool'),
- 'float_eq' : (('float', 'float'), 'bool'),
- 'float_ne' : (('float', 'float'), 'bool'),
- 'float_gt' : (('float', 'float'), 'bool'),
- 'float_ge' : (('float', 'float'), 'bool'),
- 'float_neg' : (('float',), 'float'),
- 'float_abs' : (('float',), 'float'),
- 'cast_float_to_int':(('float',), 'int'),
- 'cast_int_to_float':(('int',), 'float'),
- 'same_as' : (('int',), 'int'), # could also be ptr=>ptr
- 'new_with_vtable' : (('ref',), 'ref'),
- 'new' : ((), 'ref'),
- 'new_array' : (('int',), 'ref'),
- 'oois' : (('ref', 'ref'), 'bool'),
- 'ooisnot' : (('ref', 'ref'), 'bool'),
- 'instanceof' : (('ref',), 'bool'),
- 'subclassof' : (('ref', 'ref'), 'bool'),
- 'runtimenew' : (('ref',), 'ref'),
- 'setfield_gc' : (('ref', 'intorptr'), None),
- 'getfield_gc' : (('ref',), 'intorptr'),
- 'getfield_gc_pure': (('ref',), 'intorptr'),
- 'setfield_raw' : (('ref', 'intorptr'), None),
- 'getfield_raw' : (('ref',), 'intorptr'),
- 'getfield_raw_pure': (('ref',), 'intorptr'),
- 'setarrayitem_gc' : (('ref', 'int', 'intorptr'), None),
- 'getarrayitem_gc' : (('ref', 'int'), 'intorptr'),
- 'getarrayitem_gc_pure' : (('ref', 'int'), 'intorptr'),
- 'setarrayitem_raw' : (('ref', 'int', 'intorptr'), None),
- 'getarrayitem_raw' : (('ref', 'int'), 'intorptr'),
- 'getarrayitem_raw_pure' : (('ref', 'int'), 'intorptr'),
- 'arraylen_gc' : (('ref',), 'int'),
- 'call' : (('ref', 'varargs'), 'intorptr'),
- 'call_assembler' : (('varargs',), 'intorptr'),
- 'cond_call_gc_wb' : (('ptr', 'ptr'), None),
- 'cond_call_gc_wb_array': (('ptr', 'int', 'ptr'), None),
- 'oosend' : (('varargs',), 'intorptr'),
- 'oosend_pure' : (('varargs',), 'intorptr'),
- 'guard_true' : (('bool',), None),
- 'guard_false' : (('bool',), None),
- 'guard_value' : (('int', 'int'), None),
- 'guard_class' : (('ref', 'ref'), None),
- 'guard_no_exception' : ((), None),
- 'guard_exception' : (('ref',), 'ref'),
- 'guard_no_overflow' : ((), None),
- 'guard_overflow' : ((), None),
- 'guard_nonnull' : (('ref',), None),
- 'guard_isnull' : (('ref',), None),
- 'guard_nonnull_class' : (('ref', 'ref'), None),
- 'newstr' : (('int',), 'ref'),
- 'strlen' : (('ref',), 'int'),
- 'strgetitem' : (('ref', 'int'), 'int'),
- 'strsetitem' : (('ref', 'int', 'int'), None),
- 'newunicode' : (('int',), 'ref'),
- 'unicodelen' : (('ref',), 'int'),
- 'unicodegetitem' : (('ref', 'int'), 'int'),
- 'unicodesetitem' : (('ref', 'int', 'int'), 'int'),
- 'cast_ptr_to_int' : (('ref',), 'int'),
- 'cast_int_to_ptr' : (('int',), 'ref'),
- 'debug_merge_point': (('ref', 'int'), None),
- 'force_token' : ((), 'int'),
- 'call_may_force' : (('int', 'varargs'), 'intorptr'),
- 'guard_not_forced': ((), None),
- }
- # ____________________________________________________________
- class CompiledLoop(object):
- has_been_freed = False
- invalid = False
- def __init__(self):
- self.inputargs = []
- self.operations = []
- def getargtypes(self):
- return [v.concretetype for v in self.inputargs]
- def __repr__(self):
- lines = []
- self.as_text(lines, 1)
- return 'CompiledLoop %s:\n%s' % (self.inputargs, '\n'.join(lines))
- def as_text(self, lines, indent):
- for op in self.operations:
- lines.append('\t'*indent + repr(op))
- class Operation(object):
- result = None
- descr = None
- jump_target = None
- fail_args = None
- def __init__(self, opnum):
- self.opnum = opnum
- self.args = []
- def __repr__(self):
- if self.result is not None:
- sres = repr0(self.result) + ' = '
- else:
- sres = ''
- return '{%s%s(%s)}' % (sres, self.getopname(),
- ', '.join(map(repr0, self.args)))
- def getopname(self):
- try:
- return resoperation.opname[self.opnum]
- except KeyError:
- return '<%d>' % self.opnum
- def is_guard(self):
- return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST
- def is_final(self):
- return rop._FINAL_FIRST <= self.opnum <= rop._FINAL_LAST
- def repr0(x):
- if isinstance(x, list):
- return '[' + ', '.join(repr0(y) for y in x) + ']'
- elif isinstance(x, Constant):
- return '(' + repr0(x.value) + ')'
- elif isinstance(x, lltype._ptr):
- x = llmemory.cast_ptr_to_adr(x)
- if x.ptr:
- try:
- container = x.ptr._obj._normalizedcontainer()
- return '* %s' % (container._TYPE._short_name(),)
- except AttributeError:
- return repr(x)
- else:
- return 'NULL'
- else:
- return repr(x)
- def repr_list(lst, types):
- res_l = []
- if types and types[-1] == 'varargs':
- types = types[:-1] + ('int',) * (len(lst) - len(types) + 1)
- assert len(types) == len(lst)
- for elem, tp in zip(lst, types):
- if isinstance(elem, Constant):
- res_l.append('(%s)' % repr1(elem, tp))
- else:
- res_l.append(repr1(elem, tp))
- return '[%s]' % (', '.join(res_l))
- def repr1(x, tp):
- if tp == "intorptr":
- TYPE = lltype.typeOf(x)
- if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
- tp = "ref"
- else:
- tp = "int"
- if tp == 'int':
- return str(x)
- elif tp == 'void':
- return '---'
- elif tp == 'ref':
- if not x:
- return '(* None)'
- if isinstance(x, int):
- # XXX normalize?
- ptr = str(llmemory.cast_int_to_adr(x))
- elif isinstance(ootype.typeOf(x), ootype.OOType):
- return repr(x)
- else:
- if getattr(x, '_fake', None):
- return repr(x)
- if lltype.typeOf(x) == llmemory.GCREF:
- TP = lltype.Ptr(lltype.typeOf(x._obj.container))
- ptr = lltype.cast_opaque_ptr(TP, x)
- else:
- ptr = x
- try:
- container = ptr._obj._normalizedcontainer()
- return '(* %s)' % (container._TYPE._short_name(),)
- except AttributeError:
- return '(%r)' % (ptr,)
- elif tp == 'bool':
- assert x == 0 or x == 1
- return str(bool(x))
- #elif tp == 'fieldname':
- # return str(symbolic.TokenToField[x...][1])
- elif tp == 'float':
- return str(x)
- else:
- raise NotImplementedError("tp = %s" % tp)
- _variables = []
- def compile_start():
- del _variables[:]
- return _to_opaque(CompiledLoop())
- def mark_as_free(loop):
- loop = _from_opaque(loop)
- assert not loop.has_been_freed
- loop.has_been_freed = True
- def compile_start_int_var(loop):
- return compile_start_ref_var(loop, lltype.Signed)
- def compile_start_float_var(loop):
- return compile_start_ref_var(loop, longlong.FLOATSTORAGE)
- def compile_start_ref_var(loop, TYPE):
- loop = _from_opaque(loop)
- assert not loop.operations
- v = Variable()
- v.concretetype = TYPE
- loop.inputargs.append(v)
- r = len(_variables)
- _variables.append(v)
- return r
- def compile_started_vars(clt):
- if not hasattr(clt, '_debug_argtypes'): # only when compiling the loop
- argtypes = [v.concretetype for v in _variables]
- try:
- clt._debug_argtypes = argtypes
- except AttributeError: # when 'clt' is actually a translated
- pass # GcStruct
- def compile_add(loop, opnum):
- loop = _from_opaque(loop)
- loop.operations.append(Operation(opnum))
- def compile_add_descr(loop, ofs, type, arg_types, extrainfo, width):
- from pypy.jit.backend.llgraph.runner import Descr
- loop = _from_opaque(loop)
- op = loop.operations[-1]
- assert isinstance(type, str) and len(type) == 1
- op.descr = Descr(ofs, type, arg_types=arg_types, extrainfo=extrainfo, width=width)
- def compile_add_descr_arg(loop, ofs, type, arg_types):
- from pypy.jit.backend.llgraph.runner import Descr
- loop = _from_opaque(loop)
- op = loop.operations[-1]
- assert isinstance(type, str) and len(type) == 1
- op.args.append(Descr(ofs, type, arg_types=arg_types))
- def compile_add_loop_token(loop, descr):
- if we_are_translated():
- raise ValueError("CALL_ASSEMBLER not supported")
- loop = _from_opaque(loop)
- op = loop.operations[-1]
- op.descr = weakref.ref(descr)
- TARGET_TOKENS = weakref.WeakKeyDictionary()
- def compile_add_target_token(loop, descr, clt):
- # here, 'clt' is the compiled_loop_token of the original loop that
- # we are compiling
- loop = _from_opaque(loop)
- op = loop.operations[-1]
- descrobj = _normalize(descr)
- TARGET_TOKENS[descrobj] = loop, len(loop.operations), op.args, clt
- def compile_add_var(loop, intvar):
- loop = _from_opaque(loop)
- op = loop.operations[-1]
- op.args.append(_variables[intvar])
- def compile_add_int_const(loop, value):
- compile_add_ref_const(loop, value, lltype.Signed)
- def compile_add_float_const(loop, value):
- compile_add_ref_const(loop, value, longlong.FLOATSTORAGE)
- def compile_add_ref_const(loop, value, TYPE):
- loop = _from_opaque(loop)
- const = Constant(value)
- const.concretetype = TYPE
- op = loop.operations[-1]
- op.args.append(const)
- def compile_add_int_result(loop):
- return compile_add_ref_result(loop, lltype.Signed)
- def compile_add_float_result(loop):
- return compile_add_ref_result(loop, longlong.FLOATSTORAGE)
- def compile_add_ref_result(loop, TYPE):
- loop = _from_opaque(loop)
- v = Variable()
- v.concretetype = TYPE
- op = loop.operations[-1]
- op.result = v
- r = len(_variables)
- _variables.append(v)
- return r
- def compile_add_jump_target(loop, targettoken, source_clt):
- loop = _from_opaque(loop)
- descrobj = _normalize(targettoken)
- (loop_target, target_opindex, target_inputargs, target_clt
- ) = TARGET_TOKENS[descrobj]
- #
- try:
- assert source_clt._debug_argtypes == target_clt._debug_argtypes
- except AttributeError: # when translated
- pass
- #
- op = loop.operations[-1]
- op.jump_target = loop_target
- op.jump_target_opindex = target_opindex
- op.jump_target_inputargs = target_inputargs
- assert op.opnum == rop.JUMP
- assert [v.concretetype for v in op.args] == (
- [v.concretetype for v in target_inputargs])
- #
- if loop_target == loop:
- log.info("compiling new loop")
- else:
- log.info("compiling new bridge")
- def compile_add_guard_jump_target(loop, loop_target):
- loop = _from_opaque(loop)
- loop_target = _from_opaque(loop_target)
- op = loop.operations[-1]
- assert op.is_guard()
- op.jump_target = loop_target
- def compile_add_fail(loop, fail_index):
- loop = _from_opaque(loop)
- index = len(loop.operations)-1
- op = loop.operations[index]
- op.fail_index = fail_index
- return index
- def compile_add_fail_arg(loop, intvar):
- loop = _from_opaque(loop)
- op = loop.operations[-1]
- if op.fail_args is None:
- op.fail_args = []
- if intvar == -1:
- op.fail_args.append(None)
- else:
- op.fail_args.append(_variables[intvar])
- def compile_redirect_fail(old_loop, old_index, new_loop):
- old_loop = _from_opaque(old_loop)
- new_loop = _from_opaque(new_loop)
- guard_op = old_loop.operations[old_index]
- assert guard_op.is_guard()
- guard_op.jump_target = new_loop
- # check that the bridge's inputargs are of the correct number and
- # kind for the guard
- if guard_op.fail_args is not None:
- argkinds = [v.concretetype for v in guard_op.fail_args if v]
- else:
- argkinds = []
- assert argkinds == [v.concretetype for v in new_loop.inputargs]
- # ------------------------------
- class Frame(object):
- OPHANDLERS = [None] * (rop._LAST+1)
- def __init__(self, cpu):
- self.verbose = False
- self.cpu = cpu
- self.opindex = 1
- self._forced = False
- self._may_force = -1
- def getenv(self, v):
- from pypy.jit.backend.llgraph.runner import Descr
- if isinstance(v, Constant):
- return v.value
- elif isinstance(v, Descr):
- return v
- else:
- return self.env[v]
- def _populate_fail_args(self, op, skip=None):
- fail_args = []
- if op.fail_args:
- for fail_arg in op.fail_args:
- if fail_arg is None:
- fail_args.append(None)
- elif fail_arg is skip:
- fail_args.append(fail_arg.concretetype._defl())
- else:
- fail_args.append(self.getenv(fail_arg))
- self.fail_args = fail_args
- self.fail_index = op.fail_index
- def execute(self):
- """Execute all operations in a loop,
- possibly following to other loops as well.
- """
- global _last_exception
- assert _last_exception is None, "exception left behind"
- verbose = True
- self.opindex = 0
- while True:
- assert not self.loop.has_been_freed
- op = self.loop.operations[self.opindex]
- args = [self.getenv(v) for v in op.args]
- if not op.is_final():
- try:
- result = self.execute_operation(op.opnum, args, op.descr,
- verbose)
- except GuardFailed:
- assert op.is_guard()
- _stats.exec_conditional_jumps += 1
- if op.jump_target is not None:
- # a patched guard, pointing to further code
- if op.fail_args:
- args = [self.getenv(v) for v in op.fail_args if v]
- else:
- args = []
- assert len(op.jump_target.inputargs) == len(args)
- self.env = dict(zip(op.jump_target.inputargs, args))
- self.loop = op.jump_target
- self.opindex = 0
- continue
- else:
- self._populate_fail_args(op)
- # a non-patched guard
- if self.verbose:
- log.trace('failed: %s' % (
- ', '.join(map(str, fail_args)),))
- return op.fail_index
- #verbose = self.verbose
- assert (result is None) == (op.result is None)
- if op.result is not None:
- RESTYPE = op.result.concretetype
- if RESTYPE is lltype.Signed:
- x = self.as_int(result)
- elif RESTYPE is llmemory.GCREF:
- x = self.as_ptr(result)
- elif RESTYPE is ootype.Object:
- x = self.as_object(result)
- elif RESTYPE is longlong.FLOATSTORAGE:
- x = self.as_floatstorage(result)
- else:
- raise Exception("op.result.concretetype is %r"
- % (RESTYPE,))
- self.env[op.result] = x
- self.opindex += 1
- continue
- if op.opnum == rop.JUMP:
- inputargs = op.jump_target_inputargs
- assert len(inputargs) == len(args)
- self.env = dict(zip(inputargs, args))
- self.loop = op.jump_target
- self.opindex = op.jump_target_opindex
- _stats.exec_jumps += 1
- elif op.opnum == rop.FINISH:
- if self.verbose:
- log.trace('finished: %s' % (
- ', '.join(map(str, args)),))
- self.fail_args = args
- return op.fail_index
- else:
- assert 0, "unknown final operation %d" % (op.opnum,)
- def execute_operation(self, opnum, values, descr, verbose):
- """Execute a single operation.
- """
- ophandler = self.OPHANDLERS[opnum]
- if ophandler is None:
- self._define_impl(opnum)
- ophandler = self.OPHANDLERS[opnum]
- assert ophandler is not None, "missing impl for op %d" % opnum
- opname = resoperation.opname[opnum].lower()
- exec_counters = _stats.exec_counters
- exec_counters[opname] = exec_counters.get(opname, 0) + 1
- for i in range(len(values)):
- if isinstance(values[i], ComputedIntSymbolic):
- values[i] = values[i].compute_fn()
- res = NotImplemented
- try:
- res = ophandler(self, descr, *values)
- finally:
- if 0: # if verbose:
- argtypes, restype = TYPES[opname]
- if res is None:
- resdata = ''
- elif res is NotImplemented:
- resdata = '*fail*'
- else:
- resdata = '-> ' + repr1(res, restype)
- # fish the types
- log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes),
- resdata))
- return res
- def as_int(self, x):
- return cast_to_int(x)
- def as_ptr(self, x):
- return cast_to_ptr(x)
- def as_object(self, x):
- return ootype.cast_to_object(x)
- def as_floatstorage(self, x):
- return cast_to_floatstorage(x)
- def log_progress(self):
- count = sum(_stats.exec_counters.values())
- count_jumps = _stats.exec_jumps
- log.trace('ran %d operations, %d jumps' % (count, count_jumps))
- # ----------
- @classmethod
- def _define_impl(cls, opnum):
- opname = resoperation.opname[opnum]
- try:
- op = getattr(cls, 'op_' + opname.lower()) # op_guard_true etc.
- except AttributeError:
- try:
- impl = globals()['do_' + opname.lower()] # do_arraylen_gc etc.
- def op(self, descr, *args):
- if descr is None:
- return impl(*args)
- else:
- return impl(descr, *args)
- except KeyError:
- op = cls._make_impl_from_blackhole_interp(opname)
- cls.OPHANDLERS[opnum] = op
- @classmethod
- def _make_impl_from_blackhole_interp(cls, opname):
- from pypy.jit.metainterp.blackhole import BlackholeInterpreter
- name = 'bhimpl_' + opname.lower()
- func = BlackholeInterpreter.__dict__[name]
- for argtype in func.argtypes:
- assert argtype in ('i', 'r', 'f')
- #
- def _op_default_implementation(self, descr, *args):
- # for all operations implemented in the blackhole interpreter
- return func(*args)
- #
- return _op_default_implementation
- def op_label(self, _, *args):
- op = self.loop.operations[self.opindex]
- assert op.opnum == rop.LABEL
- assert len(op.args) == len(args)
- newenv = {}
- for v, value in zip(op.args, args):
- newenv[v] = value
- self.env = newenv
- def op_debug_merge_point(self, _, *args):
- from pypy.jit.metainterp.warmspot import get_stats
- try:
- stats = get_stats()
- except AttributeError:
- pass
- else:
- stats.add_merge_point_location(args[1:])
- pass
- def op_guard_true(self, _, value):
- if not value:
- raise GuardFailed
- def op_guard_false(self, _, value):
- if value:
- raise GuardFailed
- op_guard_nonnull = op_guard_true
- op_guard_isnull = op_guard_false
- def op_guard_class(self, _, value, expected_class):
- value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value)
- expected_class = llmemory.cast_adr_to_ptr(
- llmemory.cast_int_to_adr(expected_class),
- rclass.CLASSTYPE)
- if value.typeptr != expected_class:
- raise GuardFailed
- def op_guard_nonnull_class(self, _, value, expected_class):
- if not value:
- raise GuardFailed
- self.op_guard_class(_, value, expected_class)
- def op_guard_value(self, _, value, expected_value):
- if value != expected_value:
- raise GuardFailed
- def op_guard_no_exception(self, _):
- if _last_exception:
- raise GuardFailed
- def _check_exception(self, expected_exception):
- global _last_exception
- expected_exception = self._cast_exception(expected_exception)
- assert expected_exception
- exc = _last_exception
- if exc:
- got = exc.args[0]
- # exact match!
- if got != expected_exception:
- return False
- return True
- else:
- return False
- def _cast_exception(self, exception):
- return llmemory.cast_adr_to_ptr(
- llmemory.cast_int_to_adr(exception),
- rclass.CLASSTYPE)
- def _issubclass(self, cls1, cls2):
- return rclass.ll_issubclass(cls1, cls2)
- def op_guard_exception(self, _, expected_exception):
- global _last_exception
- if not self._check_exception(expected_exception):
- raise GuardFailed
- res = _last_exception[1]
- _last_exception = None
- return res
- def op_guard_no_overflow(self, _):
- flag = self.overflow_flag
- del self.overflow_flag
- if flag:
- raise GuardFailed
- def op_guard_overflow(self, _):
- flag = self.overflow_flag
- del self.overflow_flag
- if not flag:
- raise GuardFailed
- def op_int_add_ovf(self, _, x, y):
- try:
- z = ovfcheck(x + y)
- except OverflowError:
- ovf = True
- z = 0
- else:
- ovf = False
- self.overflow_flag = ovf
- return z
- def op_int_sub_ovf(self, _, x, y):
- try:
- z = ovfcheck(x - y)
- except OverflowError:
- ovf = True
- z = 0
- else:
- ovf = False
- self.overflow_flag = ovf
- return z
- def op_int_mul_ovf(self, _, x, y):
- try:
- z = ovfcheck(x * y)
- except OverflowError:
- ovf = True
- z = 0
- else:
- ovf = False
- self.overflow_flag = ovf
- return z
- def op_keepalive(self, _, x):
- pass
- # ----------
- # delegating to the builtins do_xxx() (done automatically for simple cases)
- def op_getarrayitem_gc(self, arraydescr, array, index):
- if arraydescr.typeinfo == REF:
- return do_getarrayitem_gc_ptr(array, index)
- elif arraydescr.typeinfo == INT:
- return do_getarrayitem_gc_int(array, index)
- elif arraydescr.typeinfo == FLOAT:
- return do_getarrayitem_gc_float(array, index)
- else:
- raise NotImplementedError
- op_getarrayitem_gc_pure = op_getarrayitem_gc
- def op_getarrayitem_raw(self, arraydescr, array, index):
- if arraydescr.typeinfo == REF:
- raise NotImplementedError("getarrayitem_raw -> gcref")
- elif arraydescr.typeinfo == INT:
- return do_getarrayitem_raw_int(array, index)
- elif arraydescr.typeinfo == FLOAT:
- return do_getarrayitem_raw_float(array, index)
- else:
- raise NotImplementedError
- op_getarrayitem_raw_pure = op_getarrayitem_raw
- def op_getfield_gc(self, fielddescr, struct):
- if fielddescr.typeinfo == REF:
- return do_getfield_gc_ptr(struct, fielddescr.ofs)
- elif fielddescr.typeinfo == INT:
- return do_getfield_gc_int(struct, fielddescr.ofs)
- elif fielddescr.typeinfo == FLOAT:
- return do_getfield_gc_float(struct, fielddescr.ofs)
- else:
- raise NotImplementedError
- op_getfield_gc_pure = op_getfield_gc
- def op_getfield_raw(self, fielddescr, struct):
- if fielddescr.typeinfo == REF:
- return do_getfield_raw_ptr(struct, fielddescr.ofs)
- elif fielddescr.typeinfo == INT:
- return do_getfield_raw_int(struct, fielddescr.ofs)
- elif fielddescr.typeinfo == FLOAT:
- return do_getfield_raw_float(struct, fielddescr.ofs)
- else:
- raise NotImplementedError
- op_getfield_raw_pure = op_getfield_raw
- def op_new(self, size):
- return do_new(size.ofs)
- def op_new_with_vtable(self, descr, vtable):
- assert descr is None
- descr = heaptracker.vtable2descr(self.cpu, vtable)
- result = do_new(descr.ofs)
- value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result)
- value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable)
- return result
- def op_setarrayitem_gc(self, arraydescr, array, index, newvalue):
- if arraydescr.typeinfo == REF:
- do_setarrayitem_gc_ptr(array, index, newvalue)
- elif arraydescr.typeinfo == INT:
- do_setarrayitem_gc_int(array, index, newvalue)
- elif arraydescr.typeinfo == FLOAT:
- do_setarrayitem_gc_float(array, index, newvalue)
- else:
- raise NotImplementedError
- def op_setarrayitem_raw(self, arraydescr, array, index, newvalue):
- if arraydescr.typeinfo == REF:
- raise NotImplementedError("setarrayitem_raw <- gcref")
- elif arraydescr.typeinfo == INT:
- do_setarrayitem_raw_int(array, index, newvalue)
- elif arraydescr.typeinfo == FLOAT:
- do_setarrayitem_raw_float(array, index, newvalue)
- else:
- raise NotImplementedError
- def op_getinteriorfield_gc(self, descr, array, index):
- if descr.typeinfo == REF:
- return do_getinteriorfield_gc_ptr(array, index, descr.ofs)
- elif descr.typeinfo == INT:
- return do_getinteriorfield_gc_int(array, index, descr.ofs)
- elif descr.typeinfo == FLOAT:
- return do_getinteriorfield_gc_float(array, index, descr.ofs)
- else:
- raise NotImplementedError
- def op_getinteriorfield_raw(self, descr, array, index):
- if descr.typeinfo == REF:
- return do_getinteriorfield_raw_ptr(array, index, descr.width, descr.ofs)
- elif descr.typeinfo == INT:
- return do_getinteriorfield_raw_int(array, index, descr.width, descr.ofs)
- elif descr.typeinfo == FLOAT:
- return do_getinteriorfield_raw_float(array, index, descr.width, descr.ofs)
- else:
- raise NotImplementedError
- def op_setinteriorfield_gc(self, descr, array, index, newvalue):
- if descr.typeinfo == REF:
- return do_setinteriorfield_gc_ptr(array, index, descr.ofs,
- newvalue)
- elif descr.typeinfo == INT:
- return do_setinteriorfield_gc_int(array, index, descr.ofs,
- newvalue)
- elif descr.typeinfo == FLOAT:
- return do_setinteriorfield_gc_float(array, index, descr.ofs,
- newvalue)
- else:
- raise NotImplementedError
- def op_setinteriorfield_raw(self, descr, array, index, newvalue):
- if descr.typeinfo == REF:
- return do_setinteriorfield_raw_ptr(array, index, newvalue, descr.width, descr.ofs)
- elif descr.typeinfo == INT:
- return do_setinteriorfield_raw_int(array, index, newvalue, descr.width, descr.ofs)
- elif descr.typeinfo == FLOAT:
- return do_setinteriorfield_raw_float(array, index, newvalue, descr.width, descr.ofs)
- else:
- raise NotImplementedError
- def op_setfield_gc(self, fielddescr, struct, newvalue):
- if fielddescr.typeinfo == REF:
- do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
- elif fielddescr.typeinfo == INT:
- do_setfield_gc_int(struct, fielddescr.ofs, newvalue)
- elif fielddescr.typeinfo == FLOAT:
- do_setfield_gc_float(struct, fielddescr.ofs, newvalue)
- else:
- raise NotImplementedError
- def op_setfield_raw(self, fielddescr, struct, newvalue):
- if fielddescr.typeinfo == REF:
- do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue)
- elif fielddescr.typeinfo == INT:
- do_setfield_raw_int(struct, fielddescr.ofs, newvalue)
- elif fielddescr.typeinfo == FLOAT:
- do_setfield_raw_float(struct, fielddescr.ofs, newvalue)
- else:
- raise NotImplementedError
- def op_call(self, calldescr, func, *args):
- return self._do_call(calldescr, func, args, call_with_llptr=False)
- def op_call_release_gil(self, calldescr, func, *args):
- return self._do_call(calldescr, func, args, call_with_llptr=True)
- def _do_call(self, calldescr, func, args, call_with_llptr):
- global _last_exception
- assert _last_exception is None, "exception left behind"
- assert _call_args_i == _call_args_r == _call_args_f == []
- args_in_order = []
- for x in args:
- T = lltype.typeOf(x)
- if T is lltype.Signed:
- args_in_order.append('i')
- _call_args_i.append(x)
- elif T == llmemory.GCREF:
- args_in_order.append('r')
- _call_args_r.append(x)
- elif T is longlong.FLOATSTORAGE:
- args_in_order.append('f')
- _call_args_f.append(x)
- else:
- raise TypeError(x)
- try:
- return _do_call_common(func, args_in_order, calldescr,
- call_with_llptr)
- except LLException, lle:
- _last_exception = lle
- d = {'v': None,
- REF: lltype.nullptr(llmemory.GCREF.TO),
- INT: 0,
- FLOAT: 0.0}
- return d[calldescr.typeinfo]
- def op_cond_call_gc_wb(self, descr, a, b):
- py.test.skip("cond_call_gc_wb not supported")
- def op_cond_call_gc_wb_array(self, descr, a, b, c):
- py.test.skip("cond_call_gc_wb_array not supported")
- def op_oosend(self, descr, obj, *args):
- raise NotImplementedError("oosend for lltype backend??")
- op_oosend_pure = op_oosend
- def op_new_array(self, arraydescr, count):
- return do_new_array(arraydescr.ofs, count)
- def op_force_token(self, descr):
- opaque_frame = _to_opaque(self)
- return llmemory.cast_ptr_to_adr(opaque_frame)
- def op_read_timestamp(self, descr):
- return read_timestamp()
- def op_call_may_force(self, calldescr, func, *args):
- assert not self._forced
- self._may_force = self.opindex
- try:
- return self.op_call(calldescr, func, *args)
- finally:
- self._may_force = -1
- def op_call_assembler(self, wref_loop_token, *args):
- if we_are_translated():
- raise ValueError("CALL_ASSEMBLER not supported")
- return self._do_call_assembler(wref_loop_token, *args)
- def _do_call_assembler(self, wref_loop_token, *args):
- global _last_exception
- loop_token = wref_loop_token()
- assert loop_token, "CALL_ASSEMBLER to a target that already died"
- ctl = loop_token.compiled_loop_token
- if hasattr(ctl, 'redirected'):
- return self._do_call_assembler(ctl.redirected, *args)
- assert not self._forced
- self._may_force = self.opindex
- try:
- inpargs = _from_opaque(ctl.compiled_version).inputargs
- assert len(inpargs) == len(args)
- for i, inparg in enumerate(inpargs):
- TYPE = inparg.concretetype
- if TYPE is lltype.Signed:
- set_future_value_int(i, args[i])
- elif isinstance(TYPE, lltype.Ptr):
- set_future_value_ref(i, args[i])
- elif TYPE is longlong.FLOATSTORAGE:
- set_future_value_float(i, args[i])
- else:
- raise Exception("Nonsense type %s" % TYPE)
- failindex = self.cpu._execute_token(loop_token)
- jd = loop_token.outermost_jitdriver_sd
- assert jd is not None, ("call_assembler(): the loop_token needs "
- "to have 'outermost_jitdriver_sd'")
- if jd.index_of_virtualizable != -1:
- vable = args[jd.index_of_virtualizable]
- else:
- vable = lltype.nullptr(llmemory.GCREF.TO)
- #
- # Emulate the fast path
- if failindex == self.cpu.done_with_this_frame_int_v:
- reset_vable(jd, vable)
- return self.cpu.get_latest_value_int(0)
- if failindex == self.cpu.done_with_this_frame_ref_v:
- reset_vable(jd, vable)
- return self.cpu.get_latest_value_ref(0)
- if failindex == self.cpu.done_with_this_frame_float_v:
- reset_vable(jd, vable)
- return self.cpu.get_latest_value_float(0)
- if failindex == self.cpu.done_with_this_frame_void_v:
- reset_vable(jd, vable)
- return None
- #
- assembler_helper_ptr = jd.assembler_helper_adr.ptr # fish
- try:
- return assembler_helper_ptr(failindex, vable)
- except LLException, lle:
- assert _last_exception is None, "exception left behind"
- _last_exception = lle
- # fish op
- op = self.loop.operations[self.opindex]
- if op.result is not None:
- return 0
- finally:
- self._may_force = -1
- def op_guard_not_forced(self, descr):
- forced = self._forced
- self._forced = False
- if forced:
- raise GuardFailed
- def op_guard_not_invalidated(self, descr):
- if self.loop.invalid:
- raise GuardFailed
- class OOFrame(Frame):
- OPHANDLERS = [None] * (rop._LAST+1)
- def op_new_with_vtable(self, descr, vtable):
- assert descr is None
- typedescr = get_class_size(self.memocast, vtable)
- return ootype.cast_to_object(ootype.new(typedescr.TYPE))
- def op_new_array(self, typedescr, count):
- res = ootype.oonewarray(typedescr.ARRAY, count)
- return ootype.cast_to_object(res)
- def op_getfield_gc(self, fielddescr, obj):
- TYPE = fielddescr.TYPE
- fieldname = fielddescr.fieldname
- _, T = TYPE._lookup_field(fieldname)
- obj = ootype.cast_from_object(TYPE, obj)
- res = getattr(obj, fieldname)
- if isinstance(T, ootype.OOType):
- return ootype.cast_to_object(res)
- return res
- op_getfield_gc_pure = op_getfield_gc
- def op_setfield_gc(self, fielddescr, obj, newvalue):
- TYPE = fielddescr.TYPE
- fieldname = fielddescr.fieldname
- _, T = TYPE._lookup_field(fieldname)
- obj = ootype.cast_from_object(TYPE, obj)
- if isinstance(ootype.typeOf(newvalue), ootype.OOType):
- newvalue = ootype.cast_from_object(T, newvalue)
- elif isinstance(T, lltype.Primitive):
- newvalue = lltype.cast_primitive(T, newvalue)
- setattr(obj, fieldname, newvalue)
- def op_getarrayitem_gc(self, typedescr, obj, index):
- array = ootype.cast_from_object(typedescr.ARRAY, obj)
- res = array.ll_getitem_fast(index)
- if isinstance(typedescr.TYPE, ootype.OOType):
- return ootype.cast_to_object(res)
- return res
- op_getarrayitem_gc_pure = op_getarrayitem_gc
- def op_setarrayitem_gc(self, typedescr, obj, index, objnewvalue):
- array = ootype.cast_from_object(typedescr.ARRAY, obj)
- if ootype.typeOf(objnewvalue) == ootype.Object:
- newvalue = ootype.cast_from_object(typedescr.TYPE, objnewvalue)
- else:
- newvalue = objnewvalue
- array.ll_setitem_fast(index, newvalue)
- def op_arraylen_gc(self, typedescr, obj):
- array = ootype.cast_from_object(typedescr.ARRAY, obj)
- return array.ll_length()
- def op_call(self, calldescr, func, *args):
- sm = ootype.cast_from_object(calldescr.FUNC, func)
- newargs = cast_call_args(calldescr.FUNC.ARGS, args)
- res = call_maybe_on_top_of_llinterp(sm, newargs)
- if isinstance(calldescr.FUNC.RESULT, ootype.OOType):
- return ootype.cast_to_object(res)
- return res
- def op_oosend(self, descr, obj, *args):
- METH = descr.METH
- obj = ootype.cast_from_object(descr.SELFTYPE, obj)
- meth = getattr(obj, descr.methname)
- newargs = cast_call_args(METH.ARGS, args)
- res = call_maybe_on_top_of_llinterp(meth, newargs)
- if isinstance(METH.RESULT, ootype.OOType):
- return ootype.cast_to_object(res)
- return res
- op_oosend_pure = op_oosend
- def op_guard_class(self, _, value, expected_class):
- value = ootype.cast_from_object(ootype.ROOT, value)
- expected_class = ootype.cast_from_object(ootype.Class, expected_class)
- if ootype.classof(value) is not expected_class:
- raise GuardFailed
- def op_runtimenew(self, _, cls):
- cls = ootype.cast_from_object(ootype.Class, cls)
- res = ootype.runtimenew(cls)
- return ootype.cast_to_object(res)
- def op_instanceof(self, typedescr, obj):
- inst = ootype.cast_from_object(ootype.ROOT, obj)
- return ootype.instanceof(inst, typedescr.TYPE)
- def op_subclassof(self, _, obj1, obj2):
- cls1 = ootype.cast_from_object(ootype.Class, obj1)
- cls2 = ootype.cast_from_object(ootype.Class, obj2)
- return ootype.subclassof(cls1, cls2)
- def _cast_exception(self, exception):
- return ootype.cast_from_object(ootype.Class, exception)
- def _issubclass(self, cls1, cls2):
- return ootype.subclassof(cls1, cls2)
- # ____________________________________________________________
- def cast_to_int(x):
- TP = lltype.typeOf(x)
- if isinstance(TP, lltype.Ptr):
- return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x))
- if TP == llmemory.Address:
- return heaptracker.adr2int(x)
- if TP is lltype.SingleFloat:
- return longlong.singlefloat2int(x)
- return lltype.cast_primitive(lltype.Signed, x)
- def cast_from_int(TYPE, x):
- if isinstance(TYPE, lltype.Ptr):
- if isinstance(x, (int, long, llmemory.AddressAsInt)):
- x = llmemory.cast_int_to_adr(x)
- if TYPE is rffi.VOIDP or (
- hasattr(TYPE.TO, '_hints') and
- TYPE.TO._hints.get("uncast_on_llgraph")):
- # assume that we want a "C-style" cast, without typechecking the value
- return rffi.cast(TYPE, x)
- return llmemory.cast_adr_to_ptr(x, TYPE)
- elif TYPE == llmemory.Address:
- if isinstance(x, (int, long, llmemory.AddressAsInt)):
- x = llmemory.cast_int_to_adr(x)
- assert lltype.typeOf(x) == llmemory.Address
- return x
- elif TYPE is lltype.SingleFloat:
- assert lltype.typeOf(x) is lltype.Signed
- return longlong.int2singlefloat(x)
- else:
- if lltype.typeOf(x) == llmemory.Address:
- x = heaptracker.adr2int(x)
- return lltype.cast_primitive(TYPE, x)
- def cast_to_ptr(x):
- assert isinstance(lltype.typeOf(x), lltype.Ptr)
- return lltype.cast_opaque_ptr(llmemory.GCREF, x)
- def cast_from_ptr(TYPE, x):
- return lltype.cast_opaque_ptr(TYPE, x)
- def cast_to_floatstorage(x):
- if isinstance(x, float):
- return longlong.getfloatstorage(x) # common case
- if IS_32_BIT:
- assert longlong.supports_longlong
- if isinstance(x, r_longlong):
- return x
- if isinstance(x, r_ulonglong):
- return rffi.cast(lltype.SignedLongLong, x)
- raise TypeError(type(x))
- def cast_from_floatstorage(TYPE, x):
- assert isinstance(x, longlong.r_float_storage)
- if TYPE is lltype.Float:
- return longlong.getrealfloat(x)
- if longlong.is_longlong(TYPE):
- return rffi.cast(TYPE, x)
- raise TypeError(TYPE)
- def new_frame(is_oo, cpu):
- if is_oo:
- frame = OOFrame(cpu)
- else:
- frame = Frame(cpu)
- return _to_opaque(frame)
- _future_values = []
- def frame_clear(frame, loop):
- frame = _from_opaque(frame)
- loop = _from_opaque(loop)
- assert len(_future_values) == len(loop.inputargs)
- frame.loop = loop
- frame.env = {}
- for i in range(len(loop.inputargs)):
- expected_type = loop.inputargs[i].concretetype
- assert lltype.typeOf(_future_values[i]) == expected_type
- frame.env[loop.inputargs[i]] = _future_values[i]
- del _future_values[:]
- def set_future_value_int(index, value):
- assert lltype.typeOf(value) is lltype.Signed
- set_future_value_ref(index, value)
- def set_future_value_float(index, value):
- assert isinstance(value, longlong.r_float_storage)
- set_future_value_ref(index, value)
- def set_future_value_ref(index, value):
- del _future_values[index:]
- assert len(_future_values) == index
- _future_values.append(value)
- def frame_execute(frame):
- frame = _from_opaque(frame)
- if frame.verbose:
- values = [frame.env[v] for v in frame.loop.inputargs]
- log.trace('Entering CPU frame <- %r' % (values,))
- try:
- result = frame.execute()
- if frame.verbose:
- log.trace('Leaving CPU frame -> #%d' % (result,))
- frame.log_progress()
- except Exception, e:
- log.ERROR('%s in CPU frame: %s' % (e.__class__.__name__, e))
- # Only invoke pdb when io capturing is not on otherwise py.io complains.
- if py.test.config.option.capture == 'no':
- import sys, pdb
- pdb.post_mortem(sys.exc_info()[2])
- raise
- del frame.env
- return result
- def frame_int_getvalue(frame, num):
- frame = _from_opaque(frame)
- assert num >= 0
- x = frame.fail_args[num]
- assert lltype.typeOf(x) is lltype.Signed
- return x
- def frame_float_getvalue(frame, num):
- frame = _from_opaque(frame)
- assert num >= 0
- x = frame.fail_args[num]
- assert lltype.typeOf(x) is longlong.FLOATSTORAGE
- return x
- def frame_ptr_getvalue(frame, num):
- frame = _from_opaque(frame)
- assert num >= 0
- x = frame.fail_args[num]
- assert lltype.typeOf(x) == llmemory.GCREF
- return x
- def frame_get_value_count(frame):
- frame = _from_opaque(frame)
- return len(frame.fail_args)
- def frame_clear_latest_values(frame, count):
- frame = _from_opaque(frame)
- assert count == len(frame.fail_args)
- del frame.fail_args
- _last_exception = None
- def grab_exc_value():
- global _last_exception
- if _last_exception is not None:
- result = _last_exception.args[1]
- _last_exception = None
- return lltype.cast_opaque_ptr(llmemory.GCREF, result)
- else:
- return lltype.nullptr(llmemory.GCREF.TO)
- ##_pseudo_exceptions = {}
- ##def _get_error(Class):
- ## if _llinterp.typer is not None:
- ## llframe = _llinterp.frame_class(None, None, _llinterp)
- ## try:
- ## llframe.make_llexception(Class())
- ## except LLException, e:
- ## return e
- ## else:
- ## assert 0, "should have raised"
- ## else:
- ## # for tests, a random emulated ll_inst will do
- ## if Class not in _pseudo_exceptions:
- ## ll_inst = lltype.malloc(rclass.OBJECT, zero=True)
- ## ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
- ## immortal=True)
- ## _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst)
- ## return _pseudo_exceptions[Class]
- ##def get_overflow_error_value():
- ## return lltype.cast_opaque_ptr(llmemory.GCREF,
- ## _get_error(OverflowError).args[1])
- def force(opaque_frame):
- frame = _from_opaque(opaque_frame)
- assert not frame._forced
- frame._forced = True
- assert frame._may_force >= 0
- call_op = frame.loop.operations[frame._may_force]
- guard_op = frame.loop.operations[frame._may_force+1]
- opnum = call_op.opnum
- assert opnum == rop.CALL_MAY_FORCE or opnum == rop.CALL_ASSEMBLER
- frame._populate_fail_args(guard_op, skip=call_op.result)
- return frame.fail_index
- def get_forced_token_frame(force_token):
- opaque_frame = llmemory.cast_adr_to_ptr(force_token,
- lltype.Ptr(_TO_OPAQUE[Frame]))
- return opaque_frame
- def get_frame_forced_token(opaque_frame):
- return llmemory.cast_ptr_to_adr(opaque_frame)
- ##def cast_adr_to_int(memocast, adr):
- ## # xxx slow
- ## assert lltype.typeOf(adr) == llmemory.Address
- ## memocast = _from_opaque(memocast)
- ## addresses = memocast.addresses
- ## for i in xrange(len(addresses)-1, -1, -1):
- ## if addresses[i] == adr:
- ## return i
- ## i = len(addresses)
- ## addresses.append(adr)
- ## return i
- ##def cast_int_to_adr(memocast, int):
- ## memocast = _from_opaque(memocast)
- ## assert 0 <= int < len(memocast.addresses)
- ## return memocast.addresses[int]
- ##def get_class_size(memocast, vtable):
- ## memocast = _from_opaque(memocast)
- ## return memocast.vtable_to_size[vtable]
- ##def set_class_size(memocast, vtable, size):
- ## memocast = _from_opaque(memocast)
- ## memocast.vtable_to_size[vtable] = size
- class GuardFailed(Exception):
- pass
- # ____________________________________________________________
- def …
Large files files are truncated, but you can click here to view the full file