def effectinfo_from_writeanalyze(effects, cpu, extraeffect=EffectInfo.EF_CAN_RAISE, oopspecindex=EffectInfo.OS_NONE, can_invalidate=False): from pypy.translator.backendopt.writeanalyze import top_set if effects is top_set or extraeffect == EffectInfo.EF_RANDOM_EFFECTS: readonly_descrs_fields = None readonly_descrs_arrays = None write_descrs_fields = None write_descrs_arrays = None extraeffect = EffectInfo.EF_RANDOM_EFFECTS else: readonly_descrs_fields = [] readonly_descrs_arrays = [] write_descrs_fields = [] write_descrs_arrays = [] def add_struct(descrs_fields, (_, T, fieldname)): T = deref(T) if consider_struct(T, fieldname): descr = cpu.fielddescrof(T, fieldname) descrs_fields.append(descr) def add_array(descrs_arrays, (_, T)): ARRAY = deref(T) if consider_array(ARRAY): descr = cpu.arraydescrof(ARRAY) descrs_arrays.append(descr)
def effectinfo_from_writeanalyze(effects, cpu, extraeffect=EffectInfo.EF_CAN_RAISE, oopspecindex=EffectInfo.OS_NONE, can_invalidate=False): from pypy.translator.backendopt.writeanalyze import top_set if effects is top_set or extraeffect == EffectInfo.EF_RANDOM_EFFECTS: readonly_descrs_fields = None readonly_descrs_arrays = None write_descrs_fields = None write_descrs_arrays = None extraeffect = EffectInfo.EF_RANDOM_EFFECTS else: readonly_descrs_fields = [] readonly_descrs_arrays = [] write_descrs_fields = [] write_descrs_arrays = [] def add_struct(descrs_fields, (_, T, fieldname)): T = deref(T) if consider_struct(T, fieldname): descr = cpu.fielddescrof(T, fieldname) descrs_fields.append(descr) def add_array(descrs_arrays, (_, T)): ARRAY = deref(T) if consider_array(ARRAY): descr = cpu.arraydescrof(ARRAY) descrs_arrays.append(descr)
def test_quasi_immutable(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ["x", "y", "a?", "b?"] class B(A): pass def f(): a = A() a.x = 42 a.a = 142 b = B() b.x = 43 b.y = 41 b.a = 44 b.b = 45 return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) accessor = B_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_y": IR_IMMUTABLE, "inst_b": IR_QUASIIMMUTABLE} or accessor.fields == { "ox": IR_IMMUTABLE, "oy": IR_IMMUTABLE, "oa": IR_QUASIIMMUTABLE, "ob": IR_QUASIIMMUTABLE, } # for ootype found = [] for op in graph.startblock.operations: if op.opname == "jit_force_quasi_immutable": found.append(op.args[1].value) assert found == ["mutate_a", "mutate_a", "mutate_b"]
def test_quasi_immutable_array(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ["c?[*]"] class B(A): pass def f(): a = A() a.c = [3, 4, 5] return A() t, typer, graph = self.gengraph(f, []) A_TYPE = deref(graph.getreturnvar().concretetype) accessor = A_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_c": IR_QUASIIMMUTABLE_ARRAY} or accessor.fields == { "oc": IR_QUASIIMMUTABLE_ARRAY } # for ootype found = [] for op in graph.startblock.operations: if op.opname == "jit_force_quasi_immutable": found.append(op.args[1].value) assert found == ["mutate_c"]
def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res): key = (oopspec_name, tuple(ll_args), ll_res) try: return rtyper._builtin_func_for_spec_cache[key] except (KeyError, AttributeError): pass args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s)) if getattr(impl, 'need_result_type', False): bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))])) # mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() # if not hasattr(rtyper, '_builtin_func_for_spec_cache'): rtyper._builtin_func_for_spec_cache = {} rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT
def test_immutable_fields_subclass_2(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ["x"] def __init__(self, x): self.x = x class B(A): _immutable_fields_ = ["y"] def __init__(self, x, y): A.__init__(self, x) self.y = y def f(): return B(3, 5) t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) accessor = B_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_x": IR_IMMUTABLE, "inst_y": IR_IMMUTABLE} or accessor.fields == { "ox": IR_IMMUTABLE, "oy": IR_IMMUTABLE, } # for ootype
def test_quasi_immutable(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ['x', 'y', 'a?', 'b?'] class B(A): pass def f(): a = A() a.x = 42 a.a = 142 b = B() b.x = 43 b.y = 41 b.a = 44 b.b = 45 return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) accessor = B_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_y": IR_IMMUTABLE, "inst_b": IR_QUASIIMMUTABLE} or \ accessor.fields == {"ox": IR_IMMUTABLE, "oy": IR_IMMUTABLE, "oa": IR_QUASIIMMUTABLE, "ob": IR_QUASIIMMUTABLE} # for ootype found = [] for op in graph.startblock.operations: if op.opname == 'jit_force_quasi_immutable': found.append(op.args[1].value) assert found == ['mutate_a', 'mutate_a', 'mutate_b']
def test_immutable_fields_subclass_2(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ["x"] def __init__(self, x): self.x = x class B(A): _immutable_fields_ = ["y"] def __init__(self, x, y): A.__init__(self, x) self.y = y def f(): return B(3, 5) t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) accessor = B_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_x": IR_IMMUTABLE, "inst_y": IR_IMMUTABLE} or \ accessor.fields == {"ox": IR_IMMUTABLE, "oy": IR_IMMUTABLE} # for ootype
def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res): key = (oopspec_name, tuple(ll_args), ll_res) try: return rtyper._builtin_func_for_spec_cache[key] except (KeyError, AttributeError): pass args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if "." not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s)) if getattr(impl, "need_result_type", False): bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))])) # mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() # if not hasattr(rtyper, "_builtin_func_for_spec_cache"): rtyper._builtin_func_for_spec_cache = {} rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT
def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res, extra=None, extrakey=None): assert (extra is None) == (extrakey is None) key = (oopspec_name, tuple(ll_args), ll_res, extrakey) try: return rtyper._builtin_func_for_spec_cache[key] except (KeyError, AttributeError): pass args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s), extra) if getattr(impl, 'need_result_type', False): bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))])) # if hasattr(rtyper, 'annotator'): # regular case mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() else: # for testing only c_func = Constant(oopspec_name, lltype.Ptr(lltype.FuncType(ll_args, ll_res))) # if not hasattr(rtyper, '_builtin_func_for_spec_cache'): rtyper._builtin_func_for_spec_cache = {} rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT
def test_immutable_subclass_2(self): from pypy.jit.metainterp.typesystem import deref class A(object): pass class B(A): _immutable_ = True def f(): A() B().v = 123 return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) assert B_TYPE._hints["immutable"]
def effectinfo_from_writeanalyze(effects, cpu, forces_virtual_or_virtualizable=False): from pypy.translator.backendopt.writeanalyze import top_set if effects is top_set: return None readonly_descrs_fields = [] # readonly_descrs_arrays = [] --- not enabled for now write_descrs_fields = [] write_descrs_arrays = [] def add_struct(descrs_fields, (_, T, fieldname)): T = deref(T) if consider_struct(T, fieldname): descr = cpu.fielddescrof(T, fieldname) descrs_fields.append(descr)
def test_immutable_subclass_void(self): from pypy.jit.metainterp.typesystem import deref class A(object): pass class B(A): _immutable_ = True def myfunc(): pass def f(): A().f = myfunc # it's ok to add Void attributes to A B().v = 123 # even though only B is declared _immutable_ return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) assert B_TYPE._hints["immutable"]
def test_immutable_subclass_2(self): from pypy.jit.metainterp.typesystem import deref class A(object): pass class B(A): _immutable_ = True def f(): A() B().v = 123 return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) assert B_TYPE._hints["immutable"]
def effectinfo_from_writeanalyze(effects, cpu, extraeffect=EffectInfo.EF_CAN_RAISE, oopspecindex=EffectInfo.OS_NONE, can_invalidate=False): from pypy.translator.backendopt.writeanalyze import top_set if effects is top_set: return None readonly_descrs_fields = [] # readonly_descrs_arrays = [] --- not enabled for now write_descrs_fields = [] write_descrs_arrays = [] def add_struct(descrs_fields, (_, T, fieldname)): T = deref(T) if consider_struct(T, fieldname): descr = cpu.fielddescrof(T, fieldname) descrs_fields.append(descr)
def test_immutable_fields(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ["x", "y[*]"] def __init__(self, x, y): self.x = x self.y = y def f(): return A(3, []) t, typer, graph = self.gengraph(f, []) A_TYPE = deref(graph.getreturnvar().concretetype) accessor = A_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_x": IR_IMMUTABLE, "inst_y": IR_IMMUTABLE_ARRAY} or \ accessor.fields == {"ox": IR_IMMUTABLE, "oy": IR_IMMUTABLE_ARRAY} # for ootype
def test_immutable_fields(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ["x", "y[*]"] def __init__(self, x, y): self.x = x self.y = y def f(): return A(3, []) t, typer, graph = self.gengraph(f, []) A_TYPE = deref(graph.getreturnvar().concretetype) accessor = A_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_x" : "", "inst_y" : "[*]"} or \ accessor.fields == {"ox" : "", "oy" : "[*]"} # for ootype
def test_immutable_subclass_void(self): from pypy.jit.metainterp.typesystem import deref class A(object): pass class B(A): _immutable_ = True def myfunc(): pass def f(): A().f = myfunc # it's ok to add Void attributes to A B().v = 123 # even though only B is declared _immutable_ return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) assert B_TYPE._hints["immutable"]
def test_immutable_ok_inheritance_2(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ['v'] class B(A): _immutable_ = True def f(): A().v = 123 B().w = 456 return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) assert B_TYPE._hints["immutable"] try: A_TYPE = B_TYPE.super except AttributeError: A_TYPE = B_TYPE._superclass # for ootype accessor = A_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_v": IR_IMMUTABLE} or \ accessor.fields == {"ov": IR_IMMUTABLE} # for ootype
def test_quasi_immutable_array(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ['c?[*]'] class B(A): pass def f(): a = A() a.c = [3, 4, 5] return A() t, typer, graph = self.gengraph(f, []) A_TYPE = deref(graph.getreturnvar().concretetype) accessor = A_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_c": IR_QUASIIMMUTABLE_ARRAY} or \ accessor.fields == {"oc": IR_QUASIIMMUTABLE_ARRAY} # for ootype found = [] for op in graph.startblock.operations: if op.opname == 'jit_force_quasi_immutable': found.append(op.args[1].value) assert found == ['mutate_c']
def test_immutable_ok_inheritance_2(self): from pypy.jit.metainterp.typesystem import deref class A(object): _immutable_fields_ = ['v'] class B(A): _immutable_ = True def f(): A().v = 123 B().w = 456 return B() t, typer, graph = self.gengraph(f, []) B_TYPE = deref(graph.getreturnvar().concretetype) assert B_TYPE._hints["immutable"] try: A_TYPE = B_TYPE.super except AttributeError: A_TYPE = B_TYPE._superclass # for ootype accessor = A_TYPE._hints["immutable_fields"] assert accessor.fields == {"inst_v": IR_IMMUTABLE} or \ accessor.fields == {"ov": IR_IMMUTABLE} # for ootype
def __init__(self, warmrunnerdesc, VTYPEPTR): self.warmrunnerdesc = warmrunnerdesc cpu = warmrunnerdesc.cpu if cpu.ts.name == 'ootype': import py py.test.skip("ootype: fix virtualizables") self.cpu = cpu self.BoxArray = cpu.ts.BoxRef # while 'virtualizable2_accessor' not in deref(VTYPEPTR)._hints: VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR) self.VTYPEPTR = VTYPEPTR self.VTYPE = VTYPE = deref(VTYPEPTR) self.vable_token_descr = cpu.fielddescrof(VTYPE, 'vable_token') # accessor = VTYPE._hints['virtualizable2_accessor'] all_fields = accessor.fields static_fields = [] array_fields = [] for name, tp in all_fields.iteritems(): if tp == IR_IMMUTABLE_ARRAY: array_fields.append(name) elif tp == IR_IMMUTABLE: static_fields.append(name) else: raise Exception("unknown type: %s" % tp) self.static_fields = static_fields self.array_fields = array_fields # FIELDTYPES = [fieldType(VTYPE, name) for name in static_fields] ARRAYITEMTYPES = [] for name in array_fields: ARRAYPTR = fieldType(VTYPE, name) ARRAY = deref(ARRAYPTR) assert isinstance(ARRAYPTR, (lltype.Ptr, ootype.Array)) assert isinstance(ARRAY, (lltype.GcArray, ootype.Array)) ARRAYITEMTYPES.append(arrayItem(ARRAY)) self.array_descrs = [ cpu.arraydescrof(deref(fieldType(VTYPE, name))) for name in array_fields ] # self.num_static_extra_boxes = len(static_fields) self.num_arrays = len(array_fields) self.static_field_to_extra_box = dict([ (name, i) for (i, name) in enumerate(static_fields) ]) self.array_field_counter = dict([ (name, i) for (i, name) in enumerate(array_fields) ]) self.static_extra_types = [ history.getkind(TYPE) for TYPE in FIELDTYPES ] self.arrayitem_extra_types = [ history.getkind(ITEM) for ITEM in ARRAYITEMTYPES ] self.static_field_descrs = [ cpu.fielddescrof(VTYPE, name) for name in static_fields ] self.array_field_descrs = [ cpu.fielddescrof(VTYPE, name) for name in array_fields ] self.static_field_by_descrs = dict([ (descr, i) for (i, descr) in enumerate(self.static_field_descrs) ]) self.array_field_by_descrs = dict([ (descr, i) for (i, descr) in enumerate(self.array_field_descrs) ]) # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem setarrayitem = cpu.ts.setarrayitem # def read_boxes(cpu, virtualizable): assert lltype.typeOf(virtualizable) == llmemory.GCREF virtualizable = cast_gcref_to_vtype(virtualizable) boxes = [] for _, fieldname in unroll_static_fields: x = getattr(virtualizable, fieldname) boxes.append(wrap(cpu, x)) for _, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for i in range(getlength(lst)): boxes.append(wrap(cpu, getarrayitem(lst, i))) return boxes # def write_boxes(virtualizable, boxes): virtualizable = cast_gcref_to_vtype(virtualizable) i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) setattr(virtualizable, fieldname, x) i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) setarrayitem(lst, j, x) i = i + 1 assert len(boxes) == i + 1 # def write_from_resume_data_partial(virtualizable, reader, numb): virtualizable = cast_gcref_to_vtype(virtualizable) # Load values from the reader (see resume.py) described by # the list of numbers 'nums', and write them in their proper # place in the 'virtualizable'. This works from the end of # the list and returns the index in 'nums' of the start of # the virtualizable data found, allowing the caller to do # further processing with the start of the list. i = len(numb.nums) - 1 assert i >= 0 for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst) - 1, -1, -1): i -= 1 assert i >= 0 x = reader.load_value_of_type(ARRAYITEMTYPE, numb.nums[i]) setarrayitem(lst, j, x) for FIELDTYPE, fieldname in unroll_static_fields_rev: i -= 1 assert i >= 0 x = reader.load_value_of_type(FIELDTYPE, numb.nums[i]) setattr(virtualizable, fieldname, x) return i # def load_list_of_boxes(virtualizable, reader, numb): virtualizable = cast_gcref_to_vtype(virtualizable) # Uses 'virtualizable' only to know the length of the arrays; # does not write anything into it. The returned list is in # the format expected of virtualizable_boxes, so it ends in # the virtualizable itself. i = len(numb.nums) - 1 assert i >= 0 boxes = [reader.decode_box_of_type(self.VTYPEPTR, numb.nums[i])] for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst) - 1, -1, -1): i -= 1 assert i >= 0 box = reader.decode_box_of_type(ARRAYITEMTYPE, numb.nums[i]) boxes.append(box) for FIELDTYPE, fieldname in unroll_static_fields_rev: i -= 1 assert i >= 0 box = reader.decode_box_of_type(FIELDTYPE, numb.nums[i]) boxes.append(box) boxes.reverse() return boxes # def check_boxes(virtualizable, boxes): virtualizable = cast_gcref_to_vtype(virtualizable) # for debugging i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) assert getattr(virtualizable, fieldname) == x i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) assert getarrayitem(lst, j) == x i = i + 1 assert len(boxes) == i + 1 # def get_index_in_array(virtualizable, arrayindex, index): virtualizable = cast_gcref_to_vtype(virtualizable) index += self.num_static_extra_boxes j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: return index lst = getattr(virtualizable, fieldname) index += getlength(lst) j = j + 1 assert False, "invalid arrayindex" # def get_array_length(virtualizable, arrayindex): virtualizable = cast_gcref_to_vtype(virtualizable) j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: lst = getattr(virtualizable, fieldname) return getlength(lst) j = j + 1 assert False, "invalid arrayindex" # unroll_static_fields = unrolling_iterable( zip(FIELDTYPES, static_fields)) unroll_array_fields = unrolling_iterable( zip(ARRAYITEMTYPES, array_fields)) unroll_static_fields_rev = unrolling_iterable( reversed(list(unroll_static_fields))) unroll_array_fields_rev = unrolling_iterable( reversed(list(unroll_array_fields))) self.read_boxes = read_boxes self.write_boxes = write_boxes self.write_from_resume_data_partial = write_from_resume_data_partial self.load_list_of_boxes = load_list_of_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length def cast_to_vtype(virtualizable): return self.cpu.ts.cast_to_instance_maybe(VTYPEPTR, virtualizable) self.cast_to_vtype = cast_to_vtype def cast_gcref_to_vtype(virtualizable): assert lltype.typeOf(virtualizable) == llmemory.GCREF return lltype.cast_opaque_ptr(VTYPEPTR, virtualizable) self.cast_gcref_to_vtype = cast_gcref_to_vtype def reset_vable_token(virtualizable): virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE self.reset_vable_token = reset_vable_token def clear_vable_token(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) if virtualizable.vable_token: force_now(virtualizable) assert not virtualizable.vable_token self.clear_vable_token = clear_vable_token def tracing_before_residual_call(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) assert not virtualizable.vable_token virtualizable.vable_token = VirtualizableInfo.TOKEN_TRACING_RESCALL self.tracing_before_residual_call = tracing_before_residual_call def tracing_after_residual_call(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) if virtualizable.vable_token: # not modified by the residual call; assert that it is still # set to TOKEN_TRACING_RESCALL and clear it. assert virtualizable.vable_token == VirtualizableInfo.TOKEN_TRACING_RESCALL virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE return False else: # marker "modified during residual call" set. return True self.tracing_after_residual_call = tracing_after_residual_call def force_now(virtualizable): token = virtualizable.vable_token if token == VirtualizableInfo.TOKEN_TRACING_RESCALL: # The values in the virtualizable are always correct during # tracing. We only need to reset vable_token to TOKEN_NONE # as a marker for the tracing, to tell it that this # virtualizable escapes. virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE else: from pypy.jit.metainterp.compile import ResumeGuardForcedDescr ResumeGuardForcedDescr.force_now(cpu, token) assert virtualizable.vable_token == VirtualizableInfo.TOKEN_NONE force_now._dont_inline_ = True self.force_now = force_now def is_token_nonnull_gcref(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) return bool(virtualizable.vable_token) self.is_token_nonnull_gcref = is_token_nonnull_gcref def reset_token_gcref(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE self.reset_token_gcref = reset_token_gcref
def __init__(self, warmrunnerdesc): self.warmrunnerdesc = warmrunnerdesc jitdriver = warmrunnerdesc.jitdriver cpu = warmrunnerdesc.cpu self.cpu = cpu self.VABLERTI = cpu.ts.get_VABLERTI() self.null_vable_rti = cpu.ts.nullptr(deref(self.VABLERTI)) self.BoxArray = cpu.ts.BoxRef # assert len(jitdriver.virtualizables) == 1 # for now [vname] = jitdriver.virtualizables index = len(jitdriver.greens) + jitdriver.reds.index(vname) self.index_of_virtualizable = index VTYPEPTR = warmrunnerdesc.JIT_ENTER_FUNCTYPE.ARGS[index] while 'virtualizable2_accessor' not in deref(VTYPEPTR)._hints: VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR) self.VTYPEPTR = VTYPEPTR self.VTYPE = VTYPE = deref(VTYPEPTR) self.null_vable = cpu.ts.nullptr(VTYPE) # accessor = VTYPE._hints['virtualizable2_accessor'] all_fields = accessor.fields static_fields = [] array_fields = [] for name, suffix in all_fields.iteritems(): if suffix == '[*]': array_fields.append(name) else: static_fields.append(name) self.static_fields = static_fields self.array_fields = array_fields # FIELDTYPES = [fieldType(VTYPE, name) for name in static_fields] ARRAYITEMTYPES = [] for name in array_fields: ARRAYPTR = fieldType(VTYPE, name) ARRAY = deref(ARRAYPTR) assert isinstance(ARRAYPTR, (lltype.Ptr, ootype.Array)) assert isinstance(ARRAY, (lltype.GcArray, ootype.Array)) ARRAYITEMTYPES.append(arrayItem(ARRAY)) self.array_descrs = [ cpu.arraydescrof(deref(fieldType(VTYPE, name))) for name in array_fields ] # self.num_static_extra_boxes = len(static_fields) self.num_arrays = len(array_fields) self.static_field_to_extra_box = dict([ (name, i) for (i, name) in enumerate(static_fields) ]) self.array_field_counter = dict([ (name, i) for (i, name) in enumerate(array_fields) ]) self.static_extra_types = [ history.getkind(TYPE) for TYPE in FIELDTYPES ] self.arrayitem_extra_types = [ history.getkind(ITEM) for ITEM in ARRAYITEMTYPES ] self.static_field_descrs = [ cpu.fielddescrof(VTYPE, name) for name in static_fields ] self.array_field_descrs = [ cpu.fielddescrof(VTYPE, name) for name in array_fields ] # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem setarrayitem = cpu.ts.setarrayitem # def read_boxes(cpu, virtualizable): boxes = [] for _, fieldname in unroll_static_fields: x = getattr(virtualizable, fieldname) boxes.append(wrap(cpu, x)) for _, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for i in range(getlength(lst)): boxes.append(wrap(cpu, getarrayitem(lst, i))) return boxes # def write_boxes(virtualizable, boxes): i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) setattr(virtualizable, fieldname, x) i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) setarrayitem(lst, j, x) i = i + 1 assert len(boxes) == i + 1 # def check_boxes(virtualizable, boxes): # for debugging i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) assert getattr(virtualizable, fieldname) == x i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) assert getarrayitem(lst, j) == x i = i + 1 assert len(boxes) == i + 1 # def get_index_in_array(virtualizable, arrayindex, index): index += self.num_static_extra_boxes j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: return index lst = getattr(virtualizable, fieldname) index += getlength(lst) j = j + 1 assert False, "invalid arrayindex" # def get_array_length(virtualizable, arrayindex): j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: lst = getattr(virtualizable, fieldname) return getlength(lst) j = j + 1 assert False, "invalid arrayindex" # unroll_static_fields = unrolling_iterable( zip(FIELDTYPES, static_fields)) unroll_array_fields = unrolling_iterable( zip(ARRAYITEMTYPES, array_fields)) self.read_boxes = read_boxes self.write_boxes = write_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length
def __init__(self, warmrunnerdesc): self.warmrunnerdesc = warmrunnerdesc jitdriver = warmrunnerdesc.jitdriver cpu = warmrunnerdesc.cpu self.cpu = cpu self.VABLERTI = cpu.ts.get_VABLERTI() self.null_vable_rti = cpu.ts.nullptr(deref(self.VABLERTI)) self.BoxArray = cpu.ts.BoxRef # assert len(jitdriver.virtualizables) == 1 # for now [vname] = jitdriver.virtualizables index = len(jitdriver.greens) + jitdriver.reds.index(vname) self.index_of_virtualizable = index VTYPEPTR = warmrunnerdesc.JIT_ENTER_FUNCTYPE.ARGS[index] while 'virtualizable2_accessor' not in deref(VTYPEPTR)._hints: VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR) self.VTYPEPTR = VTYPEPTR self.VTYPE = VTYPE = deref(VTYPEPTR) self.null_vable = cpu.ts.nullptr(VTYPE) # accessor = VTYPE._hints['virtualizable2_accessor'] all_fields = accessor.fields static_fields = [] array_fields = [] for name, suffix in all_fields.iteritems(): if suffix == '[*]': array_fields.append(name) else: static_fields.append(name) self.static_fields = static_fields self.array_fields = array_fields # FIELDTYPES = [fieldType(VTYPE, name) for name in static_fields] ARRAYITEMTYPES = [] for name in array_fields: ARRAYPTR = fieldType(VTYPE, name) ARRAY = deref(ARRAYPTR) assert isinstance(ARRAYPTR, (lltype.Ptr, ootype.Array)) assert isinstance(ARRAY, (lltype.GcArray, ootype.Array)) ARRAYITEMTYPES.append(arrayItem(ARRAY)) self.array_descrs = [cpu.arraydescrof(deref(fieldType(VTYPE, name))) for name in array_fields] # self.num_static_extra_boxes = len(static_fields) self.num_arrays = len(array_fields) self.static_field_to_extra_box = dict( [(name, i) for (i, name) in enumerate(static_fields)]) self.array_field_counter = dict( [(name, i) for (i, name) in enumerate(array_fields)]) self.static_extra_types = [history.getkind(TYPE) for TYPE in FIELDTYPES] self.arrayitem_extra_types = [history.getkind(ITEM) for ITEM in ARRAYITEMTYPES] self.static_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in static_fields] self.array_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in array_fields] # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem setarrayitem = cpu.ts.setarrayitem # def read_boxes(cpu, virtualizable): boxes = [] for _, fieldname in unroll_static_fields: x = getattr(virtualizable, fieldname) boxes.append(wrap(cpu, x)) for _, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for i in range(getlength(lst)): boxes.append(wrap(cpu, getarrayitem(lst, i))) return boxes # def write_boxes(virtualizable, boxes): i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) setattr(virtualizable, fieldname, x) i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) setarrayitem(lst, j, x) i = i + 1 assert len(boxes) == i + 1 # def check_boxes(virtualizable, boxes): # for debugging i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) assert getattr(virtualizable, fieldname) == x i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) assert getarrayitem(lst, j) == x i = i + 1 assert len(boxes) == i + 1 # def get_index_in_array(virtualizable, arrayindex, index): index += self.num_static_extra_boxes j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: return index lst = getattr(virtualizable, fieldname) index += getlength(lst) j = j + 1 assert False, "invalid arrayindex" # def get_array_length(virtualizable, arrayindex): j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: lst = getattr(virtualizable, fieldname) return getlength(lst) j = j + 1 assert False, "invalid arrayindex" # unroll_static_fields = unrolling_iterable(zip(FIELDTYPES, static_fields)) unroll_array_fields = unrolling_iterable(zip(ARRAYITEMTYPES, array_fields)) self.read_boxes = read_boxes self.write_boxes = write_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length
def __init__(self, warmrunnerdesc, VTYPEPTR): self.warmrunnerdesc = warmrunnerdesc cpu = warmrunnerdesc.cpu if cpu.ts.name == 'ootype': import py py.test.skip("ootype: fix virtualizables") self.cpu = cpu self.BoxArray = cpu.ts.BoxRef # while 'virtualizable2_accessor' not in deref(VTYPEPTR)._hints: VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR) self.VTYPEPTR = VTYPEPTR self.VTYPE = VTYPE = deref(VTYPEPTR) self.vable_token_descr = cpu.fielddescrof(VTYPE, 'vable_token') # accessor = VTYPE._hints['virtualizable2_accessor'] all_fields = accessor.fields static_fields = [] array_fields = [] for name, tp in all_fields.iteritems(): if tp == IR_IMMUTABLE_ARRAY: array_fields.append(name) elif tp == IR_IMMUTABLE: static_fields.append(name) else: raise Exception("unknown type: %s" % tp) self.static_fields = static_fields self.array_fields = array_fields # FIELDTYPES = [fieldType(VTYPE, name) for name in static_fields] ARRAYITEMTYPES = [] for name in array_fields: ARRAYPTR = fieldType(VTYPE, name) ARRAY = deref(ARRAYPTR) assert isinstance(ARRAYPTR, (lltype.Ptr, ootype.Array)) assert isinstance(ARRAY, (lltype.GcArray, ootype.Array)) ARRAYITEMTYPES.append(arrayItem(ARRAY)) self.array_descrs = [cpu.arraydescrof(deref(fieldType(VTYPE, name))) for name in array_fields] # self.num_static_extra_boxes = len(static_fields) self.num_arrays = len(array_fields) self.static_field_to_extra_box = dict( [(name, i) for (i, name) in enumerate(static_fields)]) self.array_field_counter = dict( [(name, i) for (i, name) in enumerate(array_fields)]) self.static_extra_types = [history.getkind(TYPE) for TYPE in FIELDTYPES] self.arrayitem_extra_types = [history.getkind(ITEM) for ITEM in ARRAYITEMTYPES] self.static_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in static_fields] self.array_field_descrs = [cpu.fielddescrof(VTYPE, name) for name in array_fields] self.static_field_by_descrs = dict( [(descr, i) for (i, descr) in enumerate(self.static_field_descrs)]) self.array_field_by_descrs = dict( [(descr, i) for (i, descr) in enumerate(self.array_field_descrs)]) # getlength = cpu.ts.getlength getarrayitem = cpu.ts.getarrayitem setarrayitem = cpu.ts.setarrayitem # def read_boxes(cpu, virtualizable): assert lltype.typeOf(virtualizable) == llmemory.GCREF virtualizable = cast_gcref_to_vtype(virtualizable) boxes = [] for _, fieldname in unroll_static_fields: x = getattr(virtualizable, fieldname) boxes.append(wrap(cpu, x)) for _, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for i in range(getlength(lst)): boxes.append(wrap(cpu, getarrayitem(lst, i))) return boxes # def write_boxes(virtualizable, boxes): virtualizable = cast_gcref_to_vtype(virtualizable) i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) setattr(virtualizable, fieldname, x) i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) setarrayitem(lst, j, x) i = i + 1 assert len(boxes) == i + 1 # def write_from_resume_data_partial(virtualizable, reader, numb): virtualizable = cast_gcref_to_vtype(virtualizable) # Load values from the reader (see resume.py) described by # the list of numbers 'nums', and write them in their proper # place in the 'virtualizable'. This works from the end of # the list and returns the index in 'nums' of the start of # the virtualizable data found, allowing the caller to do # further processing with the start of the list. i = len(numb.nums) - 1 assert i >= 0 for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)-1, -1, -1): i -= 1 assert i >= 0 x = reader.load_value_of_type(ARRAYITEMTYPE, numb.nums[i]) setarrayitem(lst, j, x) for FIELDTYPE, fieldname in unroll_static_fields_rev: i -= 1 assert i >= 0 x = reader.load_value_of_type(FIELDTYPE, numb.nums[i]) setattr(virtualizable, fieldname, x) return i # def load_list_of_boxes(virtualizable, reader, numb): virtualizable = cast_gcref_to_vtype(virtualizable) # Uses 'virtualizable' only to know the length of the arrays; # does not write anything into it. The returned list is in # the format expected of virtualizable_boxes, so it ends in # the virtualizable itself. i = len(numb.nums) - 1 assert i >= 0 boxes = [reader.decode_box_of_type(self.VTYPEPTR, numb.nums[i])] for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)-1, -1, -1): i -= 1 assert i >= 0 box = reader.decode_box_of_type(ARRAYITEMTYPE,numb.nums[i]) boxes.append(box) for FIELDTYPE, fieldname in unroll_static_fields_rev: i -= 1 assert i >= 0 box = reader.decode_box_of_type(FIELDTYPE, numb.nums[i]) boxes.append(box) boxes.reverse() return boxes # def check_boxes(virtualizable, boxes): virtualizable = cast_gcref_to_vtype(virtualizable) # for debugging i = 0 for FIELDTYPE, fieldname in unroll_static_fields: x = unwrap(FIELDTYPE, boxes[i]) assert getattr(virtualizable, fieldname) == x i = i + 1 for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): x = unwrap(ARRAYITEMTYPE, boxes[i]) assert getarrayitem(lst, j) == x i = i + 1 assert len(boxes) == i + 1 # def get_index_in_array(virtualizable, arrayindex, index): virtualizable = cast_gcref_to_vtype(virtualizable) index += self.num_static_extra_boxes j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: return index lst = getattr(virtualizable, fieldname) index += getlength(lst) j = j + 1 assert False, "invalid arrayindex" # def get_array_length(virtualizable, arrayindex): virtualizable = cast_gcref_to_vtype(virtualizable) j = 0 for _, fieldname in unroll_array_fields: if arrayindex == j: lst = getattr(virtualizable, fieldname) return getlength(lst) j = j + 1 assert False, "invalid arrayindex" # unroll_static_fields = unrolling_iterable(zip(FIELDTYPES, static_fields)) unroll_array_fields = unrolling_iterable(zip(ARRAYITEMTYPES, array_fields)) unroll_static_fields_rev = unrolling_iterable( reversed(list(unroll_static_fields))) unroll_array_fields_rev = unrolling_iterable( reversed(list(unroll_array_fields))) self.read_boxes = read_boxes self.write_boxes = write_boxes self.write_from_resume_data_partial = write_from_resume_data_partial self.load_list_of_boxes = load_list_of_boxes self.check_boxes = check_boxes self.get_index_in_array = get_index_in_array self.get_array_length = get_array_length def cast_to_vtype(virtualizable): return self.cpu.ts.cast_to_instance_maybe(VTYPEPTR, virtualizable) self.cast_to_vtype = cast_to_vtype def cast_gcref_to_vtype(virtualizable): assert lltype.typeOf(virtualizable) == llmemory.GCREF return lltype.cast_opaque_ptr(VTYPEPTR, virtualizable) self.cast_gcref_to_vtype = cast_gcref_to_vtype def reset_vable_token(virtualizable): virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE self.reset_vable_token = reset_vable_token def clear_vable_token(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) if virtualizable.vable_token: force_now(virtualizable) assert not virtualizable.vable_token self.clear_vable_token = clear_vable_token def tracing_before_residual_call(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) assert not virtualizable.vable_token virtualizable.vable_token = VirtualizableInfo.TOKEN_TRACING_RESCALL self.tracing_before_residual_call = tracing_before_residual_call def tracing_after_residual_call(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) if virtualizable.vable_token: # not modified by the residual call; assert that it is still # set to TOKEN_TRACING_RESCALL and clear it. assert virtualizable.vable_token == VirtualizableInfo.TOKEN_TRACING_RESCALL virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE return False else: # marker "modified during residual call" set. return True self.tracing_after_residual_call = tracing_after_residual_call def force_now(virtualizable): token = virtualizable.vable_token if token == VirtualizableInfo.TOKEN_TRACING_RESCALL: # The values in the virtualizable are always correct during # tracing. We only need to reset vable_token to TOKEN_NONE # as a marker for the tracing, to tell it that this # virtualizable escapes. virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE else: from pypy.jit.metainterp.compile import ResumeGuardForcedDescr ResumeGuardForcedDescr.force_now(cpu, token) assert virtualizable.vable_token == VirtualizableInfo.TOKEN_NONE force_now._dont_inline_ = True self.force_now = force_now def is_token_nonnull_gcref(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) return bool(virtualizable.vable_token) self.is_token_nonnull_gcref = is_token_nonnull_gcref def reset_token_gcref(virtualizable): virtualizable = cast_gcref_to_vtype(virtualizable) virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE self.reset_token_gcref = reset_token_gcref
from pypy.translator.backendopt.writeanalyze import top_set if effects is top_set: return None readonly_descrs_fields = [] # readonly_descrs_arrays = [] --- not enabled for now write_descrs_fields = [] write_descrs_arrays = [] def add_struct(descrs_fields, (_, T, fieldname)): T = deref(T) if consider_struct(T, fieldname): descr = cpu.fielddescrof(T, fieldname) descrs_fields.append(descr) def add_array(descrs_arrays, (_, T)): ARRAY = deref(T) if consider_array(ARRAY): descr = cpu.arraydescrof(ARRAY) descrs_arrays.append(descr) for tup in effects: if tup[0] == "struct": add_struct(write_descrs_fields, tup) elif tup[0] == "readstruct": tupw = ("struct",) + tup[1:] if tupw not in effects: add_struct(readonly_descrs_fields, tup) elif tup[0] == "array": add_array(write_descrs_arrays, tup) elif tup[0] == "readarray": pass