[pypy-commit] pypy stmgc-static-barrier: import stmgc/9dc18268f0da
arigo
noreply at buildbot.pypy.org
Tue Aug 13 18:04:57 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-static-barrier
Changeset: r66122:82d9f20cc182
Date: 2013-08-13 16:29 +0200
http://bitbucket.org/pypy/pypy/changeset/82d9f20cc182/
Log: import stmgc/9dc18268f0da
diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c
--- a/rpython/translator/stm/src_stm/et.c
+++ b/rpython/translator/stm/src_stm/et.c
@@ -7,6 +7,7 @@
*/
#include "stmimpl.h"
+#ifdef _GC_DEBUG
char tmp_buf[128];
char* stm_dbg_get_hdr_str(gcptr obj)
{
@@ -26,6 +27,7 @@
cur += sprintf(cur, "tid=%ld", stm_get_tid(obj));
return tmp_buf;
}
+#endif
@@ -275,29 +277,81 @@
/* Version of stm_DirectReadBarrier() that doesn't abort and assumes
* that 'P' was already an up-to-date result of a previous
* stm_DirectReadBarrier(). We only have to check if we did in the
- * meantime a stm_write_barrier().
+ * meantime a stm_write_barrier(). Should only be called if we
+ * have the flag PUBLIC_TO_PRIVATE or on MOVED objects. This version
+ * should never abort (it is used in stm_decode_abort_info()).
*/
- if (P->h_tid & GCFLAG_PUBLIC)
+ assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(!(P->h_tid & GCFLAG_STUB));
+
+ if (P->h_tid & GCFLAG_MOVED)
{
- if (P->h_tid & GCFLAG_MOVED)
+ dprintf(("repeat_read_barrier: %p -> %p moved\n", P,
+ (gcptr)P->h_revision));
+ P = (gcptr)P->h_revision;
+ assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(!(P->h_tid & GCFLAG_STUB));
+ assert(!(P->h_tid & GCFLAG_MOVED));
+ if (!(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE))
+ return P;
+ }
+ assert(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE);
+
+ struct tx_descriptor *d = thread_descriptor;
+ wlog_t *item;
+ G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
+
+ /* We have a key in 'public_to_private'. The value is the
+ corresponding private object. */
+ dprintf(("repeat_read_barrier: %p -> %p public_to_private\n", P, item->val));
+ P = item->val;
+ assert(!(P->h_tid & GCFLAG_PUBLIC));
+ assert(!(P->h_tid & GCFLAG_STUB));
+ assert(is_private(P));
+ return P;
+
+ no_private_obj:
+ /* Key not found. It should not be waiting in 'stolen_objects',
+ because this case from steal.c applies to objects to were originally
+ backup objects. 'P' cannot be a backup object if it was obtained
+ earlier as a result of stm_read_barrier().
+ */
+ return P;
+}
+
+gcptr stm_ImmutReadBarrier(gcptr P)
+{
+ assert(P->h_tid & GCFLAG_STUB);
+ assert(P->h_tid & GCFLAG_PUBLIC);
+
+ revision_t v = ACCESS_ONCE(P->h_revision);
+ assert(IS_POINTER(v)); /* "is a pointer", "has a more recent revision" */
+
+ if (!(v & 2))
+ {
+ P = (gcptr)v;
+ }
+ else
+ {
+ /* follow a stub reference */
+ struct tx_descriptor *d = thread_descriptor;
+ struct tx_public_descriptor *foreign_pd = STUB_THREAD(P);
+ if (foreign_pd == d->public_descriptor)
{
- P = (gcptr)P->h_revision;
- assert(P->h_tid & GCFLAG_PUBLIC);
+ /* Same thread: dereference the pointer directly. */
+ dprintf(("immut_read_barrier: %p -> %p via stub\n ", P,
+ (gcptr)(v - 2)));
+ P = (gcptr)(v - 2);
}
- if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)
+ else
{
- struct tx_descriptor *d = thread_descriptor;
- wlog_t *item;
- G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
-
- P = item->val;
- assert(!(P->h_tid & GCFLAG_PUBLIC));
- no_private_obj:
- ;
+ /* stealing: needed because accessing v - 2 from this thread
+ is forbidden (the target might disappear under our feet) */
+ dprintf(("immut_read_barrier: %p -> stealing...\n ", P));
+ stm_steal_stub(P);
}
}
- assert(!(P->h_tid & GCFLAG_STUB));
- return P;
+ return stm_immut_read_barrier(P); /* retry */
}
static gcptr _match_public_to_private(gcptr P, gcptr pubobj, gcptr privobj,
@@ -565,6 +619,16 @@
}
}
+gcptr stm_RepeatWriteBarrier(gcptr P)
+{
+ assert(!(P->h_tid & GCFLAG_IMMUTABLE));
+ assert(is_private(P));
+ assert(P->h_tid & GCFLAG_WRITE_BARRIER);
+ P->h_tid &= ~GCFLAG_WRITE_BARRIER;
+ gcptrlist_insert(&thread_descriptor->old_objects_to_trace, P);
+ return P;
+}
+
gcptr stm_WriteBarrier(gcptr P)
{
assert(!(P->h_tid & GCFLAG_IMMUTABLE));
diff --git a/rpython/translator/stm/src_stm/et.h b/rpython/translator/stm/src_stm/et.h
--- a/rpython/translator/stm/src_stm/et.h
+++ b/rpython/translator/stm/src_stm/et.h
@@ -70,11 +70,11 @@
static const revision_t GCFLAG_VISITED = STM_FIRST_GCFLAG << 1;
static const revision_t GCFLAG_PUBLIC = STM_FIRST_GCFLAG << 2;
static const revision_t GCFLAG_PREBUILT_ORIGINAL = STM_FIRST_GCFLAG << 3;
-static const revision_t GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG << 4;
+// in stmgc.h: GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG << 4;
// in stmgc.h: GCFLAG_WRITE_BARRIER = STM_FIRST_GCFLAG << 5;
-static const revision_t GCFLAG_MOVED = STM_FIRST_GCFLAG << 6;
+// in stmgc.h: GCFLAG_MOVED = STM_FIRST_GCFLAG << 6;
static const revision_t GCFLAG_BACKUP_COPY /*debug*/ = STM_FIRST_GCFLAG << 7;
-static const revision_t GCFLAG_STUB /*debug*/ = STM_FIRST_GCFLAG << 8;
+// in stmgc.h: GCFLAG_STUB = STM_FIRST_GCFLAG << 8;
static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG << 9;
static const revision_t GCFLAG_HAS_ID = STM_FIRST_GCFLAG << 10;
static const revision_t GCFLAG_IMMUTABLE = STM_FIRST_GCFLAG << 11;
@@ -196,8 +196,10 @@
void SpinLoop(int);
gcptr stm_DirectReadBarrier(gcptr);
+gcptr stm_WriteBarrier(gcptr);
gcptr stm_RepeatReadBarrier(gcptr);
-gcptr stm_WriteBarrier(gcptr);
+gcptr stm_ImmutReadBarrier(gcptr);
+gcptr stm_RepeatWriteBarrier(gcptr);
gcptr _stm_nonrecord_barrier(gcptr); /* debugging: read barrier, but
not recording anything */
int _stm_is_private(gcptr); /* debugging */
diff --git a/rpython/translator/stm/src_stm/extra.c b/rpython/translator/stm/src_stm/extra.c
--- a/rpython/translator/stm/src_stm/extra.c
+++ b/rpython/translator/stm/src_stm/extra.c
@@ -154,6 +154,19 @@
return (p1 == p2);
}
+_Bool stm_pointer_equal_prebuilt(gcptr p1, gcptr p2)
+{
+ assert(p2 != NULL);
+ assert(p2->h_tid & GCFLAG_PREBUILT_ORIGINAL);
+
+ if (p1 == p2)
+ return 1;
+
+ /* the only possible case to still get True is if p2 == p1->h_original */
+ return (p1 != NULL) && (p1->h_original == p2) &&
+ !(p1->h_tid & GCFLAG_PREBUILT_ORIGINAL);
+}
+
/************************************************************/
void stm_abort_info_push(gcptr obj, long fieldoffsets[])
@@ -205,7 +218,7 @@
WRITE_BUF(buffer, res_size);
WRITE('e');
for (i=0; i<d->abortinfo.size; i+=2) {
- char *object = (char *)stm_RepeatReadBarrier(d->abortinfo.items[i+0]);
+ char *object = (char*)stm_repeat_read_barrier(d->abortinfo.items[i+0]);
long *fieldoffsets = (long*)d->abortinfo.items[i+1];
long kind, offset;
size_t rps_size;
diff --git a/rpython/translator/stm/src_stm/revision b/rpython/translator/stm/src_stm/revision
--- a/rpython/translator/stm/src_stm/revision
+++ b/rpython/translator/stm/src_stm/revision
@@ -1,1 +1,1 @@
-12cf412eb2d7+
+9dc18268f0da
diff --git a/rpython/translator/stm/src_stm/stmgc.h b/rpython/translator/stm/src_stm/stmgc.h
--- a/rpython/translator/stm/src_stm/stmgc.h
+++ b/rpython/translator/stm/src_stm/stmgc.h
@@ -42,6 +42,7 @@
/* returns nonzero if the two object-copy pointers belong to the
same original object */
_Bool stm_pointer_equal(gcptr, gcptr);
+_Bool stm_pointer_equal_prebuilt(gcptr, gcptr); /* 2nd arg is known prebuilt */
/* to push/pop objects into the local shadowstack */
#if 0 // (optimized version below)
@@ -59,7 +60,7 @@
int stm_enter_callback_call(void);
void stm_leave_callback_call(int);
-/* read/write barriers (the most general versions only for now).
+/* read/write barriers.
- the read barrier must be applied before reading from an object.
the result is valid as long as we're in the same transaction,
@@ -69,10 +70,28 @@
the result is valid for a shorter period of time: we have to
do stm_write_barrier() again if we ended the transaction, or
if we did a potential collection (e.g. stm_allocate()).
+
+ - as an optimization, stm_repeat_read_barrier() can be used
+ instead of stm_read_barrier() if the object was already
+ obtained by a stm_read_barrier() in the same transaction.
+ The only thing that may have occurred is that a
+ stm_write_barrier() on the same object could have made it
+ invalid.
+
+ - a different optimization is to read immutable fields: in order
+ to do that, use stm_immut_read_barrier(), which only activates
+ on stubs.
+
+ - stm_repeat_write_barrier() can be used on an object on which
+ we already did stm_write_barrier(), but a potential collection
+ can have occurred.
*/
#if 0 // (optimized version below)
gcptr stm_read_barrier(gcptr);
gcptr stm_write_barrier(gcptr);
+gcptr stm_repeat_read_barrier(gcptr);
+gcptr stm_immut_read_barrier(gcptr);
+gcptr stm_repeat_write_barrier(gcptr); /* <= always returns its argument */
#endif
/* start a new transaction, calls callback(), and when it returns
@@ -159,7 +178,10 @@
extern __thread revision_t stm_private_rev_num;
gcptr stm_DirectReadBarrier(gcptr);
gcptr stm_WriteBarrier(gcptr);
+static const revision_t GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG << 4;
static const revision_t GCFLAG_WRITE_BARRIER = STM_FIRST_GCFLAG << 5;
+static const revision_t GCFLAG_MOVED = STM_FIRST_GCFLAG << 6;
+static const revision_t GCFLAG_STUB = STM_FIRST_GCFLAG << 8;
extern __thread char *stm_read_barrier_cache;
#define FX_MASK 65535
#define FXCACHE_AT(obj) \
@@ -167,23 +189,6 @@
#define UNLIKELY(test) __builtin_expect(test, 0)
-
-static inline gcptr stm_read_barrier(gcptr obj) {
- /* XXX optimize to get the smallest code */
- if (UNLIKELY((obj->h_revision != stm_private_rev_num) &&
- (FXCACHE_AT(obj) != obj)))
- obj = stm_DirectReadBarrier(obj);
- return obj;
-}
-
-static inline gcptr stm_write_barrier(gcptr obj) {
- if (UNLIKELY((obj->h_revision != stm_private_rev_num) |
- ((obj->h_tid & GCFLAG_WRITE_BARRIER) != 0)))
- obj = stm_WriteBarrier(obj);
- return obj;
-}
-
-#if 0
#define stm_read_barrier(obj) \
(UNLIKELY(((obj)->h_revision != stm_private_rev_num) && \
(FXCACHE_AT(obj) != (obj))) ? \
@@ -195,6 +200,21 @@
(((obj)->h_tid & GCFLAG_WRITE_BARRIER) != 0)) ? \
stm_WriteBarrier(obj) \
: (obj))
-#endif
+
+#define stm_repeat_read_barrier(obj) \
+ (UNLIKELY((obj)->h_tid & (GCFLAG_PUBLIC_TO_PRIVATE | GCFLAG_MOVED)) ? \
+ stm_RepeatReadBarrier(obj) \
+ : (obj))
+
+#define stm_immut_read_barrier(obj) \
+ (UNLIKELY((obj)->h_tid & GCFLAG_STUB) ? \
+ stm_ImmutReadBarrier(obj) \
+ : (obj))
+
+#define stm_repeat_write_barrier(obj) \
+ (UNLIKELY((obj)->h_tid & GCFLAG_WRITE_BARRIER) ? \
+ stm_RepeatWriteBarrier(obj) \
+ : (obj))
+
#endif
More information about the pypy-commit
mailing list