Author: Armin Rigo <[email protected]>
Branch: stm-thread-2
Changeset: r57154:952723b65bd2
Date: 2012-09-05 17:50 +0200
http://bitbucket.org/pypy/pypy/changeset/952723b65bd2/
Log: In-progress
diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -1,6 +1,6 @@
from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
+from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage, raw_memcopy
from pypy.rpython.memory.gc.base import GCBase, MovingGCBase
from pypy.rpython.memory.support import mangle_hash
from pypy.rpython.annlowlevel import llhelper
@@ -174,11 +174,9 @@
self.nursery_size = nursery_size
self.sharedarea = stmshared.StmGCSharedArea(self)
#
- def _stm_getsize(obj): # indirection to hide 'self'
- return self.get_size(obj)
- self._stm_getsize = _stm_getsize
- #
- self.declare_write_barrier()
+ def _stm_duplicate(obj): # indirection to hide 'self'
+ return self.stm_duplicate(obj)
+ self._stm_duplicate = _stm_duplicate
def setup(self):
"""Called at run-time to initialize the GC."""
@@ -307,134 +305,26 @@
flags |= GCFLAG_GLOBAL
self.init_gc_object(addr, typeid16, flags)
- # ----------
-
-## TURNED OFF, maybe temporarily: the following logic is now entirely
-## done by C macros and functions.
-##
-## def declare_reader(self, size, TYPE):
-## # Reading functions. Defined here to avoid the extra burden of
-## # passing 'self' explicitly.
-## assert rffi.sizeof(TYPE) == size
-## PTYPE = rffi.CArrayPtr(TYPE)
-## stm_read_int = getattr(self.stm_operations, 'stm_read_int%d' % size)
-## #
-## @always_inline
-## def reader(obj, offset):
-## if self.header(obj).tid & GCFLAG_GLOBAL == 0:
-## adr = rffi.cast(PTYPE, obj + offset)
-## return adr[0] # local obj: read directly
-## else:
-## return stm_read_int(obj, offset) # else: call a helper
-## setattr(self, 'read_int%d' % size, reader)
-## #
-## @dont_inline
-## def _read_word_global(obj, offset):
-## hdr = self.header(obj)
-## if hdr.tid & GCFLAG_WAS_COPIED != 0:
-## #
-## # Look up in the thread-local dictionary.
-## localobj = stm_operations.tldict_lookup(obj)
-## if localobj:
-## ll_assert(self.header(localobj).tid & GCFLAG_GLOBAL == 0,
-## "stm_read: tldict_lookup() -> GLOBAL obj")
-## return (localobj + offset).signed[0]
-## #
-## return stm_operations.stm_read_word(obj, offset)
-
-
- def declare_write_barrier(self):
- # Write barrier. Defined here to avoid the extra burden of
- # passing 'self' explicitly.
- stm_operations = self.stm_operations
+ def stm_duplicate(self, obj):
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ size = self.get_size(obj)
+ totalsize = size_gc_header + size
+ tls = self.get_tls()
+ try:
+ localobj = tls.malloc_local_copy(totalsize)
+ except MemoryError:
+ # should not really let the exception propagate.
+ # XXX do something slightly better, like abort the transaction
+ # and raise a MemoryError when retrying
+ fatalerror("FIXME: MemoryError in stm_duplicate")
+ return llmemory.NULL
#
- @always_inline
- def stm_writebarrier(obj):
- """The write barrier must be called on any object that may be
- a global. It looks for, and possibly makes, a local copy of
- this object. The result of this call is the local copy ---
- or 'obj' itself if it is already local.
- """
- if self.header(obj).tid & GCFLAG_GLOBAL != 0:
- obj = _stm_write_barrier_global(obj)
- return obj
- self.stm_writebarrier = stm_writebarrier
- #
- @dont_inline
- def _stm_write_barrier_global(obj):
- # find or make a local copy of the global object
- hdr = self.header(obj)
- if hdr.tid & GCFLAG_WAS_COPIED == 0:
- #
- # in this case, we are sure that we don't have a copy
- hdr.tid |= GCFLAG_WAS_COPIED
- # ^^^ non-protected write, but concurrent writes should
- # have the same effect, so fine
- else:
- # in this case, we need to check first
- localobj = stm_operations.tldict_lookup(obj)
- if localobj:
- hdr = self.header(localobj)
- ll_assert(hdr.tid & GCFLAG_GLOBAL == 0,
- "stm_write: tldict_lookup() -> GLOBAL obj")
- ll_assert(hdr.tid & GCFLAG_WAS_COPIED != 0,
- "stm_write: tldict_lookup() -> non-COPIED obj")
- return localobj
- #
- # Here, we need to really make a local copy
- size = self.get_size(obj)
- totalsize = self.gcheaderbuilder.size_gc_header + size
- tls = self.get_tls()
- try:
- localobj = tls.malloc_local_copy(totalsize)
- except MemoryError:
- # should not really let the exception propagate.
- # XXX do something slightly better, like abort the transaction
- # and raise a MemoryError when retrying
- fatalerror("FIXME: MemoryError in _stm_write_barrier_global")
- return llmemory.NULL
- #
- # Initialize the copy by doing an stm raw copy of the bytes
- stm_operations.stm_copy_transactional_to_raw(obj, localobj, size)
- #
- # The raw copy done above does not include the header fields.
- hdr = self.header(obj)
- localhdr = self.header(localobj)
- GCFLAGS = (GCFLAG_GLOBAL | GCFLAG_WAS_COPIED | GCFLAG_VISITED)
- ll_assert(hdr.tid & GCFLAGS == (GCFLAG_GLOBAL | GCFLAG_WAS_COPIED),
- "stm_write: bogus flags on source object")
- #
- # Remove the GCFLAG_GLOBAL from the copy, and add GCFLAG_VISITED
- localhdr.tid = hdr.tid + (GCFLAG_VISITED - GCFLAG_GLOBAL)
- #
- # Set the 'version' field of the local copy to be a pointer
- # to the global obj. (The field is called 'version' because
- # of its use by the C STM library: on global objects (only),
- # it is a version number.)
- localhdr.version = obj
- #
- # Register the object as a valid copy
- stm_operations.tldict_add(obj, localobj)
- #
- return localobj
- self._stm_write_barrier_global = _stm_write_barrier_global
- #
- def stm_normalize_global(obj):
- """Normalize a pointer for the purpose of equality
- comparison with another pointer. If 'obj' is the local
- version of an existing global object, then returns the
- global object. Don't use for e.g. hashing, because if 'obj'
- is a local object, it just returns 'obj' --- even for nursery
- objects, which move at the next local collection.
- """
- if not obj:
- return obj
- tid = self.header(obj).tid
- if tid & (GCFLAG_GLOBAL|GCFLAG_WAS_COPIED) != GCFLAG_WAS_COPIED:
- return obj
- # the only relevant case: it's the local copy of a global object
- return self.header(obj).version
- self.stm_normalize_global = stm_normalize_global
+ # Initialize the copy by doing a memcpy of the bytes.
+ # The object header of localobj will then be fixed by the C code.
+ llmemory.raw_memcopy(obj - size_gc_header,
+ localobj - size_gc_header,
+ totalsize)
+ return localobj
# ----------
# id() and identityhash() support
diff --git a/pypy/rpython/memory/gc/test/test_stmgc.py
b/pypy/rpython/memory/gc/test/test_stmgc.py
--- a/pypy/rpython/memory/gc/test/test_stmgc.py
+++ b/pypy/rpython/memory/gc/test/test_stmgc.py
@@ -26,11 +26,10 @@
# any use of 'self._gc' is wrong here: it's stmgc.py that should call
# et.c, and not the other way around.
- PRIMITIVE_SIZES = {1: lltype.Char,
- WORD: lltype.Signed}
CALLBACK_ENUM = lltype.Ptr(lltype.FuncType([llmemory.Address] * 3,
lltype.Void))
- GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Signed))
+ DUPLICATE = lltype.Ptr(lltype.FuncType([llmemory.Address],
+ llmemory.Address))
threadnum = 0 # 0 = main thread; 1,2,3... = transactional threads
diff --git a/pypy/translator/stm/src_stm/et.c b/pypy/translator/stm/src_stm/et.c
--- a/pypy/translator/stm/src_stm/et.c
+++ b/pypy/translator/stm/src_stm/et.c
@@ -645,7 +645,7 @@
if (P->h_tid & GCFLAG_GLOBAL)
P = LatestGlobalRevision(d, P, NULL, 0);
else
- P = (gcptr)P->h_revision; // return the original global obj
+ P = (gcptr)P->h_revision; // LOCAL_COPY: return the original global obj
}
return P;
}
diff --git a/pypy/translator/stm/src_stm/et.h b/pypy/translator/stm/src_stm/et.h
--- a/pypy/translator/stm/src_stm/et.h
+++ b/pypy/translator/stm/src_stm/et.h
@@ -83,8 +83,8 @@
//gcptr _NonTransactionalReadBarrier(gcptr);
-extern gcptr pypy_g__stm_duplicate(gcptr);
-extern void pypy_g__stm_enum_callback(void *, gcptr, gcptr);
+extern void *pypy_g__stm_duplicate(void *);
+extern void pypy_g__stm_enum_callback(void *, void *, void *);
void stm_set_tls(void *newtls);
void *stm_get_tls(void);
void stm_del_tls(void);
diff --git a/pypy/translator/stm/stmgcintf.py b/pypy/translator/stm/stmgcintf.py
--- a/pypy/translator/stm/stmgcintf.py
+++ b/pypy/translator/stm/stmgcintf.py
@@ -29,8 +29,8 @@
CALLBACK_TX = lltype.Ptr(lltype.FuncType([rffi.VOIDP, lltype.Signed],
lltype.Signed))
- GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address],
- lltype.Signed))
+ DUPLICATE = lltype.Ptr(lltype.FuncType([llmemory.Address],
+ llmemory.Address))
CALLBACK_ENUM = lltype.Ptr(lltype.FuncType([llmemory.Address]*3,
lltype.Void))
@@ -44,44 +44,25 @@
[], lltype.Signed)
add_atomic = smexternal('stm_add_atomic', [lltype.Signed], lltype.Void)
get_atomic = smexternal('stm_get_atomic', [], lltype.Signed)
- descriptor_init = smexternal('stm_descriptor_init', [], lltype.Signed)
- descriptor_done = smexternal('stm_descriptor_done', [], lltype.Void)
+ descriptor_init = smexternal('DescriptorInit', [], lltype.Signed)
+ descriptor_done = smexternal('DescriptorDone', [], lltype.Void)
begin_inevitable_transaction = smexternal(
- 'stm_begin_inevitable_transaction', [], lltype.Void)
+ 'BeginInevitableTransaction', [], lltype.Void)
commit_transaction = smexternal(
- 'stm_commit_transaction', [], lltype.Void)
+ 'CommitTransaction', [], lltype.Void)
perform_transaction = smexternal('stm_perform_transaction',
[CALLBACK_TX, rffi.VOIDP,
llmemory.Address],
lltype.Void)
- # for the GC: store and read a thread-local-storage field, as well
- # as initialize and shut down the internal thread_descriptor
+ # for the GC: store and read a thread-local-storage field
set_tls = smexternal('stm_set_tls', [llmemory.Address], lltype.Void)
get_tls = smexternal('stm_get_tls', [], llmemory.Address)
del_tls = smexternal('stm_del_tls', [], lltype.Void)
- # lookup, add, and enumerate the content of the internal dictionary
- # that maps GLOBAL objects to LOCAL objects
- tldict_lookup = smexternal('stm_tldict_lookup', [llmemory.Address],
- llmemory.Address)
- tldict_add = smexternal('stm_tldict_add', [llmemory.Address] * 2,
- lltype.Void)
+ # calls FindRootsForLocalCollect() and invokes for each such root
+ # the callback set in CALLBACK_ENUM.
tldict_enum = smexternal('stm_tldict_enum', [], lltype.Void)
- # reader functions, to call if the object is GLOBAL
- for _size, _TYPE in PRIMITIVE_SIZES.items():
- _name = 'stm_read_int%s' % _size
- locals()[_name] = smexternal(_name, [llmemory.Address, lltype.Signed],
- _TYPE)
-
- # a special reader function that copies all the content of the object
- # somewhere else
- stm_copy_transactional_to_raw = smexternal('stm_copy_transactional_to_raw',
- [llmemory.Address,
- llmemory.Address,
- lltype.Signed],
- lltype.Void)
-
# sets the transaction length, after which should_break_transaction()
# returns True
set_transaction_length = smexternal('stm_set_transaction_length',
diff --git a/pypy/translator/stm/test/test_stmgcintf.c
b/pypy/translator/stm/test/test_stmgcintf.c
--- a/pypy/translator/stm/test/test_stmgcintf.c
+++ b/pypy/translator/stm/test/test_stmgcintf.c
@@ -34,13 +34,13 @@
gcptr (*cb_duplicate)(gcptr);
void (*cb_enum_callback)(void *, gcptr, gcptr);
-gcptr pypy_g__stm_duplicate(gcptr a) {
+void *pypy_g__stm_duplicate(void *a) {
assert(cb_duplicate != NULL);
- return cb_duplicate(a);
+ return cb_duplicate((gcptr)a);
}
-void pypy_g__stm_enum_callback(void *a, gcptr b, gcptr c) {
+void pypy_g__stm_enum_callback(void *a, void *b, void *c) {
assert(cb_enum_callback != NULL);
- cb_enum_callback(a, b, c);
+ cb_enum_callback(a, (gcptr)b, (gcptr)c);
}
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit