def test_gc_offsets(): STRUCT = lltype.GcStruct('S1', ('x', lltype.Signed), ('y', lltype.Char)) ARRAY = lltype.GcArray(lltype.Signed) s1 = llarena.round_up_for_allocation(llmemory.sizeof(STRUCT)) s2 = llmemory.offsetof(STRUCT, 'x') s3 = llmemory.ArrayLengthOffset(ARRAY) s4 = llmemory.sizeof(ARRAY, 0) s5 = llmemory.ArrayItemsOffset(ARRAY) def fn(): return (s1 * 100000000 + s2 * 1000000 + s3 * 10000 + s4 * 100 + s5) mod, f = compile_test(fn, [], gcpolicy="semispace") res = f() i1 = (res // 100000000) % 100 i2 = (res // 1000000) % 100 i3 = (res // 10000) % 100 i4 = (res // 100) % 100 i5 = (res // 1) % 100 assert i1 % 4 == 0 assert 12 <= i1 <= 24 assert 4 <= i2 <= i1 - 8 assert 4 <= i3 <= 12 assert i4 == i5 assert i3 + 4 <= i5
def test_vararray(): S1 = lltype.Struct('s1', ('s', lltype.Signed)) A = lltype.Array(S1) S2 = lltype.GcStruct('s2', ('b', lltype.Signed), ('a', A)) S1PTR = lltype.Ptr(S1) offset1 = (llmemory.offsetof(S2, 'a') + llmemory.ArrayItemsOffset(A) + llmemory.ItemOffset(S1, 21) + llmemory.offsetof(S1, 's')) offset2 = (llmemory.offsetof(S2, 'a') + llmemory.ArrayItemsOffset(A) + llmemory.ItemOffset(S1, 21)) def vararray(n): s = lltype.malloc(S2, n) adr = llmemory.cast_ptr_to_adr(s) s.a[n].s = n s1 = llmemory.cast_adr_to_ptr(adr + offset2, S1PTR) return (adr + offset1).signed[0] + s1.s fn = compile_function(vararray, [int]) assert fn(21) == 42
def finish_tables(self): table = self.layoutbuilder.flatten_table() log.info("assigned %s typeids" % (len(table), )) log.info("added %s push/pop stack root instructions" % (self.num_pushs, )) if self.write_barrier_ptr: log.info("inserted %s write barrier calls" % (self.write_barrier_calls, )) # replace the type_info_table pointer in gcdata -- at this point, # the database is in principle complete, so it has already seen # the delayed pointer. We need to force it to consider the new # array now. self.gcdata.type_info_table._become(table) # XXX because we call inputconst already in replace_malloc, we can't # modify the instance, we have to modify the 'rtyped instance' # instead. horrors. is there a better way? s_gcdata = self.translator.annotator.bookkeeper.immutablevalue( self.gcdata) r_gcdata = self.translator.rtyper.getrepr(s_gcdata) ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value addresses_of_static_ptrs = ( self.layoutbuilder.addresses_of_static_ptrs_in_nongc + self.layoutbuilder.addresses_of_static_ptrs) log.info("found %s static roots" % (len(addresses_of_static_ptrs), )) additional_ptrs = self.layoutbuilder.additional_roots_sources log.info("additional %d potential static roots" % additional_ptrs) ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address), len(addresses_of_static_ptrs) + additional_ptrs, immortal=True) for i in range(len(addresses_of_static_ptrs)): ll_static_roots_inside[i] = addresses_of_static_ptrs[i] ll_instance.inst_static_root_start = llmemory.cast_ptr_to_adr( ll_static_roots_inside) + llmemory.ArrayItemsOffset( lltype.Array(llmemory.Address)) ll_instance.inst_static_root_nongcend = ll_instance.inst_static_root_start + llmemory.sizeof( llmemory.Address) * len( self.layoutbuilder.addresses_of_static_ptrs_in_nongc) ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof( llmemory.Address) * len(addresses_of_static_ptrs) newgcdependencies = [] newgcdependencies.append(ll_static_roots_inside) self.write_typeid_list() return newgcdependencies
def test_sizeof_array_with_no_length(): A = lltype.GcArray(lltype.Signed, hints={'nolength': True}) B = lltype.Array(lltype.Signed, hints={'nolength': True}) a = lltype.malloc(A, 5, zero=True) arraysize = llmemory.itemoffsetof(A, 10) signedsize = llmemory.sizeof(lltype.Signed) b_items = llmemory.ArrayItemsOffset(B) def f(): return (a[0] + arraysize - signedsize * 10) * 1000 + b_items fn = compile_function(f, []) res = fn() assert res == 0
def test_null_padding(): from pypy.rpython.lltypesystem import llmemory from pypy.rpython.lltypesystem import rstr chars_offset = llmemory.FieldOffset(rstr.STR, 'chars') + \ llmemory.ArrayItemsOffset(rstr.STR.chars) # sadly, there's no way of forcing this to fail if the strings # are allocated in a region of memory such that they just # happen to get a NUL byte anyway :/ (a debug build will # always fail though) def trailing_byte(s): adr_s = llmemory.cast_ptr_to_adr(s) return (adr_s + chars_offset).char[len(s)] def f(x): r = 0 for i in range(x): r += ord(trailing_byte(' '*(100-x*x))) return r fn = compile_function(f, [int]) res = fn(10) assert res == 0
def arrayToken(A): return (llmemory.ArrayLengthOffset(A), llmemory.ArrayItemsOffset(A), llmemory.ItemOffset(A.OF), RLLVMGenOp.kindToken(A.OF))
def arrayToken(A): return ((llmemory.ArrayLengthOffset(A), WORD), llmemory.ArrayItemsOffset(A), llmemory.ItemOffset(A.OF))