def do_call(result, path, index, remaining_depth): # clone the while path clonedata.gcobjectptr = lltype.cast_opaque_ptr(llmemory.GCREF, path) clonedata.pool = lltype.nullptr(X_POOL) llop.gc_x_clone(lltype.Void, clonedata) # install the new pool as the current one parentpool = llop.gc_x_swap_pool(X_POOL_PTR, clonedata.pool) path = lltype.cast_opaque_ptr(lltype.Ptr(NODE), clonedata.gcobjectptr) # The above should have the same effect as: # path = clone(path) # bump all the path node counters by one p = path while p: p.counter += 1 p = p.next if remaining_depth == 0: llop.debug_print(lltype.Void, "setting", index, "with", path) result[index] = path # leaf else: node = lltype.malloc(NODE) node.index = index * 2 node.counter = 0 node.next = path do_call(result, node, index * 2, remaining_depth - 1) node.index += 1 # mutation! do_call(result, node, index * 2 + 1, remaining_depth - 1) # restore the parent pool llop.gc_x_swap_pool(X_POOL_PTR, parentpool)
def resume_after_raising(state, exception): if global_state.restart_substate == -1: # normal entry point for a call to state.switch() # first unwind the stack u = UnwindException() s = lltype.malloc(SWITCH_STATE) s.header.f_restart = INDEX_RESUME_AFTER_RAISING s.c = lltype.cast_opaque_ptr(SAVED_REFERENCE, state) add_frame_state(u, s.header) global_state.exception = exception raise u elif global_state.restart_substate == 0: # STATE 0: we didn't do anything so far, but the stack is unwound global_state.restart_substate = -1 # grab the frame corresponding to ourself # the 'targetstate' local is garbage here, it must be read back from # 's.c' where we saved it by the normal entry point above mystate = global_state.top s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), mystate) targetstate = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), s.c) resume_bottom = targetstate while resume_bottom.f_back: resume_bottom = resume_bottom.f_back resume_bottom.f_back = mystate.f_back global_state.top = targetstate raise UnwindException()
def resume_after_raising(state, exception): if global_state.restart_substate == -1: # normal entry point for a call to state.switch() # first unwind the stack u = UnwindException() s = lltype.malloc(SWITCH_STATE) s.header.f_restart = INDEX_RESUME_AFTER_RAISING s.c = lltype.cast_opaque_ptr(SAVED_REFERENCE, state) add_frame_state(u, s.header) global_state.exception = exception raise u elif global_state.restart_substate == 0: # STATE 0: we didn't do anything so far, but the stack is unwound global_state.restart_substate = -1 # grab the frame corresponding to ourself # the 'targetstate' local is garbage here, it must be read back from # 's.c' where we saved it by the normal entry point above mystate = global_state.top s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), mystate) targetstate = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), s.c) resume_bottom = targetstate while resume_bottom.f_back: resume_bottom = resume_bottom.f_back resume_bottom.f_back = mystate.f_back global_state.top = targetstate raise UnwindException()
def test_save_regs_at_correct_place(self): cpu = self.cpu gc_ll_descr = cpu.gc_ll_descr S1 = gc_ll_descr.gcrootmap.S1 S2 = lltype.GcStruct('S2', ('s0', lltype.Ptr(S1)), ('s1', lltype.Ptr(S1)), ('s2', lltype.Ptr(S1)), ('s3', lltype.Ptr(S1)), ('s4', lltype.Ptr(S1)), ('s5', lltype.Ptr(S1)), ('s6', lltype.Ptr(S1)), ('s7', lltype.Ptr(S1)), ('s8', lltype.Ptr(S1)), ('s9', lltype.Ptr(S1)), ('s10', lltype.Ptr(S1)), ('s11', lltype.Ptr(S1)), ('s12', lltype.Ptr(S1)), ('s13', lltype.Ptr(S1)), ('s14', lltype.Ptr(S1)), ('s15', lltype.Ptr(S1))) self.namespace = self.namespace.copy() for i in range(16): self.namespace['ds%i' % i] = cpu.fielddescrof(S2, 's%d' % i) ops = ''' [p0] p1 = getfield_gc(p0, descr=ds0) p2 = getfield_gc(p0, descr=ds1) p3 = getfield_gc(p0, descr=ds2) p4 = getfield_gc(p0, descr=ds3) p5 = getfield_gc(p0, descr=ds4) p6 = getfield_gc(p0, descr=ds5) p7 = getfield_gc(p0, descr=ds6) p8 = getfield_gc(p0, descr=ds7) p9 = getfield_gc(p0, descr=ds8) p10 = getfield_gc(p0, descr=ds9) p11 = getfield_gc(p0, descr=ds10) p12 = getfield_gc(p0, descr=ds11) p13 = getfield_gc(p0, descr=ds12) p14 = getfield_gc(p0, descr=ds13) p15 = getfield_gc(p0, descr=ds14) p16 = getfield_gc(p0, descr=ds15) # # now all registers are in use p17 = call_malloc_nursery(40) p18 = call_malloc_nursery(40) # overflow # finish(p1, p2, p3, p4, p5, p6, p7, p8, \ p9, p10, p11, p12, p13, p14, p15, p16) ''' s2 = lltype.malloc(S2) for i in range(16): s1 = lltype.malloc(S1) setattr(s2, 's%d' % i, s1) gc_ll_descr.gcrootmap.should_see.append(s1) s2ref = lltype.cast_opaque_ptr(llmemory.GCREF, s2) # self.interpret(ops, [s2ref]) gc_ll_descr.check_nothing_in_nursery() assert gc_ll_descr.calls == [40] gc_ll_descr.gcrootmap.check_initial_and_final_state() # check the returned pointers for i in range(16): s1ref = self.cpu.get_latest_value_ref(i) s1 = lltype.cast_opaque_ptr(lltype.Ptr(S1), s1ref) for j in range(16): assert s1 != getattr(s2, 's%d' % j) assert s1 == gc_ll_descr.gcrootmap.should_see[i]
def ll_frame_switch(targetstate): if global_state.restart_substate == -1: # normal entry point for a call to state.switch() # first unwind the stack u = UnwindException() s = lltype.malloc(SWITCH_STATE) s.header.f_restart = INDEX_SWITCH s.c = lltype.cast_opaque_ptr(SAVED_REFERENCE, targetstate) add_frame_state(u, s.header) raise u elif global_state.restart_substate == 0: # STATE 0: we didn't do anything so far, but the stack is unwound global_state.restart_substate = -1 # grab the frame corresponding to ourself # the 'targetstate' local is garbage here, it must be read back from # 's.c' where we saved it by the normal entry point above mystate = global_state.top s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), mystate) targetstate = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), s.c) # prepare a new saved state for the future switch() back, # which will go to STATE 1 below sourcestate = lltype.malloc(EMPTY_STATE).header sourcestate.f_back = mystate.f_back sourcestate.f_restart = INDEX_SWITCH + 1 global_state.top = targetstate global_state.retval_ref = lltype.cast_opaque_ptr(SAVED_REFERENCE, sourcestate) raise UnwindException() # this jumps to targetstate else: # STATE 1: switching back into a tasklet suspended by # a call to switch() global_state.top = frame.null_state global_state.restart_substate = -1 origin_state = lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR, fetch_retval_ref()) return origin_state # a normal return into the current tasklet,
def continue_tracing(self, gcref, real_object): if not self.is_virtual_ref(gcref): return assert real_object vref = lltype.cast_opaque_ptr(lltype.Ptr(self.JIT_VIRTUAL_REF), gcref) assert vref.virtual_token != self.TOKEN_TRACING_RESCALL vref.virtual_token = self.TOKEN_NONE vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object)
def virtual_ref_during_tracing(self, real_object): assert real_object vref = lltype.malloc(self.JIT_VIRTUAL_REF) p = lltype.cast_pointer(rclass.OBJECTPTR, vref) p.typeptr = self.jit_virtual_ref_vtable vref.virtual_token = self.TOKEN_NONE vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object) return lltype.cast_opaque_ptr(llmemory.GCREF, vref)
def virtual_ref_during_tracing(self, real_object): assert real_object vref = lltype.malloc(self.JIT_VIRTUAL_REF) p = lltype.cast_pointer(rclass.OBJECTPTR, vref) p.typeptr = self.jit_virtual_ref_vtable vref.virtual_token = self.TOKEN_NONE vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object) return lltype.cast_opaque_ptr(llmemory.GCREF, vref)
def continue_tracing(self, gcref, real_object): if not self.is_virtual_ref(gcref): return assert real_object vref = lltype.cast_opaque_ptr(lltype.Ptr(self.JIT_VIRTUAL_REF), gcref) assert vref.virtual_token != self.TOKEN_TRACING_RESCALL vref.virtual_token = self.TOKEN_NONE vref.forced = lltype.cast_opaque_ptr(rclass.OBJECTPTR, real_object)
def test_compile_tmp_callback(): from pypy.jit.codewriter import heaptracker from pypy.jit.backend.llgraph import runner from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.annlowlevel import llhelper from pypy.rpython.llinterp import LLException # cpu = runner.LLtypeCPU(None) FUNC = lltype.FuncType([lltype.Signed]*4, lltype.Signed) def ll_portal_runner(g1, g2, r3, r4): assert (g1, g2, r3, r4) == (12, 34, -156, -178) if raiseme: raise raiseme else: return 54321 # class FakeJitDriverSD: portal_runner_ptr = llhelper(lltype.Ptr(FUNC), ll_portal_runner) portal_runner_adr = llmemory.cast_ptr_to_adr(portal_runner_ptr) portal_calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT) portal_finishtoken = compile.DoneWithThisFrameDescrInt() num_red_args = 2 result_type = INT # loop_token = compile_tmp_callback(cpu, FakeJitDriverSD(), [ConstInt(12), ConstInt(34)], [BoxInt(56), ConstInt(78), BoxInt(90)]) # raiseme = None cpu.set_future_value_int(0, -156) cpu.set_future_value_int(1, -178) cpu.set_future_value_int(2, -190) # passed in, but dropped fail_descr = cpu.execute_token(loop_token) assert fail_descr is FakeJitDriverSD().portal_finishtoken # EXC = lltype.GcStruct('EXC') llexc = lltype.malloc(EXC) raiseme = LLException("exception class", llexc) cpu.set_future_value_int(0, -156) cpu.set_future_value_int(1, -178) cpu.set_future_value_int(2, -190) fail_descr = cpu.execute_token(loop_token) assert isinstance(fail_descr, compile.PropagateExceptionDescr) got = cpu.grab_exc_value() assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), got) == llexc # class FakeMetaInterpSD: class ExitFrameWithExceptionRef(Exception): pass FakeMetaInterpSD.cpu = cpu cpu.set_future_value_int(0, -156) cpu.set_future_value_int(1, -178) cpu.set_future_value_int(2, -190) fail_descr = cpu.execute_token(loop_token) try: fail_descr.handle_fail(FakeMetaInterpSD(), None) except FakeMetaInterpSD.ExitFrameWithExceptionRef, e: assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), e.args[1]) == llexc
def concat_unicodes(self, str1num, str2num): str1 = self.decode_ref(str1num) str2 = self.decode_ref(str2num) str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str1) str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str2) cic = self.callinfocollection funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT) result = funcptr(str1, str2) return lltype.cast_opaque_ptr(llmemory.GCREF, result)
def slice_unicode(self, strnum, startnum, lengthnum): str = self.decode_ref(strnum) start = self.decode_int(startnum) length = self.decode_int(lengthnum) str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str) cic = self.callinfocollection funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_UNI_SLICE) result = funcptr(str, start, start + length) return lltype.cast_opaque_ptr(llmemory.GCREF, result)
def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s) gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u) lst = rgc.get_rpy_referents(gcref1) assert gcref2 in lst assert gcref1 not in lst s.u.x = 42 return 0
def g(s): lst = rgc.get_rpy_roots() found = False for x in lst: if x == lltype.cast_opaque_ptr(llmemory.GCREF, s): found = True if x == lltype.cast_opaque_ptr(llmemory.GCREF, s.u): os.write(2, "s.u should not be found!\n") assert False return found == 1
def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s) gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u) lst = rgc.get_rpy_referents(gcref1) assert gcref2 in lst assert gcref1 not in lst s.u.x = 42 return 0
def g(s): lst = rgc.get_rpy_roots() found = False for x in lst: if x == lltype.cast_opaque_ptr(llmemory.GCREF, s): found = True if x == lltype.cast_opaque_ptr(llmemory.GCREF, s.u): os.write(2, "s.u should not be found!\n") assert False return found == 1
def test_compile_tmp_callback(): from pypy.jit.codewriter import heaptracker from pypy.jit.backend.llgraph import runner from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.annlowlevel import llhelper from pypy.rpython.llinterp import LLException # cpu = runner.LLtypeCPU(None) FUNC = lltype.FuncType([lltype.Signed] * 4, lltype.Signed) def ll_portal_runner(g1, g2, r3, r4): assert (g1, g2, r3, r4) == (12, 34, -156, -178) if raiseme: raise raiseme else: return 54321 # class FakeJitDriverSD: portal_runner_ptr = llhelper(lltype.Ptr(FUNC), ll_portal_runner) portal_runner_adr = llmemory.cast_ptr_to_adr(portal_runner_ptr) portal_calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, None) portal_finishtoken = compile.DoneWithThisFrameDescrInt() num_red_args = 2 result_type = INT # loop_token = compile_tmp_callback( cpu, FakeJitDriverSD(), [ConstInt(12), ConstInt(34)], "ii") # raiseme = None # only two arguments must be passed in fail_descr = cpu.execute_token(loop_token, -156, -178) assert fail_descr is FakeJitDriverSD().portal_finishtoken # EXC = lltype.GcStruct('EXC') llexc = lltype.malloc(EXC) raiseme = LLException("exception class", llexc) fail_descr = cpu.execute_token(loop_token, -156, -178) assert isinstance(fail_descr, compile.PropagateExceptionDescr) got = cpu.grab_exc_value() assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), got) == llexc # class FakeMetaInterpSD: class ExitFrameWithExceptionRef(Exception): pass FakeMetaInterpSD.cpu = cpu fail_descr = cpu.execute_token(loop_token, -156, -178) try: fail_descr.handle_fail(FakeMetaInterpSD(), None) except FakeMetaInterpSD.ExitFrameWithExceptionRef, e: assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), e.args[1]) == llexc
def test_extract_runtime_data_4(): struct = lltype.malloc(LLtypeMixin.S) struct.a = 123 struct.b = lltype.malloc(LLtypeMixin.NODE) structbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, struct)) sspecnode = _get_sspecnode() res = [] sspecnode.extract_runtime_data(LLtypeMixin.cpu, structbox, res) assert len(res) == 2 assert res[0].value == 123 assert (lltype.cast_opaque_ptr(lltype.Ptr(LLtypeMixin.NODE), res[1].value) == struct.b)
def test_extract_runtime_data_4(): struct = lltype.malloc(LLtypeMixin.S) struct.a = 123 struct.b = lltype.malloc(LLtypeMixin.NODE) structbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, struct)) sspecnode = _get_sspecnode() res = [] sspecnode.extract_runtime_data(LLtypeMixin.cpu, structbox, res) assert len(res) == 2 assert res[0].value == 123 assert (lltype.cast_opaque_ptr(lltype.Ptr(LLtypeMixin.NODE), res[1].value) == struct.b)
def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) a = lltype.malloc(A, 1000) gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s) int1 = rgc.get_rpy_memory_usage(gcref1) assert 8 <= int1 <= 32 gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u) int2 = rgc.get_rpy_memory_usage(gcref2) assert 4*9 <= int2 <= 8*12 gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, a) int3 = rgc.get_rpy_memory_usage(gcref3) assert 4*1001 <= int3 <= 8*1010 return 0
def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) a = lltype.malloc(A, 1000) gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s) int1 = rgc.get_rpy_memory_usage(gcref1) assert 8 <= int1 <= 32 gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u) int2 = rgc.get_rpy_memory_usage(gcref2) assert 4*9 <= int2 <= 8*12 gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, a) int3 = rgc.get_rpy_memory_usage(gcref3) assert 4*1001 <= int3 <= 8*1010 return 0
def do_force_quasi_immutable(cpu, p, mutatefielddescr): qmut_ref = cpu.bh_getfield_gc_r(p, mutatefielddescr) if qmut_ref: cpu.bh_setfield_gc_r(p, mutatefielddescr, cpu.ts.NULLREF) qmut_ptr = lltype.cast_opaque_ptr(rclass.OBJECTPTR, qmut_ref) qmut = cast_base_ptr_to_instance(QuasiImmut, qmut_ptr) qmut.invalidate()
def test_record_constptrs(self): class MyFakeCPU(object): def cast_adr_to_int(self, adr): assert adr == "some fake address" return 43 class MyFakeGCRefList(object): def get_address_of_gcref(self, s_gcref1): assert s_gcref1 == s_gcref return "some fake address" S = lltype.GcStruct('S') s = lltype.malloc(S) s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) v_random_box = BoxPtr() v_result = BoxInt() operations = [ ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr gc_ll_descr.gcrefs = MyFakeGCRefList() gcrefs = [] operations = get_deep_immutable_oplist(operations) operations2 = gc_ll_descr.rewrite_assembler(MyFakeCPU(), operations, gcrefs) assert operations2 == operations assert gcrefs == [s_gcref]
def test_get_current_qmut_instance(): accessor = FieldListAccessor() accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE}) STRUCT = lltype.GcStruct('Foo', ('inst_x', lltype.Signed), ('mutate_x', rclass.OBJECTPTR), hints={'immutable_fields': accessor}) foo = lltype.malloc(STRUCT, zero=True) foo.inst_x = 42 assert not foo.mutate_x class FakeCPU: ts = typesystem.llhelper def bh_getfield_gc_r(self, gcref, fielddescr): assert fielddescr == mutatefielddescr foo = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref) result = foo.mutate_x return lltype.cast_opaque_ptr(llmemory.GCREF, result) def bh_setfield_gc_r(self, gcref, fielddescr, newvalue_gcref): assert fielddescr == mutatefielddescr foo = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref) newvalue = lltype.cast_opaque_ptr(rclass.OBJECTPTR, newvalue_gcref) foo.mutate_x = newvalue cpu = FakeCPU() mutatefielddescr = ('fielddescr', STRUCT, 'mutate_x') foo_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, foo) qmut1 = get_current_qmut_instance(cpu, foo_gcref, mutatefielddescr) assert isinstance(qmut1, QuasiImmut) qmut2 = get_current_qmut_instance(cpu, foo_gcref, mutatefielddescr) assert qmut1 is qmut2
def test_rewrite_assembler_1_cannot_move(self): # check rewriting of ConstPtrs class MyFakeCPU: def cast_adr_to_int(self, adr): xxx # should not be called class MyFakeGCRefList: def get_address_of_gcref(self, s_gcref1): seen.append(s_gcref1) assert s_gcref1 == s_gcref return "some fake address" seen = [] S = lltype.GcStruct('S') s = lltype.malloc(S) s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) v_random_box = BoxPtr() v_result = BoxInt() operations = [ ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr gc_ll_descr.gcrefs = MyFakeGCRefList() old_can_move = rgc.can_move try: rgc.can_move = lambda s: False gc_ll_descr.rewrite_assembler(MyFakeCPU(), operations) finally: rgc.can_move = old_can_move assert len(operations) == 1 assert operations[0].opnum == rop.OOIS assert operations[0].args == [v_random_box, ConstPtr(s_gcref)] assert operations[0].result == v_result # check that s_gcref gets added to the list anyway, to make sure # that the GC sees it assert seen == [s_gcref]
def test_wrap(): def _is(box1, box2): return box1.__class__ == box2.__class__ and box1.value == box2.value p = lltype.malloc(lltype.GcStruct("S")) po = lltype.cast_opaque_ptr(llmemory.GCREF, p) assert _is(wrap(None, 42), BoxInt(42)) assert _is(wrap(None, 42.5), boxfloat(42.5)) assert _is(wrap(None, p), BoxPtr(po)) assert _is(wrap(None, 42, in_const_box=True), ConstInt(42)) assert _is(wrap(None, 42.5, in_const_box=True), constfloat(42.5)) assert _is(wrap(None, p, in_const_box=True), ConstPtr(po)) if longlong.supports_longlong: import sys from pypy.rlib.rarithmetic import r_longlong, r_ulonglong value = r_longlong(-sys.maxint * 17) assert _is(wrap(None, value), BoxFloat(value)) assert _is(wrap(None, value, in_const_box=True), ConstFloat(value)) value_unsigned = r_ulonglong(-sys.maxint * 17) assert _is(wrap(None, value_unsigned), BoxFloat(value)) sfval = r_singlefloat(42.5) ival = longlong.singlefloat2int(sfval) assert _is(wrap(None, sfval), BoxInt(ival)) assert _is(wrap(None, sfval, in_const_box=True), ConstInt(ival))
def wrap(cpu, value, in_const_box=False): if isinstance(lltype.typeOf(value), lltype.Ptr): if lltype.typeOf(value).TO._gckind == 'gc': value = lltype.cast_opaque_ptr(llmemory.GCREF, value) if in_const_box: return history.ConstPtr(value) else: return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) value = cpu.cast_adr_to_int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) if in_const_box: return history.ConstObj(value) else: return history.BoxObj(value) elif isinstance(value, float): if in_const_box: return history.ConstFloat(value) else: return history.BoxFloat(value) else: value = intmask(value) if in_const_box: return history.ConstInt(value) else: return history.BoxInt(value)
def getvar(self, arg): if not arg: return ConstInt(0) try: return ConstInt(int(arg)) except ValueError: if self.is_float(arg): return ConstFloat(float(arg)) if arg.startswith('"') or arg.startswith("'"): # XXX ootype info = arg.strip("'\"") return ConstPtr( lltype.cast_opaque_ptr(llmemory.GCREF, llstr(info))) if arg.startswith('ConstClass('): name = arg[len('ConstClass('):-1] return self.get_const(name, 'class') elif arg == 'None': return None elif arg == 'NULL': if self.type_system == 'lltype': return ConstPtr(ConstPtr.value) else: return ConstObj(ConstObj.value) elif arg.startswith('ConstPtr('): name = arg[len('ConstPtr('):-1] return self.get_const(name, 'ptr') return self.vars[arg]
def test_rewrite_assembler_1(self): # check rewriting of ConstPtrs class MyFakeCPU: def cast_adr_to_int(self, adr): stored_addr = adr.address[0] assert stored_addr == llmemory.cast_ptr_to_adr(s_gcref) return 43 S = lltype.GcStruct('S') s = lltype.malloc(S) s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) v_random_box = BoxPtr() v_result = BoxInt() operations = [ ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr gc_ll_descr.rewrite_assembler(MyFakeCPU(), operations) assert len(operations) == 2 assert operations[0].opnum == rop.GETFIELD_RAW assert operations[0].args == [ConstInt(43)] assert operations[0].descr == gc_ll_descr.single_gcref_descr v_box = operations[0].result assert isinstance(v_box, BoxPtr) assert operations[1].opnum == rop.OOIS assert operations[1].args == [v_random_box, v_box] assert operations[1].result == v_result
def wrap(cpu, value, in_const_box=False): if isinstance(lltype.typeOf(value), lltype.Ptr): if lltype.typeOf(value).TO._gckind == 'gc': value = lltype.cast_opaque_ptr(llmemory.GCREF, value) if in_const_box: return history.ConstPtr(value) else: return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) value = cpu.cast_adr_to_int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) if in_const_box: return history.ConstObj(value) else: return history.BoxObj(value) elif isinstance(value, float): if in_const_box: return history.ConstFloat(value) else: return history.BoxFloat(value) else: value = intmask(value) if in_const_box: return history.ConstInt(value) else: return history.BoxInt(value)
def wrap(cpu, value, in_const_box=False): if isinstance(lltype.typeOf(value), lltype.Ptr): if lltype.typeOf(value).TO._gckind == 'gc': value = lltype.cast_opaque_ptr(llmemory.GCREF, value) if in_const_box: return history.ConstPtr(value) else: return history.BoxPtr(value) else: adr = llmemory.cast_ptr_to_adr(value) value = heaptracker.adr2int(adr) # fall through to the end of the function elif isinstance(lltype.typeOf(value), ootype.OOType): value = ootype.cast_to_object(value) if in_const_box: return history.ConstObj(value) else: return history.BoxObj(value) elif isinstance(value, float): value = longlong.getfloatstorage(value) if in_const_box: return history.ConstFloat(value) else: return history.BoxFloat(value) elif isinstance(value, str) or isinstance(value, unicode): assert len(value) == 1 # must be a character value = ord(value) else: value = intmask(value) if in_const_box: return history.ConstInt(value) else: return history.BoxInt(value)
def test_rewrite_assembler_1(self): # check rewriting of ConstPtrs class MyFakeCPU: def cast_adr_to_int(self, adr): stored_addr = adr.address[0] assert stored_addr == llmemory.cast_ptr_to_adr(s_gcref) return 43 S = lltype.GcStruct('S') s = lltype.malloc(S) s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) v_random_box = BoxPtr() v_result = BoxInt() operations = [ ResOperation(rop.OOIS, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr gc_ll_descr.rewrite_assembler(MyFakeCPU(), operations) assert len(operations) == 2 assert operations[0].opnum == rop.GETFIELD_RAW assert operations[0].args == [ConstInt(43)] assert operations[0].descr == gc_ll_descr.single_gcref_descr v_box = operations[0].result assert isinstance(v_box, BoxPtr) assert operations[1].opnum == rop.OOIS assert operations[1].args == [v_random_box, v_box] assert operations[1].result == v_result
def test_nullity_with_guard(self): allops = [rop.INT_IS_TRUE] guards = [rop.GUARD_TRUE, rop.GUARD_FALSE] p = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(lltype.GcStruct("x"))) nullptr = lltype.nullptr(llmemory.GCREF.TO) f = BoxInt() for op in allops: for guard in guards: if op == rop.INT_IS_TRUE: bp = BoxInt(1) n = BoxInt(0) else: bp = BoxPtr(p) n = BoxPtr(nullptr) for b in (bp, n): i1 = BoxInt(1) ops = [ ResOperation(rop.SAME_AS, [ConstInt(1)], i1), ResOperation(op, [b], f), ResOperation(guard, [f], None, descr=BasicFailDescr()), ResOperation(rop.FINISH, [ConstInt(0)], None, descr=BasicFailDescr()), ] ops[-2].setfailargs([i1]) looptoken = JitCellToken() self.cpu.compile_loop([b], ops, looptoken) self.cpu.execute_token(looptoken, b.value) result = self.cpu.get_latest_value_int(0) if guard == rop.GUARD_FALSE: assert result == execute(self.cpu, None, op, None, b).value else: assert result != execute(self.cpu, None, op, None, b).value
def test_repr(): S = lltype.GcStruct('S') T = lltype.GcStruct('T', ('header', S)) t = lltype.malloc(T) s = lltype.cast_pointer(lltype.Ptr(S), t) const = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, s)) assert const._getrepr_() == "*T"
def test_assemble_cast_consts(): ssarepr = SSARepr("test") S = lltype.GcStruct('S') s = lltype.malloc(S) F = lltype.FuncType([], lltype.Signed) f = lltype.functionptr(F, 'f') ssarepr.insns = [ ('int_return', Constant('X', lltype.Char)), ('int_return', Constant(unichr(0x1234), lltype.UniChar)), ('int_return', Constant(f, lltype.Ptr(F))), ('ref_return', Constant(s, lltype.Ptr(S))), ] assembler = Assembler() jitcode = assembler.assemble(ssarepr) assert jitcode.code == ("\x00\x58" "\x01\xFF" "\x01\xFE" "\x02\xFF") assert assembler.insns == {'int_return/c': 0, 'int_return/i': 1, 'ref_return/r': 2} f_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(f)) assert jitcode.constants_i == [0x1234, f_int] s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) assert jitcode.constants_r == [s_gcref]
def test_record_constptrs(self): class MyFakeCPU(object): def cast_adr_to_int(self, adr): assert adr == "some fake address" return 43 class MyFakeGCRefList(object): def get_address_of_gcref(self, s_gcref1): assert s_gcref1 == s_gcref return "some fake address" S = lltype.GcStruct('S') s = lltype.malloc(S) s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) v_random_box = BoxPtr() v_result = BoxInt() operations = [ ResOperation(rop.PTR_EQ, [v_random_box, ConstPtr(s_gcref)], v_result), ] gc_ll_descr = self.gc_ll_descr gc_ll_descr.gcrefs = MyFakeGCRefList() gcrefs = [] operations = get_deep_immutable_oplist(operations) operations2 = gc_ll_descr.rewrite_assembler(MyFakeCPU(), operations, gcrefs) assert operations2 == operations assert gcrefs == [s_gcref]
def do_force_quasi_immutable(cpu, p, mutatefielddescr): qmut_ref = cpu.bh_getfield_gc_r(p, mutatefielddescr) if qmut_ref: cpu.bh_setfield_gc_r(p, mutatefielddescr, cpu.ts.NULLREF) qmut_ptr = lltype.cast_opaque_ptr(rclass.OBJECTPTR, qmut_ref) qmut = cast_base_ptr_to_instance(QuasiImmut, qmut_ptr) qmut.invalidate()
def test_call_stubs(): c0 = GcCache(False) ARGS = [lltype.Char, lltype.Signed] RES = lltype.Char descr1 = get_call_descr(c0, ARGS, RES) def f(a, b): return 'c' call_stub = descr1.call_stub fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f) res = call_stub(rffi.cast(lltype.Signed, fnptr), [1, 2], None, None) assert res == ord('c') ARRAY = lltype.GcArray(lltype.Signed) ARGS = [lltype.Float, lltype.Ptr(ARRAY)] RES = lltype.Float def f(a, b): return float(b[0]) + a fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f) descr2 = get_call_descr(c0, ARGS, RES) a = lltype.malloc(ARRAY, 3) opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a) a[0] = 1 res = descr2.call_stub(rffi.cast(lltype.Signed, fnptr), [], [opaquea], [longlong.getfloatstorage(3.5)]) assert longlong.getrealfloat(res) == 4.5
def setup_class(cls): if option.runappdirect: py.test.skip("Can't run this test with -A") space = gettestobjspace(usemodules=('pypyjit',)) cls.space = space w_f = space.appexec([], """(): def f(): pass return f """) cls.w_f = w_f ll_code = cast_instance_to_base_ptr(w_f.code) code_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, ll_code) logger = Logger(MockSD()) oplist = parse(""" [i1, i2] i3 = int_add(i1, i2) debug_merge_point(0, 0, 0, 0, ConstPtr(ptr0)) guard_true(i3) [] """, namespace={'ptr0': code_gcref}).operations def interp_on_compile(): pypyjitdriver.on_compile(logger, LoopToken(), oplist, 'loop', 0, False, ll_code) def interp_on_compile_bridge(): pypyjitdriver.on_compile_bridge(logger, LoopToken(), oplist, 0) cls.w_on_compile = space.wrap(interp2app(interp_on_compile)) cls.w_on_compile_bridge = space.wrap(interp2app(interp_on_compile_bridge))
def func(): oldpool = llop.gc_x_swap_pool(X_POOL_PTR, lltype.nullptr(X_POOL)) a2 = make(22) newpool = llop.gc_x_swap_pool(X_POOL_PTR, oldpool) # clone a2 a2ref = lltype.cast_opaque_ptr(llmemory.GCREF, a2) clonedata = lltype.malloc(X_CLONE) clonedata.gcobjectptr = a2ref clonedata.pool = newpool llop.gc_x_clone(lltype.Void, clonedata) a2copyref = clonedata.gcobjectptr a2copy = lltype.cast_opaque_ptr(lltype.Ptr(A), a2copyref) a2copy.b.x = 44 a2copy.more[0].x = 440 a2copy.more[1].x = 441 return a2.b.x * 1000000 + a2.more[0].x * 1000 + a2.more[1].x
def test_get_current_qmut_instance(): accessor = FieldListAccessor() accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE}) STRUCT = lltype.GcStruct('Foo', ('inst_x', lltype.Signed), ('mutate_x', rclass.OBJECTPTR), hints={'immutable_fields': accessor}) foo = lltype.malloc(STRUCT, zero=True) foo.inst_x = 42 assert not foo.mutate_x class FakeCPU: ts = typesystem.llhelper def bh_getfield_gc_r(self, gcref, fielddescr): assert fielddescr == mutatefielddescr foo = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref) result = foo.mutate_x return lltype.cast_opaque_ptr(llmemory.GCREF, result) def bh_setfield_gc_r(self, gcref, fielddescr, newvalue_gcref): assert fielddescr == mutatefielddescr foo = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref) newvalue = lltype.cast_opaque_ptr(rclass.OBJECTPTR, newvalue_gcref) foo.mutate_x = newvalue cpu = FakeCPU() mutatefielddescr = ('fielddescr', STRUCT, 'mutate_x') foo_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, foo) qmut1 = get_current_qmut_instance(cpu, foo_gcref, mutatefielddescr) assert isinstance(qmut1, QuasiImmut) qmut2 = get_current_qmut_instance(cpu, foo_gcref, mutatefielddescr) assert qmut1 is qmut2
def g(): r = lltype.malloc(P) r.x = 1 p = llop.do_malloc_fixedsize_clear(llmemory.GCREF) # placeholder p = lltype.cast_opaque_ptr(lltype.Ptr(P), p) p.x = r.x return p.x
def getvar(self, arg): if not arg: return ConstInt(0) try: return ConstInt(int(arg)) except ValueError: if self.is_float(arg): return ConstFloat(float(arg)) if arg.startswith('"') or arg.startswith("'"): # XXX ootype info = arg.strip("'\"") return ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, llstr(info))) if arg.startswith('ConstClass('): name = arg[len('ConstClass('):-1] return self.get_const(name, 'class') elif arg == 'None': return None elif arg == 'NULL': if self.type_system == 'lltype': return ConstPtr(ConstPtr.value) else: return ConstObj(ConstObj.value) elif arg.startswith('ConstPtr('): name = arg[len('ConstPtr('):-1] return self.get_const(name, 'ptr') return self.vars[arg]
def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct): while True: ptrvars = [(v, S) for (v, S) in self.ptrvars if isinstance(S, type)] if ptrvars and r.random() < 0.8: v, S = r.choice(ptrvars) else: prebuilt_ptr_consts = [(v, S) for (v, S, _) in self.prebuilt_ptr_consts if isinstance(S, type)] if prebuilt_ptr_consts and r.random() < 0.7: v, S = r.choice(prebuilt_ptr_consts) else: if type is lltype.Struct: # create a new constant structure must_have_vtable = must_have_vtable or r.random() < 0.5 p = self.get_random_structure(r, has_vtable=must_have_vtable) else: # create a new constant array p = self.get_random_array(r) S = lltype.typeOf(p).TO v = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, p)) self.prebuilt_ptr_consts.append((v, S, self.field_values(p))) if not (must_have_vtable and S._names[0] != 'parent'): break return v, S
def yield_current_frame_to_caller(): if global_state.restart_substate == -1: # normal entry point for yield_current_frame_to_caller() # first unwind the stack u = UnwindException() s = lltype.malloc(EMPTY_STATE).header s.f_restart = INDEX_YCFTC add_frame_state(u, s) raise u # this goes to 'STATE 0' below elif global_state.restart_substate == 0: # STATE 0: we didn't do anything so far, but the stack is unwound global_state.restart_substate = -1 ycftc_state = global_state.top our_caller_state = ycftc_state.f_back caller_state = our_caller_state.f_back caller_state.f_depth = ycftc_state.f_depth - 2 # when our immediate caller finishes (which is later, when the # tasklet finishes), then we will jump to 'STATE 1' below endstate = lltype.malloc(EMPTY_STATE).header endstate.f_restart = INDEX_YCFTC + 1 our_caller_state.f_back = endstate our_caller_state.f_depth = 1 global_state.top = caller_state global_state.retval_ref = lltype.cast_opaque_ptr(SAVED_REFERENCE, our_caller_state) raise SwitchException() # this goes to the caller's caller elif global_state.restart_substate == 1: # STATE 1: this is a slight abuse of yield_current_frame_to_caller(), # as we return here when our immediate caller returns (and thus the # new tasklet finishes). global_state.restart_substate = -1 next_state = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), fetch_retval_ref()) # return a NULL state pointer to the target of the implicit switch global_state.top = next_state global_state.retval_ref = frame.null_saved_ref raise SwitchException() # this goes to the switch target given by # the 'return' at the end of our caller else: # this is never reached! But the annotator doesn't know it, # so it makes the whole function be annotated as returning a random # non-constant STATE_HEADER pointer. return lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR, global_state.top)
def yield_current_frame_to_caller(): if global_state.restart_substate == -1: # normal entry point for yield_current_frame_to_caller() # first unwind the stack u = UnwindException() s = lltype.malloc(EMPTY_STATE).header s.f_restart = INDEX_YCFTC add_frame_state(u, s) raise u # this goes to 'STATE 0' below elif global_state.restart_substate == 0: # STATE 0: we didn't do anything so far, but the stack is unwound global_state.restart_substate = -1 ycftc_state = global_state.top our_caller_state = ycftc_state.f_back caller_state = our_caller_state.f_back caller_state.f_depth = ycftc_state.f_depth - 2 # when our immediate caller finishes (which is later, when the # tasklet finishes), then we will jump to 'STATE 1' below endstate = lltype.malloc(EMPTY_STATE).header endstate.f_restart = INDEX_YCFTC + 1 our_caller_state.f_back = endstate our_caller_state.f_depth = 1 global_state.top = caller_state global_state.retval_ref = lltype.cast_opaque_ptr( SAVED_REFERENCE, our_caller_state) raise SwitchException() # this goes to the caller's caller elif global_state.restart_substate == 1: # STATE 1: this is a slight abuse of yield_current_frame_to_caller(), # as we return here when our immediate caller returns (and thus the # new tasklet finishes). global_state.restart_substate = -1 next_state = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), fetch_retval_ref()) # return a NULL state pointer to the target of the implicit switch global_state.top = next_state global_state.retval_ref = frame.null_saved_ref raise SwitchException() # this goes to the switch target given by # the 'return' at the end of our caller else: # this is never reached! But the annotator doesn't know it, # so it makes the whole function be annotated as returning a random # non-constant STATE_HEADER pointer. return lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR, global_state.top)
def fill_into(vablerti, s, base, vrti): s = lltype.cast_opaque_ptr(PTRTYPE, s) i = 0 for desc in descs: v = vrti._read_field(vablerti, desc, base, i) tgt = lltype.cast_pointer(desc.PTRTYPE, s) setattr(tgt, desc.fieldname, v) i = i + 1
def test_name_gcref(): from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.translator.c import primitive from pypy.translator.c.database import LowLevelDatabase x = lltype.cast_int_to_ptr(rclass.OBJECTPTR, 19) y = lltype.cast_opaque_ptr(llmemory.GCREF, x) db = LowLevelDatabase() assert primitive.name_gcref(y, db) == "((void*) 19)"
def _get_str(self): # for debugging only from pypy.rpython.annlowlevel import hlstr from pypy.rpython.lltypesystem import rstr try: return hlstr( lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), self.value)) except lltype.UninitializedMemoryAccess: return '<uninitialized string>'
def save_exception_memoryerr(): from pypy.rpython.annlowlevel import cast_instance_to_base_ptr save_exception() if not self.saved_exc_value: exc = MemoryError() exc = cast_instance_to_base_ptr(exc) exc = lltype.cast_opaque_ptr(llmemory.GCREF, exc) self.saved_exc_value = exc
def x_swap_pool(self, newpool): # Set newpool as the current pool (create one if newpool == NULL). # All malloc'ed objects are put into the current pool;this is a # way to separate objects depending on when they were allocated. size_gc_header = self.gcheaderbuilder.size_gc_header # invariant: each POOL GcStruct is at the _front_ of a linked list # of malloced objects. oldpool = self.curpool #llop.debug_print(lltype.Void, 'x_swap_pool', # lltype.cast_ptr_to_int(oldpool), # lltype.cast_ptr_to_int(newpool)) if not oldpool: # make a fresh pool object, which is automatically inserted at the # front of the current list oldpool = lltype.malloc(self.POOL) addr = llmemory.cast_ptr_to_adr(oldpool) addr -= size_gc_header hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) # put this new POOL object in the poolnodes list node = lltype.malloc(self.POOLNODE, flavor="raw") node.linkedlist = hdr node.nextnode = self.poolnodes self.poolnodes = node else: # manually insert oldpool at the front of the current list addr = llmemory.cast_ptr_to_adr(oldpool) addr -= size_gc_header hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) hdr.next = self.malloced_objects newpool = lltype.cast_opaque_ptr(self.POOLPTR, newpool) if newpool: # newpool is at the front of the new linked list to install addr = llmemory.cast_ptr_to_adr(newpool) addr -= size_gc_header hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) self.malloced_objects = hdr.next # invariant: now that objects in the hdr.next list are accessible # through self.malloced_objects, make sure they are not accessible # via poolnodes (which has a node pointing to newpool): hdr.next = lltype.nullptr(self.HDR) else: # start a fresh new linked list self.malloced_objects = lltype.nullptr(self.HDR) self.curpool = newpool return lltype.cast_opaque_ptr(X_POOL_PTR, oldpool)
def test_getvar_const_ptr(): x = ''' [] call(ConstPtr(func_ptr)) ''' TP = lltype.GcArray(lltype.Signed) NULL = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(TP)) loop = parse(x, None, {'func_ptr': NULL}) assert loop.operations[0].args[0].value == NULL
def test_unwrap(): S = lltype.GcStruct('S') p = lltype.malloc(S) po = lltype.cast_opaque_ptr(llmemory.GCREF, p) assert unwrap(lltype.Void, BoxInt(42)) is None assert unwrap(lltype.Signed, BoxInt(42)) == 42 assert unwrap(lltype.Char, BoxInt(42)) == chr(42) assert unwrap(lltype.Float, BoxFloat(42.5)) == 42.5 assert unwrap(lltype.Ptr(S), BoxPtr(po)) == p
def fn(): s = lltype.malloc(S) s.u = lltype.malloc(U) a = lltype.malloc(A, 1000) s2 = lltype.malloc(S) gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s) int1 = rgc.get_rpy_type_index(gcref1) gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u) int2 = rgc.get_rpy_type_index(gcref2) gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, a) int3 = rgc.get_rpy_type_index(gcref3) gcref4 = lltype.cast_opaque_ptr(llmemory.GCREF, s2) int4 = rgc.get_rpy_type_index(gcref4) assert int1 != int2 assert int1 != int3 assert int2 != int3 assert int1 == int4 return 0