<s> import array , weakref <EOL> from pypy . rpython . lltypesystem import lltype , llmemory <EOL> class ArenaError ( Exception ) : <EOL> pass <EOL> class Arena ( object ) : <EOL> object_arena_location = { } <EOL> old_object_arena_location = weakref . WeakKeyDictionary ( ) <EOL> def __init__ ( self , nbytes , zero ) : <EOL> self . nbytes = nbytes <EOL> self . usagemap = array . array ( '<STR_LIT:c>' ) <EOL> self . objectptrs = { } <EOL> self . objectsizes = { } <EOL> self . freed = False <EOL> self . reset ( zero ) <EOL> def reset ( self , zero , start = <NUM_LIT:0> , size = None ) : <EOL> self . check ( ) <EOL> if size is None : <EOL> stop = self . nbytes <EOL> else : <EOL> stop = start + llmemory . raw_malloc_usage ( size ) <EOL> assert <NUM_LIT:0> <= start <= stop <= self . nbytes <EOL> for offset , ptr in self . objectptrs . items ( ) : <EOL> size = self . objectsizes [ offset ] <EOL> if offset < start : <EOL> assert offset + size <= start , "<STR_LIT>" <EOL> elif offset + size > stop : <EOL> assert offset >= stop , "<STR_LIT>" <EOL> else : <EOL> obj = ptr . _obj <EOL> del Arena . object_arena_location [ obj ] <EOL> del self . objectptrs [ offset ] <EOL> del self . objectsizes [ offset ] <EOL> obj . _free ( ) <EOL> if zero : <EOL> initialbyte = "<STR_LIT:0>" <EOL> else : <EOL> initialbyte = "<STR_LIT:#>" <EOL> self . usagemap [ start : stop ] = array . array ( '<STR_LIT:c>' , initialbyte * ( stop - start ) ) <EOL> def check ( self ) : <EOL> if self . freed : <EOL> raise ArenaError ( "<STR_LIT>" ) <EOL> def _getid ( self ) : <EOL> address , length = self . usagemap . buffer_info ( ) <EOL> return address <EOL> def getaddr ( self , offset ) : <EOL> if not ( <NUM_LIT:0> <= offset <= self . nbytes ) : <EOL> raise ArenaError ( "<STR_LIT>" ) <EOL> return fakearenaaddress ( self , offset ) <EOL> def allocate_object ( self , offset , size ) : <EOL> self . check ( ) <EOL> bytes = llmemory . raw_malloc_usage ( size ) <EOL> if offset + bytes > self . nbytes : <EOL> raise ArenaError ( "<STR_LIT>" ) <EOL> zero = True <EOL> for c in self . usagemap [ offset : offset + bytes ] : <EOL> if c == '<STR_LIT:0>' : <EOL> pass <EOL> elif c == '<STR_LIT:#>' : <EOL> zero = False <EOL> else : <EOL> raise ArenaError ( "<STR_LIT>" ) <EOL> assert offset not in self . objectptrs <EOL> addr2 = size . _raw_malloc ( [ ] , zero = zero ) <EOL> pattern = '<STR_LIT:X>' + '<STR_LIT:x>' * ( bytes - <NUM_LIT:1> ) <EOL> self . usagemap [ offset : offset + bytes ] = array . array ( '<STR_LIT:c>' , pattern ) <EOL> self . setobject ( addr2 , offset , bytes ) <EOL> while isinstance ( size , RoundedUpForAllocation ) : <EOL> size = size . basesize <EOL> if ( isinstance ( size , llmemory . CompositeOffset ) and <EOL> isinstance ( size . offsets [ <NUM_LIT:0> ] , llmemory . GCHeaderOffset ) ) : <EOL> objaddr = addr2 + size . offsets [ <NUM_LIT:0> ] <EOL> hdrbytes = llmemory . raw_malloc_usage ( size . offsets [ <NUM_LIT:0> ] ) <EOL> objoffset = offset + hdrbytes <EOL> self . setobject ( objaddr , objoffset , bytes - hdrbytes ) <EOL> return addr2 <EOL> def setobject ( self , objaddr , offset , bytes ) : <EOL> assert bytes > <NUM_LIT:0> , ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> assert offset not in self . objectptrs <EOL> self . objectptrs [ offset ] = objaddr . ptr <EOL> self . objectsizes [ offset ] = bytes <EOL> container = objaddr . ptr . _obj <EOL> Arena . object_arena_location [ container ] = self , offset <EOL> Arena . old_object_arena_location [ container ] = self , offset <EOL> class fakearenaaddress ( llmemory . fakeaddress ) : <EOL> def __init__ ( self , arena , offset ) : <EOL> self . arena = arena <EOL> self . offset = offset <EOL> def _getptr ( self ) : <EOL> try : <EOL> return self . arena . objectptrs [ self . offset ] <EOL> except KeyError : <EOL> self . arena . check ( ) <EOL> raise ArenaError ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( self . offset , ) ) <EOL> ptr = property ( _getptr ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . arena , self . offset ) <EOL> def __add__ ( self , other ) : <EOL> if isinstance ( other , ( int , long ) ) : <EOL> position = self . offset + other <EOL> elif isinstance ( other , llmemory . AddressOffset ) : <EOL> bytes = llmemory . raw_malloc_usage ( other ) <EOL> if ( self . offset in self . arena . objectsizes and <EOL> bytes < self . arena . objectsizes [ self . offset ] ) : <EOL> return llmemory . fakeaddress . __add__ ( self , other ) <EOL> position = self . offset + bytes <EOL> else : <EOL> return NotImplemented <EOL> return self . arena . getaddr ( position ) <EOL> def __sub__ ( self , other ) : <EOL> if isinstance ( other , llmemory . AddressOffset ) : <EOL> other = llmemory . raw_malloc_usage ( other ) <EOL> if isinstance ( other , ( int , long ) ) : <EOL> return self . arena . getaddr ( self . offset - other ) <EOL> if isinstance ( other , fakearenaaddress ) : <EOL> if self . arena is not other . arena : <EOL> raise ArenaError ( "<STR_LIT>" ) <EOL> return self . offset - other . offset <EOL> return NotImplemented <EOL> def __nonzero__ ( self ) : <EOL> return True <EOL> def compare_with_fakeaddr ( self , other ) : <EOL> other = other . _fixup ( ) <EOL> if not other : <EOL> return None , None <EOL> obj = other . ptr . _obj <EOL> innerobject = False <EOL> while obj not in Arena . object_arena_location : <EOL> obj = obj . _parentstructure ( ) <EOL> if obj is None : <EOL> return None , None <EOL> innerobject = True <EOL> arena , offset = Arena . object_arena_location [ obj ] <EOL> if innerobject : <EOL> if self . arena is arena : <EOL> objectsize = arena . objectsizes [ offset ] <EOL> if offset < self . offset < offset + objectsize : <EOL> raise AssertionError ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> offset += objectsize // <NUM_LIT:2> <EOL> return arena , offset <EOL> def __eq__ ( self , other ) : <EOL> if isinstance ( other , fakearenaaddress ) : <EOL> arena = other . arena <EOL> offset = other . offset <EOL> elif isinstance ( other , llmemory . fakeaddress ) : <EOL> arena , offset = self . compare_with_fakeaddr ( other ) <EOL> else : <EOL> return llmemory . fakeaddress . __eq__ ( self , other ) <EOL> return self . arena is arena and self . offset == offset <EOL> def __lt__ ( self , other ) : <EOL> if isinstance ( other , fakearenaaddress ) : <EOL> arena = other . arena <EOL> offset = other . offset <EOL> elif isinstance ( other , llmemory . fakeaddress ) : <EOL> arena , offset = self . compare_with_fakeaddr ( other ) <EOL> if arena is None : <EOL> return False <EOL> else : <EOL> raise TypeError ( "<STR_LIT>" % ( <EOL> self . __class__ . __name__ , other . __class__ . __name__ ) ) <EOL> if self . arena is arena : <EOL> return self . offset < offset <EOL> else : <EOL> return self . arena . _getid ( ) < arena . _getid ( ) <EOL> def _cast_to_int ( self ) : <EOL> return self . arena . _getid ( ) + self . offset <EOL> def _getfakearenaaddress ( addr ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( addr , fakearenaaddress ) : <EOL> return addr <EOL> else : <EOL> assert isinstance ( addr , llmemory . fakeaddress ) <EOL> assert addr , "<STR_LIT>" <EOL> obj = addr . ptr . _getobj ( check = False ) <EOL> return _oldobj_to_address ( obj ) <EOL> def _oldobj_to_address ( obj ) : <EOL> obj = obj . _normalizedcontainer ( check = False ) <EOL> try : <EOL> arena , offset = Arena . old_object_arena_location [ obj ] <EOL> except KeyError : <EOL> if obj . _was_freed ( ) : <EOL> msg = "<STR_LIT>" <EOL> else : <EOL> msg = "<STR_LIT>" <EOL> raise RuntimeError ( msg % ( obj , ) ) <EOL> return arena . getaddr ( offset ) <EOL> class RoundedUpForAllocation ( llmemory . AddressOffset ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , basesize , minsize ) : <EOL> assert isinstance ( basesize , llmemory . AddressOffset ) <EOL> assert isinstance ( minsize , llmemory . AddressOffset ) or minsize == <NUM_LIT:0> <EOL> self . basesize = basesize <EOL> self . minsize = minsize <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . basesize , <EOL> self . minsize ) <EOL> def known_nonneg ( self ) : <EOL> return self . basesize . known_nonneg ( ) <EOL> def ref ( self , ptr ) : <EOL> return self . basesize . ref ( ptr ) <EOL> def _raw_malloc ( self , rest , zero ) : <EOL> return self . basesize . _raw_malloc ( rest , zero = zero ) <EOL> def raw_memcopy ( self , srcadr , dstadr ) : <EOL> self . basesize . raw_memcopy ( srcadr , dstadr ) <EOL> def arena_malloc ( nbytes , zero ) : <EOL> """<STR_LIT>""" <EOL> return Arena ( nbytes , zero ) . getaddr ( <NUM_LIT:0> ) <EOL> def arena_free ( arena_addr ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( arena_addr , fakearenaaddress ) <EOL> assert arena_addr . offset == <NUM_LIT:0> <EOL> arena_addr . arena . reset ( False ) <EOL> arena_addr . arena . freed = True <EOL> def arena_reset ( arena_addr , size , zero ) : <EOL> """<STR_LIT>""" <EOL> arena_addr = _getfakearenaaddress ( arena_addr ) <EOL> arena_addr . arena . reset ( zero , arena_addr . offset , size ) <EOL> def arena_reserve ( addr , size , check_alignment = True ) : <EOL> """<STR_LIT>""" <EOL> from pypy . rpython . memory . lltypelayout import memory_alignment <EOL> addr = _getfakearenaaddress ( addr ) <EOL> if check_alignment and ( addr . offset & ( memory_alignment - <NUM_LIT:1> ) ) != <NUM_LIT:0> : <EOL> raise ArenaError ( "<STR_LIT>" <EOL> % ( addr . offset , ) ) <EOL> addr . arena . allocate_object ( addr . offset , size ) <EOL> def round_up_for_allocation ( size , minsize = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> return _round_up_for_allocation ( size , minsize ) <EOL> def _round_up_for_allocation ( size , minsize ) : <EOL> return RoundedUpForAllocation ( size , minsize ) <EOL> def arena_new_view ( ptr ) : <EOL> """<STR_LIT>""" <EOL> return Arena ( ptr . arena . nbytes , False ) . getaddr ( <NUM_LIT:0> ) <EOL> import os , sys <EOL> from pypy . rpython . lltypesystem import rffi , lltype <EOL> from pypy . rpython . extfunc import register_external <EOL> from pypy . rlib . objectmodel import CDefinedIntSymbolic <EOL> if sys . platform == '<STR_LIT>' : <EOL> from pypy . rpython . tool import rffi_platform <EOL> MADV_DONTNEED = rffi_platform . getconstantinteger ( '<STR_LIT>' , <EOL> '<STR_LIT>' ) <EOL> linux_madvise = rffi . llexternal ( '<STR_LIT>' , <EOL> [ llmemory . Address , rffi . SIZE_T , rffi . INT ] , <EOL> rffi . INT , <EOL> sandboxsafe = True , _nowrapper = True ) <EOL> linux_getpagesize = rffi . llexternal ( '<STR_LIT>' , [ ] , rffi . INT , <EOL> sandboxsafe = True , _nowrapper = True ) <EOL> class LinuxPageSize : <EOL> def __init__ ( self ) : <EOL> self . pagesize = <NUM_LIT:0> <EOL> _freeze_ = __init__ <EOL> linuxpagesize = LinuxPageSize ( ) <EOL> def clear_large_memory_chunk ( baseaddr , size ) : <EOL> pagesize = linuxpagesize . pagesize <EOL> if pagesize == <NUM_LIT:0> : <EOL> pagesize = rffi . cast ( lltype . Signed , linux_getpagesize ( ) ) <EOL> linuxpagesize . pagesize = pagesize <EOL> if size > <NUM_LIT:2> * pagesize : <EOL> lowbits = rffi . cast ( lltype . Signed , baseaddr ) & ( pagesize - <NUM_LIT:1> ) <EOL> if lowbits : <EOL> partpage = pagesize - lowbits <EOL> llmemory . raw_memclear ( baseaddr , partpage ) <EOL> baseaddr += partpage <EOL> size -= partpage <EOL> length = size & - pagesize <EOL> madv_length = rffi . cast ( rffi . SIZE_T , length ) <EOL> madv_flags = rffi . cast ( rffi . INT , MADV_DONTNEED ) <EOL> err = linux_madvise ( baseaddr , madv_length , madv_flags ) <EOL> if rffi . cast ( lltype . Signed , err ) == <NUM_LIT:0> : <EOL> baseaddr += length <EOL> size -= length <EOL> if size > <NUM_LIT:0> : <EOL> llmemory . raw_memclear ( baseaddr , size ) <EOL> elif os . name == '<STR_LIT>' : <EOL> READ_MAX = ( sys . maxint // <NUM_LIT:4> ) + <NUM_LIT:1> <EOL> raw_os_open = rffi . llexternal ( '<STR_LIT>' , <EOL> [ rffi . CCHARP , rffi . INT , rffi . MODE_T ] , <EOL> rffi . INT , <EOL> sandboxsafe = True , _nowrapper = True ) <EOL> raw_os_read = rffi . llexternal ( '<STR_LIT>' , <EOL> [ rffi . INT , llmemory . Address , rffi . SIZE_T ] , <EOL> rffi . SIZE_T , <EOL> sandboxsafe = True , _nowrapper = True ) <EOL> raw_os_close = rffi . llexternal ( '<STR_LIT>' , <EOL> [ rffi . INT ] , <EOL> rffi . INT , <EOL> sandboxsafe = True , _nowrapper = True ) <EOL> _dev_zero = rffi . str2charp ( '<STR_LIT>' ) <EOL> def clear_large_memory_chunk ( baseaddr , size ) : <EOL> fd = raw_os_open ( _dev_zero , <EOL> rffi . cast ( rffi . INT , os . O_RDONLY ) , <EOL> rffi . cast ( rffi . MODE_T , <NUM_LIT:0> <NUM_LIT> ) ) <EOL> if rffi . cast ( lltype . Signed , fd ) != - <NUM_LIT:1> : <EOL> while size > <NUM_LIT:0> : <EOL> size1 = rffi . cast ( rffi . SIZE_T , min ( READ_MAX , size ) ) <EOL> count = raw_os_read ( fd , baseaddr , size1 ) <EOL> count = rffi . cast ( lltype . Signed , count ) <EOL> if count <= <NUM_LIT:0> : <EOL> break <EOL> size -= count <EOL> baseaddr += count <EOL> raw_os_close ( fd ) <EOL> if size > <NUM_LIT:0> : <EOL> llmemory . raw_memclear ( baseaddr , size ) <EOL> else : <EOL> clear_large_memory_chunk = llmemory . raw_memclear <EOL> def llimpl_arena_malloc ( nbytes , zero ) : <EOL> addr = llmemory . raw_malloc ( nbytes ) <EOL> if zero and bool ( addr ) : <EOL> clear_large_memory_chunk ( addr , nbytes ) <EOL> return addr <EOL> register_external ( arena_malloc , [ int , bool ] , llmemory . Address , <EOL> '<STR_LIT>' , <EOL> llimpl = llimpl_arena_malloc , <EOL> llfakeimpl = arena_malloc , <EOL> sandboxsafe = True ) <EOL> def llimpl_arena_free ( arena_addr ) : <EOL> llmemory . raw_free ( arena_addr ) <EOL> register_external ( arena_free , [ llmemory . Address ] , None , '<STR_LIT>' , <EOL> llimpl = llimpl_arena_free , <EOL> llfakeimpl = arena_free , <EOL> sandboxsafe = True ) <EOL> def llimpl_arena_reset ( arena_addr , size , zero ) : <EOL> if zero : <EOL> if zero == <NUM_LIT:1> : <EOL> clear_large_memory_chunk ( arena_addr , size ) <EOL> else : <EOL> llmemory . raw_memclear ( arena_addr , size ) <EOL> register_external ( arena_reset , [ llmemory . Address , int , int ] , None , <EOL> '<STR_LIT>' , <EOL> llimpl = llimpl_arena_reset , <EOL> llfakeimpl = arena_reset , <EOL> sandboxsafe = True ) <EOL> def llimpl_arena_reserve ( addr , size ) : <EOL> pass <EOL> register_external ( arena_reserve , [ llmemory . Address , int ] , None , <EOL> '<STR_LIT>' , <EOL> llimpl = llimpl_arena_reserve , <EOL> llfakeimpl = arena_reserve , <EOL> sandboxsafe = True ) <EOL> llimpl_round_up_for_allocation = rffi . llexternal ( '<STR_LIT>' , <EOL> [ lltype . Signed , lltype . Signed ] , <EOL> lltype . Signed , <EOL> sandboxsafe = True , <EOL> _nowrapper = True ) <EOL> register_external ( _round_up_for_allocation , [ int , int ] , int , <EOL> '<STR_LIT>' , <EOL> llimpl = llimpl_round_up_for_allocation , <EOL> llfakeimpl = round_up_for_allocation , <EOL> sandboxsafe = True ) <EOL> def llimpl_arena_new_view ( addr ) : <EOL> return addr <EOL> register_external ( arena_new_view , [ llmemory . Address ] , llmemory . Address , <EOL> '<STR_LIT>' , llimpl = llimpl_arena_new_view , <EOL> llfakeimpl = arena_new_view , sandboxsafe = True ) </s>
