[pypy-commit] pypy continulet-jit: In-progress: add some notion of stacklet id.

arigo noreply at buildbot.pypy.org
Sun Oct 16 11:49:19 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: continulet-jit
Changeset: r48077:b0e1da0656a9
Date: 2011-10-16 11:49 +0200
http://bitbucket.org/pypy/pypy/changeset/b0e1da0656a9/

Log:	In-progress: add some notion of stacklet id. Not composable at all,
	but seems to be needed for the JIT's virtualizables and
	virtualrefs...

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
@@ -34,6 +34,8 @@
 /************************************************************/
 
 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 */
@@ -60,6 +62,7 @@
                               stacklet_run_fn, void *) = NULL;
 
 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;
@@ -67,6 +70,10 @@
     struct stacklet_s *g_target;
 };
 
+struct stacklet_id_s {
+    stacklet_handle stacklet;
+};
+
 /***************************************************************/
 
 static void g_save(struct stacklet_s* g, char* stop
@@ -128,6 +135,9 @@
         return -1;
 
     stacklet = thrd->g_source;
+    stacklet->id = thrd->g_current_id;
+    if (stacklet->id != NULL)
+        stacklet->id->stacklet = stacklet;
     stacklet->stack_start = old_stack_pointer;
     stacklet->stack_stop  = thrd->g_current_stack_stop;
     stacklet->stack_saved = 0;
@@ -227,6 +237,9 @@
     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;
+    if (thrd->g_current_id != NULL)
+        thrd->g_current_id->stacklet = NULL;
     free(g);
     return EMPTY_STACKLET_HANDLE;
 }
@@ -235,18 +248,33 @@
                           stacklet_run_fn run, void *run_arg)
 {
     struct stacklet_s *result;
+    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,
                                                          g_restore_state,
                                                          thrd);
-    if (result == NULL && thrd->g_source != NULL) {
-        /* First time it returns.  Only g_initial_save_state() has run
-           and has created 'g_source'.  Call run(). */
+    if (result == NULL) {
+        /* First time it returns. */
+        if (thrd->g_source == NULL) {     /* out of memory */
+            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;
+        fprintf(stderr, "new sid: %p\n", sid);
         thrd->g_current_stack_stop = thrd->g_current_stack_marker;
         result = run(thrd->g_source, run_arg);
 
         /* Then switch to 'result'. */
+        free(sid);
         thrd->g_target = result;
         _stacklet_switchstack(g_destroy_state, g_restore_state, thrd);
 
@@ -254,6 +282,8 @@
         abort();
     }
     /* The second time it returns. */
+    assert(thrd->g_current_id == sid1);
+    fprintf(stderr, "continue with sid: %p\n", sid1);
 }
 
 /************************************************************/
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
@@ -59,4 +59,14 @@
  */
 char **_stacklet_translate_pointer(stacklet_handle context, char **ptr);
 
+/* The "stacklet id" is NULL for main stacklets; for other stacklets it is a
+ * value that remain valid and unchanged if the stacklet is suspended and
+ * resumed.  WARNING: DON'T USE unless you have no other choice, because
+ * it is not "composable" at all.
+ */
+typedef struct stacklet_id_s *stacklet_id;
+#define _stacklet_id_of_stacklet(stacklet) (*(stacklet_id*)(stacklet))
+#define _stacklet_id_current(thrd) (*(stacklet_id*)(thrd))
+stacklet_handle _stacklet_with_id(stacklet_thread_handle thrd, stacklet_id id);
+
 #endif /* _STACKLET_H_ */
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
@@ -627,6 +627,66 @@
 #endif
 /************************************************************/
 
+struct test_id_s {
+    stacklet_id id1;
+    stacklet_id id2;
+} tid;
+
+stacklet_handle stacklet_id_callback_1(stacklet_handle h, void *arg)
+{
+    stacklet_id myid = _stacklet_id_current(thrd);
+    h = stacklet_switch(thrd, h);
+    
+    tid.id1 = _stacklet_id_current(thrd);
+    assert(tid.id1 != NULL);
+    assert(tid.id1 == myid);
+    assert(status == 0);
+    status = 1;
+
+    return stacklet_switch(thrd, h);
+}
+
+stacklet_handle stacklet_id_callback_2(stacklet_handle h, void *arg)
+{
+    stacklet_id myid = _stacklet_id_current(thrd);
+    h = stacklet_switch(thrd, h);
+
+    tid.id2 = _stacklet_id_current(thrd);
+    assert(tid.id2 != NULL);
+    assert(tid.id2 == myid);
+    assert(status == 1);
+    status = 2;
+
+    return stacklet_switch(thrd, h);
+}
+
+void test_stacklet_id(void)
+{
+    status = 0;
+    stacklet_handle h1 = stacklet_new(thrd, stacklet_id_callback_1, NULL);
+    stacklet_handle h2 = stacklet_new(thrd, stacklet_id_callback_2, NULL);
+
+    assert(_stacklet_id_current(thrd) == NULL);
+
+    assert(status == 0);
+    h1 = stacklet_switch(thrd, h1);
+
+    assert(status == 1);
+    h2 = stacklet_switch(thrd, h2);
+
+    assert(status == 2);
+    assert(_stacklet_id_of_stacklet(h1) == tid.id1);
+    assert(_stacklet_id_of_stacklet(h2) == tid.id2);
+    assert(_stacklet_id_current(thrd) == NULL);
+
+    h1 = stacklet_switch(thrd, h1);
+    assert(h1 == EMPTY_STACKLET_HANDLE);
+    h2 = stacklet_switch(thrd, h2);
+    assert(h2 == EMPTY_STACKLET_HANDLE);
+}
+
+/************************************************************/
+
 #define TEST(name)   { name, #name }
 
 typedef struct {
@@ -649,6 +709,7 @@
   TEST(test_double),
   TEST(test_random),
 #endif
+  TEST(test_stacklet_id),
   { NULL, NULL }
 };
 


More information about the pypy-commit mailing list