[pypy-commit] pypy continulet-jit: Random progress.
arigo
noreply at buildbot.pypy.org
Wed Feb 29 17:54:02 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: continulet-jit
Changeset: r53022:e8a39aa24c9b
Date: 2012-02-29 17:53 +0100
http://bitbucket.org/pypy/pypy/changeset/e8a39aa24c9b/
Log: Random progress.
diff --git a/pypy/translator/c/src/stacklet/stacklet.c b/pypy/translator/c/src/stacklet/stacklet.c
--- a/pypy/translator/c/src/stacklet/stacklet.c
+++ b/pypy/translator/c/src/stacklet/stacklet.c
@@ -33,9 +33,13 @@
/************************************************************/
+struct cap_loc_s {
+ char **cl_original_pointer;
+ struct stacklet_s **cl_contained_in_stacklet;
+ struct cap_loc_s *cl_next;
+}
+
struct stacklet_s {
- stacklet_id id; /* first field */
-
/* The portion of the real stack claimed by this paused tealet. */
char *stack_start; /* the "near" end of the stack */
char *stack_stop; /* the "far" end of the stack */
@@ -54,6 +58,9 @@
* main stack.
*/
struct stacklet_s *stack_prev;
+
+ /* the captured stack locations */
+ struct cap_loc_s *stack_cap_locs;
};
void *(*_stacklet_switchstack)(void*(*)(void*, void*),
@@ -61,20 +68,18 @@
void (*_stacklet_initialstub)(struct stacklet_thread_s *,
stacklet_run_fn, void *) = NULL;
-struct stacklet_id_s {
- stacklet_handle stacklet;
-};
-
struct stacklet_thread_s {
- stacklet_id g_current_id; /* first field */
struct stacklet_s *g_stack_chain_head; /* NULL <=> running main */
char *g_current_stack_stop;
char *g_current_stack_marker;
struct stacklet_s *g_source;
struct stacklet_s *g_target;
- struct stacklet_id_s g_main_id;
+ struct stacklet_thread_s *g_prev_thread, *g_next_thread;
};
+/* circular doubly-linked list */
+static struct stacklet_thread_s *g_all_threads = NULL;
+
/***************************************************************/
static void g_save(struct stacklet_s* g, char* stop
@@ -136,8 +141,6 @@
return -1;
stacklet = thrd->g_source;
- stacklet->id = thrd->g_current_id;
- stacklet->id->stacklet = stacklet;
stacklet->stack_start = old_stack_pointer;
stacklet->stack_stop = thrd->g_current_stack_stop;
stacklet->stack_saved = 0;
@@ -237,8 +240,6 @@
memcpy(g->stack_start - stack_saved, g+1, stack_saved);
#endif
thrd->g_current_stack_stop = g->stack_stop;
- thrd->g_current_id = g->id;
- thrd->g_current_id->stacklet = NULL;
free(g);
return EMPTY_STACKLET_HANDLE;
}
@@ -247,12 +248,12 @@
stacklet_run_fn run, void *run_arg)
{
struct stacklet_s *result;
- stacklet_id sid1 = thrd->g_current_id;
+ /*stacklet_id sid1 = thrd->g_current_id;
stacklet_id sid = malloc(sizeof(struct stacklet_id_s));
if (sid == NULL) {
thrd->g_source = NULL;
return;
- }
+ }*/
/* The following call returns twice! */
result = (struct stacklet_s *) _stacklet_switchstack(g_initial_save_state,
@@ -261,18 +262,18 @@
if (result == NULL) {
/* First time it returns. */
if (thrd->g_source == NULL) { /* out of memory */
- free(sid);
+ /*free(sid);*/
return;
}
/* Only g_initial_save_state() has run and has created 'g_source'.
Call run(). */
- sid->stacklet = NULL;
- thrd->g_current_id = sid;
+ /*sid->stacklet = NULL;
+ thrd->g_current_id = sid;*/
thrd->g_current_stack_stop = thrd->g_current_stack_marker;
result = run(thrd->g_source, run_arg);
/* Then switch to 'result'. */
- free(sid);
+ /*free(sid);*/
thrd->g_target = result;
_stacklet_switchstack(g_destroy_state, g_restore_state, thrd);
@@ -280,7 +281,7 @@
abort();
}
/* The second time it returns. */
- assert(thrd->g_current_id == sid1);
+ /*assert(thrd->g_current_id == sid1);*/
}
/************************************************************/
@@ -299,13 +300,36 @@
thrd = malloc(sizeof(struct stacklet_thread_s));
if (thrd != NULL) {
memset(thrd, 0, sizeof(struct stacklet_thread_s));
- thrd->g_current_id = &thrd->g_main_id;
+ if (g_all_threads == NULL) {
+ g_all_threads = thrd;
+ thrd->g_prev_thread = thrd;
+ thrd->g_next_thread = thrd;
+ }
+ else {
+ struct stacklet_thread_s *next = g_all_threads->g_next_thread;
+ thrd->g_prev_thread = g_all_threads;
+ thrd->g_next_thread = next;
+ g_all_threads->g_next_thread = thrd;
+ next->g_prev_thread = thrd;
+ }
}
return thrd;
}
void stacklet_deletethread(stacklet_thread_handle thrd)
{
+ /* remove 'thrd' from the circular doubly-linked list */
+ stacklet_thread_handle prev = thrd->g_prev_thread;
+ stacklet_thread_handle next = thrd->g_next_thread;
+ assert(next->g_prev_thread == thrd);
+ assert(prev->g_next_thread == thrd);
+ next->g_prev_thread = prev;
+ prev->g_next_thread = next;
+ assert(g_all_threads != NULL);
+ if (g_all_threads == thrd) {
+ g_all_threads = (next == thrd) ? NULL : next;
+ }
+ /* free it */
free(thrd);
}
@@ -343,9 +367,9 @@
*pp = target->stack_prev;
break;
}
- assert(target->id->stacklet == target);
+ /*assert(target->id->stacklet == target);
if (target->id != &thrd->g_main_id)
- free(target->id);
+ free(target->id);*/
free(target);
}
@@ -371,3 +395,64 @@
}
return ptr;
}
+
+long _stacklet_capture_stack_pointer(stacklet_thread_handle thrd,
+ char **stackptr)
+{
+ if (thrd->g_stack_chain_head == NULL) {
+ /* running in 'main' */
+ return (long)stackptr;
+ }
+ else {
+ fprintf(stderr, "1!\n");
+ abort();
+ }
+}
+
+char **_stacklet_get_captured_pointer(long captured)
+{
+ if ((captured & 1) == 0) {
+ return (char**)captured;
+ }
+ else {
+ fprintf(stderr, "2!\n");
+ abort();
+ }
+}
+
+stacklet_handle _stacklet_get_captured_context(long captured)
+{
+ if ((captured & 1) == 0) {
+ /* it is one of the 'main' stacklets. If it was moved away,
+ we need to figure out which one it was. */
+ char *p = (char *)captured;
+ struct stacklet_thread_s *thrd = g_all_threads;
+ if (thrd == NULL)
+ return NULL; /* no stacklet_thread at all */
+
+ while (1) {
+ struct stacklet_s *stacklet = thrd->g_stack_chain_head;
+ if (stacklet != NULL) {
+ /* not running 'main'. Find the main stacklet */
+ while (stacklet->stack_prev)
+ stacklet = stacklet->stack_prev;
+
+ /* is 'captured' among the moved-away data? */
+ if (stacklet->stack_start <= p && p < stacklet->stack_stop) {
+ /* yes. to optimize the next calls make g_all_threads
+ point directly to thrd. */
+ g_all_threads = thrd;
+ return stacklet;
+ }
+ }
+ thrd = thrd->g_next_thread;
+ if (thrd == g_all_threads)
+ break;
+ }
+ return NULL;
+ }
+ else {
+ fprintf(stderr, "3!\n");
+ abort();
+ }
+}
diff --git a/pypy/translator/c/src/stacklet/stacklet.h b/pypy/translator/c/src/stacklet/stacklet.h
--- a/pypy/translator/c/src/stacklet/stacklet.h
+++ b/pypy/translator/c/src/stacklet/stacklet.h
@@ -72,8 +72,14 @@
* the main stacklet. This guarantees that it is possible to use
* '_stacklet_get_...()' on a regular address taken before starting
* to use stacklets.
+ *
+ * XXX assumes a single stacklet_thread_handle per thread
+ *
+ * XXX _stacklet_capture_stack_pointer() invalidates all 'long' values
+ * previously returned for the same stacklet that were for addresses
+ * later in the stack (i.e. lower).
*/
-long _stacklet_capture_stack_pointer(char **stackptr);
+long _stacklet_capture_stack_pointer(stacklet_thread_handle, char **stackptr);
char **_stacklet_get_captured_pointer(long captured);
stacklet_handle _stacklet_get_captured_context(long captured);
diff --git a/pypy/translator/c/src/stacklet/tests.c b/pypy/translator/c/src/stacklet/tests.c
--- a/pypy/translator/c/src/stacklet/tests.c
+++ b/pypy/translator/c/src/stacklet/tests.c
@@ -628,8 +628,9 @@
/************************************************************/
struct test_captr_s {
- long c, c1, c2;
+ long c, c0, c1, c2;
char **fooref;
+ char **fooref0;
char **fooref1;
char **fooref2;
stacklet_handle hmain;
@@ -637,7 +638,7 @@
stacklet_handle h2;
} tid;
-void cap_check_all(int depth);
+int cap_check_all(int depth);
stacklet_handle stacklet_captr_callback_1(stacklet_handle h, void *arg)
{
@@ -647,11 +648,11 @@
status = 1;
assert(_stacklet_get_captured_pointer(tid.c) == tid.fooref);
- assert(_stacklet_get_captured_context(tid.c) == tid.hmain);
+ assert(_stacklet_get_captured_context(tid.c) == NULL);
assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42);
char *ref1 = (char*)1111;
- tid.c1 = _stacklet_capture_stack_pointer(&ref1);
+ tid.c1 = _stacklet_capture_stack_pointer(thrd, &ref1);
tid.fooref1 = &ref1;
assert(_stacklet_get_captured_pointer(tid.c1) == &ref1);
assert(_stacklet_get_captured_context(tid.c1) == NULL);
@@ -675,13 +676,11 @@
status = 2;
char *ref2 = (char*)2222;
- tid.c2 = _stacklet_capture_stack_pointer(&ref2);
+ tid.c2 = _stacklet_capture_stack_pointer(thrd, &ref2);
tid.fooref2 = &ref2;
assert(_stacklet_get_captured_pointer(tid.c2) == &ref2);
assert(_stacklet_get_captured_context(tid.c2) == NULL);
- cap_check_all(20);
-
h = stacklet_switch(thrd, h);
tid.hmain = h;
tid.h2 = NULL;
@@ -694,11 +693,17 @@
return stacklet_switch(thrd, h);
}
-void cap_check_all(int depth)
+int cap_check_all(int depth)
{
assert(_stacklet_get_captured_pointer(tid.c) == tid.fooref);
+ /* we always get NULL because it's before the portion of the stack
+ that is copied away and restored: */
+ assert(_stacklet_get_captured_context(tid.c) == NULL);
+ assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42);
+
+ assert(_stacklet_get_captured_pointer(tid.c0) == tid.fooref0);
assert(_stacklet_get_captured_context(tid.c) == tid.hmain);
- assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42);
+ assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)6363);
assert(_stacklet_get_captured_pointer(tid.c1) == tid.fooref1);
assert(_stacklet_get_captured_context(tid.c1) == tid.h1);
@@ -709,39 +714,26 @@
assert(*_stacklet_translate_pointer(tid.h2, tid.fooref2) == (char*)2222);
if (depth > 0)
- cap_check_all(depth - 1);
-
- assert(_stacklet_get_captured_pointer(tid.c) == tid.fooref);
- assert(_stacklet_get_captured_context(tid.c) == tid.hmain);
- assert(*_stacklet_translate_pointer(tid.hmain, tid.fooref) == (char*)-42);
-
- assert(_stacklet_get_captured_pointer(tid.c1) == tid.fooref1);
- assert(_stacklet_get_captured_context(tid.c1) == tid.h1);
- assert(*_stacklet_translate_pointer(tid.h1, tid.fooref1) == (char*)1111);
-
- assert(_stacklet_get_captured_pointer(tid.c2) == tid.fooref2);
- assert(_stacklet_get_captured_context(tid.c2) == tid.h2);
- assert(*_stacklet_translate_pointer(tid.h2, tid.fooref2) == (char*)2222);
+ return cap_check_all(depth - 1) * depth;
+ return 1;
}
-void test_stacklet_capture(void)
+int cap_with_extra_stack(int depth)
{
- char *foo = (char*)-42;
- tid.c = _stacklet_capture_stack_pointer(&foo);
- tid.fooref = &foo;
- assert(tid.c == (long)tid.fooref);
- assert(_stacklet_get_captured_pointer(tid.c) == &foo);
- assert(_stacklet_get_captured_context(tid.c) == NULL);
+ stacklet_handle h1, h2;
+ char *foo0 = (char*)6363;
- status = 0;
- stacklet_handle h1 = stacklet_new(thrd, stacklet_captr_callback_1, NULL);
- stacklet_handle h2 = stacklet_new(thrd, stacklet_captr_callback_2, NULL);
- tid.hmain = NULL;
- tid.h1 = h1;
- tid.h2 = h2;
+ if (depth > 0)
+ return cap_with_extra_stack(depth - 1) * depth;
+
+ tid.c0 = _stacklet_capture_stack_pointer(thrd, &foo0);
+ tid.fooref0 = &foo0;
+ assert(tid.c0 == (long)tid.fooref0);
+ assert(_stacklet_get_captured_pointer(tid.c0) == &foo0);
+ assert(_stacklet_get_captured_context(tid.c0) == NULL);
cap_check_all(20);
- assert(_stacklet_capture_stack_pointer(tid.fooref) == tid.c);
+ assert(_stacklet_capture_stack_pointer(thrd, tid.fooref) == tid.c);
assert(status == 2);
status = 3;
@@ -758,11 +750,31 @@
tid.h2 = h2;
cap_check_all(20);
+ return 1;
+}
+
+void test_stacklet_capture(void)
+{
+ char *foo = (char*)-42;
+ tid.c = _stacklet_capture_stack_pointer(thrd, &foo);
+ tid.fooref = &foo;
+ assert(tid.c == (long)tid.fooref);
+ assert(_stacklet_get_captured_pointer(tid.c) == &foo);
+ assert(_stacklet_get_captured_context(tid.c) == NULL);
+
+ status = 0;
+ stacklet_handle h1 = stacklet_new(thrd, stacklet_captr_callback_1, NULL);
+ stacklet_handle h2 = stacklet_new(thrd, stacklet_captr_callback_2, NULL);
+ tid.hmain = NULL;
+ tid.h1 = h1;
+ tid.h2 = h2;
+
+ cap_with_extra_stack(20);
assert(status == 6);
- h1 = stacklet_switch(thrd, h1);
+ h1 = stacklet_switch(thrd, tid.h1);
assert(h1 == EMPTY_STACKLET_HANDLE);
- h2 = stacklet_switch(thrd, h2);
+ h2 = stacklet_switch(thrd, tid.h2);
assert(h2 == EMPTY_STACKLET_HANDLE);
}
More information about the pypy-commit
mailing list