[pypy-svn] r47333 - in pypy/dist/pypy/rpython: . lltypesystem lltypesystem/test
arigo at codespeak.net
arigo at codespeak.net
Tue Oct 9 12:26:32 CEST 2007
Author: arigo
Date: Tue Oct 9 12:26:31 2007
New Revision: 47333
Modified:
pypy/dist/pypy/rpython/extfunc.py
pypy/dist/pypy/rpython/llinterp.py
pypy/dist/pypy/rpython/lltypesystem/llarena.py
pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py
Log:
Annotate and translate the arena functions.
Extended the register_external() logic so that if we specify both
llimpl and llfakeimpl, the latter is called by the llinterpreter
and the former is translated to C.
Modified: pypy/dist/pypy/rpython/extfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunc.py (original)
+++ pypy/dist/pypy/rpython/extfunc.py Tue Oct 9 12:26:31 2007
@@ -191,6 +191,8 @@
'_name': self.name,
'_safe_not_sandboxed': self.safe_not_sandboxed,
}
+ if hasattr(self, fake_method_name):
+ impl._llfnobjattrs_['_fakeimpl'] = fakeimpl
obj = rtyper.getannmixlevel().delayedfunction(
impl, signature_args, hop.s_result)
else:
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Tue Oct 9 12:26:31 2007
@@ -439,8 +439,12 @@
def invoke_callable_with_pyexceptions(self, fptr, *args):
obj = self.llinterpreter.typer.type_system.deref(fptr)
+ if hasattr(obj, '_fakeimpl'):
+ f = obj._fakeimpl
+ else:
+ f = obj._callable
try:
- return obj._callable(*args)
+ return f(*args)
except LLException, e:
raise
except Exception, e:
@@ -606,6 +610,8 @@
def perform_call(self, f, ARGS, args):
fobj = self.llinterpreter.typer.type_system.deref(f)
+ if hasattr(fobj, '_fakeimpl'):
+ return self.invoke_callable_with_pyexceptions(f, *args)
has_callable = getattr(fobj, '_callable', None) is not None
if has_callable and getattr(fobj._callable, 'suggested_primitive', False):
return self.invoke_callable_with_pyexceptions(f, *args)
Modified: pypy/dist/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/llarena.py Tue Oct 9 12:26:31 2007
@@ -169,11 +169,10 @@
# ____________________________________________________________
#
-# Public interface: arena_malloc(), arena_free() and arena_reset()
-# which directly correspond to lloperations. Although the operations
-# are similar to raw_malloc(), raw_free() and raw_memclear(), the
-# backend can choose a different implementation for arenas, one that
-# is more suited to very large chunks of memory.
+# Public interface: arena_malloc(), arena_free(), arena_reset()
+# are similar to raw_malloc(), raw_free() and raw_memclear(), but
+# work with fakearenaaddresses on which arbitrary arithmetic is
+# possible even on top of the llinterpreter.
def arena_malloc(nbytes, zero):
"""Allocate and return a new arena, optionally zero-initialized."""
@@ -201,3 +200,80 @@
this is used to know what type of lltype object to allocate."""
assert isinstance(addr, fakearenaaddress)
addr.arena.allocate_object(addr.offset, size)
+
+# ____________________________________________________________
+#
+# Translation support: the functions above turn into the code below.
+# We can tweak these implementations to be more suited to very large
+# chunks of memory.
+
+import os, sys
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.extfunc import register_external
+
+if os.name == 'posix':
+ READ_MAX = (sys.maxint//4) + 1 # upper bound on reads to avoid surprises
+ os_read = rffi.llexternal('read',
+ [rffi.INT, llmemory.Address, rffi.SIZE_T],
+ rffi.SIZE_T)
+
+ def clear_large_memory_chunk(baseaddr, size):
+ # on Linux at least, reading from /dev/zero is the fastest way
+ # to clear arenas, because the kernel knows that it doesn't
+ # need to even allocate the pages before they are used
+ try:
+ fd = os.open('/dev/zero', os.O_RDONLY, 0644)
+ except OSError:
+ pass
+ else:
+ while size > 0:
+ count = os_read(fd, baseaddr, min(READ_MAX, size))
+ count = rffi.cast(lltype.Signed, count)
+ if count < 0:
+ break
+ size -= count
+ baseaddr += count
+ os.close(fd)
+
+ if size > 0: # reading from /dev/zero failed, fallback
+ llmemory.raw_memclear(baseaddr, size)
+
+else:
+ # XXX any better implementation on Windows?
+ clear_large_memory_chunk = llmemory.raw_memclear
+
+
+def llimpl_arena_malloc(nbytes, zero):
+ addr = llmemory.raw_malloc(nbytes)
+ if zero:
+ clear_large_memory_chunk(addr, nbytes)
+ return addr
+register_external(arena_malloc, [int, bool], llmemory.Address,
+ 'll_arena.arena_malloc',
+ llimpl=llimpl_arena_malloc,
+ llfakeimpl=arena_malloc,
+ sandboxsafe=True)
+
+def llimpl_arena_free(arena_addr):
+ llmemory.raw_free(arena_addr)
+register_external(arena_free, [llmemory.Address], None, 'll_arena.arena_free',
+ llimpl=llimpl_arena_free,
+ llfakeimpl=arena_free,
+ sandboxsafe=True)
+
+def llimpl_arena_reset(arena_addr, myarenasize, zero):
+ if zero:
+ clear_large_memory_chunk(arena_addr, myarenasize)
+register_external(arena_reset, [llmemory.Address, int, bool], None,
+ 'll_arena.arena_reset',
+ llimpl=llimpl_arena_reset,
+ llfakeimpl=arena_reset,
+ sandboxsafe=True)
+
+def llimpl_arena_reserve(addr, size):
+ pass
+register_external(arena_reserve, [llmemory.Address, int], None,
+ 'll_arena.arena_reserve',
+ llimpl=llimpl_arena_reserve,
+ llfakeimpl=arena_reserve,
+ sandboxsafe=True)
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py Tue Oct 9 12:26:31 2007
@@ -2,7 +2,7 @@
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr
from pypy.rpython.lltypesystem.llarena import arena_malloc, arena_reset
-from pypy.rpython.lltypesystem.llarena import arena_reserve
+from pypy.rpython.lltypesystem.llarena import arena_reserve, arena_free
from pypy.rpython.lltypesystem.llarena import ArenaError
def test_arena():
@@ -106,13 +106,32 @@
assert lt(a, b+19)
+SX = lltype.Struct('S', ('x',lltype.Signed))
+
def test_look_inside_object():
- S = lltype.Struct('S', ('x',lltype.Signed))
- SPTR = lltype.Ptr(S)
- a = arena_malloc(50, False)
+ SPTR = lltype.Ptr(SX)
+ myarenasize = 50
+ a = arena_malloc(myarenasize, False)
b = a + 4
- arena_reserve(b, llmemory.sizeof(S))
- (b + llmemory.offsetof(S, 'x')).signed[0] = 123
+ arena_reserve(b, llmemory.sizeof(SX))
+ (b + llmemory.offsetof(SX, 'x')).signed[0] = 123
assert llmemory.cast_adr_to_ptr(b, SPTR).x == 123
llmemory.cast_adr_to_ptr(b, SPTR).x += 1
- assert (b + llmemory.offsetof(S, 'x')).signed[0] == 124
+ assert (b + llmemory.offsetof(SX, 'x')).signed[0] == 124
+ arena_reset(a, myarenasize, True)
+ arena_reserve(b, llmemory.sizeof(SX))
+ assert llmemory.cast_adr_to_ptr(b, SPTR).x == 0
+ arena_free(a)
+ return 42
+
+
+def test_llinterpreted():
+ from pypy.rpython.test.test_llinterp import interpret
+ res = interpret(test_look_inside_object, [])
+ assert res == 42
+
+def test_compiled():
+ from pypy.translator.c.test.test_genc import compile
+ fn = compile(test_look_inside_object, [])
+ res = fn()
+ assert res == 42
More information about the Pypy-commit
mailing list