Author: Armin Rigo <[email protected]>
Branch: tealet
Changeset: r45999:f3d3bf4acb0c
Date: 2011-07-26 11:01 +0200
http://bitbucket.org/pypy/pypy/changeset/f3d3bf4acb0c/

Log:    Waaa. Intermediate check-in (untested) of this scary code.

diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -31,7 +31,8 @@
     BoolOption("tealet", "enable stackless features via tealets",
                default=False, cmdline="--tealet",
                requires=[("translation.type_system", "lltype"),
-                         ("translation.gctransformer", "framework")]),
+                         ("translation.gctransformer", "framework"),
+                         ("translation.gcrootfinder", "asmgcc")]), #XXX for now
     ChoiceOption("type_system", "Type system to use when RTyping",
                  ["lltype", "ootype"], cmdline=None, default="lltype",
                  requires={
diff --git a/pypy/rlib/_tealet_rffi.py b/pypy/rlib/_tealet_rffi.py
--- a/pypy/rlib/_tealet_rffi.py
+++ b/pypy/rlib/_tealet_rffi.py
@@ -24,3 +24,7 @@
                                               rffi.VOIDP], rffi.INT)
 tealet_switch     = llexternal("tealet_switch", [TEALET_P], rffi.INT)
 tealet_current    = llexternal("tealet_current", [TEALET_P], TEALET_P)
+
+_tealet_translate_pointer = llexternal("_tealet_translate_pointer",
+                                       [TEALET_P, llmemory.Address],
+                                       llmemory.Address)
diff --git a/pypy/rlib/rtealet.py b/pypy/rlib/rtealet.py
--- a/pypy/rlib/rtealet.py
+++ b/pypy/rlib/rtealet.py
@@ -22,8 +22,7 @@
 
     class Tealet(base_class):
         lltealet = _tealet_rffi.NULL_TEALET
-        _gc_gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
-        _gc_signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
+        _suspended_stack = NULL_SUSPSTACK
 
         def switch(self):
             _switch(self)
@@ -61,22 +60,22 @@
     exception = None
 switcher = Switcher()
 
+llswitcher = lltype.malloc(rffi.CArray(_tealet_rffi.TEALET_P), 1,
+                           flavor='raw', zero=True)
+
 def _new(main, starting_tealet):
     switcher.current = main.current
     switcher.target = starting_tealet
-    llmain = main.lltealet
+    llswitcher[0] = main.lltealet
+    r = _stack_protected_call(llhelper(FUNCNOARG, _new_critical))
+    _check_exception(r)
+
+def _new_critical():
+    # critical function: no gc operation, and no gc variable alive!
+    llmain = llswitcher[0]
     llrun = llhelper(_tealet_rffi.TEALET_RUN_P, _run)
     llarg = _tealet_rffi.NULL
-    r = _new_critical(llmain, llrun, llarg)
-    _check_exception(r)
-
-def _new_critical(llmain, llrun, llarg):
-    # critical function: no gc operation, and no gc variable alive!
-    _save_shadow_stack()
-    r = _tealet_rffi.tealet_new(llmain, llrun, llarg)
-    _restore_shadow_stack()
-    return r
-_new_critical._dont_inline_ = True
+    return _tealet_rffi.tealet_new(llmain, llrun, llarg)
 
 def _run(lltealet, llarg):
     llop.gc_stack_bottom(lltype.Void)
@@ -110,20 +109,18 @@
     switcher.current = main.current
     switcher.target = target
     main.current = target
-    r = _switch_critical(target.lltealet)
+    llswitcher[0] = target.lltealet
+    r = _stack_protected_call(llhelper(FUNCNOARG, _switch_critical))
+    _check_exception(r)
+
+def _switch_critical():
+    # critical code: no gc operation!
+    lltarget = llswitcher[0]
+    return _tealet_rffi.tealet_switch(lltarget)
+
+def _check_exception(r):
     switcher.current = None
     switcher.target = None
-    _check_exception(r)
-
-def _switch_critical(lltarget):
-    # critical code: no gc operation!
-    _save_shadow_stack()
-    r = _tealet_rffi.tealet_switch(lltarget)
-    _restore_shadow_stack()
-    return r
-_switch_critical._dont_inline_ = True
-
-def _check_exception(r):
     r = rffi.cast(lltype.Signed, r)
     if r != 0:
         # rare case: tealet.c complains, e.g. out of memory.  I think that
@@ -138,36 +135,177 @@
 
 # ____________________________________________________________
 #
-# Shadow stack saving/restoring.
+# AsmGcRoot stack walking.
+# XXX rethink the interfacing with asmgcroot.py
+#
+# This is a copy of the logic in asmgcroot.py, rewritten so that all
+# pointer reads from the stack go via _tealet_translate_pointer()
+# and also rewritten in an iterator-like style, with a next() method
+# that just returns the next stack pointer.
+# XXX avoid copying so much of the logic of asmgcroot
 
-GCPTR_ARRAY  = lltype.Ptr(lltype.GcArray(llmemory.GCREF))
-SIGNED_ARRAY = lltype.Ptr(lltype.GcArray(lltype.Signed))
-WALKER_PTR   = lltype.Ptr(lltype.Struct('walker',
-                                        ('gcptr_array', GCPTR_ARRAY),
-                                        ('signed_array', SIGNED_ARRAY)))
-walker = lltype.malloc(WALKER_PTR.TO, immortal=True)
+_asmstackrootwalker = None    # BIG HACK: monkey-patched by asmgcroot.py
+_tealetrootwalker = None
 
-def _save_shadow_stack():
-    llop.gc_save_stack_roots(lltype.Void, walker)
-    tealet = switcher.current
-    ll_assert(not tealet._gc_gcptr_array, "tealet stack mismatch (save)")
-    tealet._gc_gcptr_array  = walker.gcptr_array
-    tealet._gc_signed_array = walker.signed_array
-    walker.gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
-    walker.signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
-_save_shadow_stack._dont_inline_ = True
+def get_tealetrootwalker():
+    # lazily called, to make the following imports lazy
+    global _tealetrootwalker
+    if _tealetrootwalker is not None:
+        return _tealetrootwalker
 
-def _restore_shadow_stack():
-    tealet = switcher.target
-    ll_assert(bool(tealet._gc_gcptr_array), "tealet stack mismatch (restore)")
-    walker.gcptr_array  = tealet._gc_gcptr_array
-    walker.signed_array = tealet._gc_signed_array
-    tealet._gc_gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
-    tealet._gc_signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
-    llop.gc_restore_stack_roots(lltype.Void, walker)
-    walker.gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
-    walker.signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
-_restore_shadow_stack._dont_inline_ = True
+    from pypy.rpython.memory.gctransform.asmgcroot import (
+        WALKFRAME, CALLEE_SAVED_REGS)
+
+    assert _asmstackrootwalker is not None, "should have been monkey-patched"
+    basewalker = _asmstackrootwalker
+
+    class TealetRootWalker(object):
+        _alloc_flavor_ = "raw"
+
+        enumerating = False
+
+        def setup(self, obj):
+            # initialization: read the SUSPSTACK object
+            p = llmemory.cast_adr_to_ptr(obj, lltype.Ptr(SUSPSTACK))
+            if not p.context:
+                return False
+            self.context = p.context
+            initialframedata = p.initialframedata
+            del p
+            self.curframe = lltype.malloc(WALKFRAME, flavor='raw')
+            self.otherframe = lltype.malloc(WALKFRAME, flavor='raw')
+            basewalker.fill_initial_frame(self.curframe, self.initialframedata)
+            return True
+
+        def teardown(self):
+            lltype.free(self.curframe, flavor='raw')
+            lltype.free(self.otherframe, flavor='raw')
+            self.context = _tealet_rffi.NULL_TEALET
+            return llmemory.NULL
+
+        def next(self, obj, prev):
+            #
+            # Pointers to the stack can be "translated" or not:
+            #
+            #   * Non-translated pointers point to where the data would be
+            #     if the stack was installed and running.
+            #
+            #   * Translated pointers correspond to where the data
+            #     is now really in memory.
+            #
+            # Note that 'curframe' contains non-translated pointers, and
+            # of course the stack itself is full of non-translated pointers.
+            #
+            while True:
+                callee = self.curframe
+                #
+                if not self.enumerating:
+                    if not prev:
+                        if not self.setup(obj):      # one-time initialization
+                            return llmemory.NULL
+                        prev = obj   # random value, but non-NULL
+                    retaddraddr = self.translateptr(callee.frame_address)
+                    retaddr = retaddraddr.address[0]
+                    basewalker.locate_caller_based_on_retaddr(retaddr)
+                    self.enumerating = True
+                #
+                # not really a loop, but kept this way for similarity
+                # with asmgcroot:
+                while True:
+                    location = basewalker._shape_decompressor.next()
+                    if location == 0:
+                        break
+                    addr = basewalker.getlocation(callee, location)
+                    # yield the translated addr of the next GCREF in the stack
+                    return self.translateptr(addr)
+                #
+                self.enumerating = False
+                caller = self.otherframe
+                reg = CALLEE_SAVED_REGS - 1
+                while reg >= 0:
+                    location = basewalker._shape_decompressor.next()
+                    addr = basewalker.getlocation(callee, location)
+                    caller.regs_stored_at[reg] = addr   # non-translated
+                    reg -= 1
+
+                location = basewalker._shape_decompressor.next()
+                caller.frame_address = basewalker.getlocation(callee, location)
+                # ^^^ non-translated
+                if caller.frame_address == llmemory.NULL:
+                    return self.teardown()    # completely done with this stack
+                #
+                self.otherframe = callee
+                self.curframe = caller
+                # loop back
+
+        def translateptr(self, addr):
+            return _tealet_rffi._tealet_translate_pointer(self.context, addr)
+
+    _tealetrootwalker = TealetRootWalker()
+    return _tealetrootwalker
+get_tealetrootwalker._annspecialcase_ = 'specialize:memo'
+
+
+def customtrace(obj, prev):
+    tealetrootwalker = get_tealetrootwalker()
+    return tealetrootwalker.next(obj, prev)
+
+ASM_FRAMEDATA_HEAD_PTR = lltype.Ptr(lltype.FixedSizeArray(llmemory.Address, 2))
+SUSPSTACK = lltype.GcStruct('SuspStack',
+                            ('context', _tealet_rffi.TEALET_P),
+                            ('anchor', ASM_FRAMEDATA_HEAD_PTR),
+                            ('my_index', lltype.Signed),
+                            ('next_unused', lltype.Signed),
+                            rtti=True)
+CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
+                                  llmemory.Address)
+customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace)
+lltype.attachRuntimeTypeInfo(SUSPSTACK, customtraceptr=customtraceptr)
+NULL_SUSPSTACK = lltype.Ptr(SUSPSTACK)
+
+
+class SuspendedStacks:
+
+    def __init__(self):
+        self.lst = []
+        self.first_unused = -1
+
+    def acquire(self):
+        if self.first_unused == -1:
+            p = lltype.malloc(SUSPSTACK)
+            p.context = _tealet_rffi.NULL_TEALET
+            p.my_index = len(self.lst)
+            self.lst.append(p)
+        else:
+            p = self.lst[self.first_unused]
+            self.first_unused = p.next_unused
+        return p
+
+    def release(self, p):
+        p.next_unused = self.first_unused
+        self.first_unused = p.my_index
+
+suspendedstacks = SuspendedStacks()
+
+def _stack_protected_call(callback):
+    # :-/
+    p = suspendedstacks.acquire()
+    suspendedstacks.callback = callback
+    anchor = lltype.malloc(ASM_FRAMEDATA_HEAD_PTR.TO, flavor='raw')
+    anchor[0] = anchor[1] = llmemory.cast_ptr_to_adr(anchor)
+    p.anchor = anchor
+    r = pypy_asm_stackwalk2(callback, anchor)
+    suspendedstacks.release(p)
+    lltype.free(anchor, flavor='raw')
+    return r
+
+FUNCNOARG = lltype.FuncType([], rffi.INT)
+
+pypy_asm_stackwalk2 = rffi.llexternal('pypy_asm_stackwalk',
+                                      [lltype.Ptr(FUNCNOARG),
+                                       ASM_FRAMEDATA_HEAD_PTR],
+                                      rffi.INT, sandboxsafe=True,
+                                      _nowrapper=True)
 
 # ____________________________________________________________
 
diff --git a/pypy/rpython/memory/gctransform/asmgcroot.py 
b/pypy/rpython/memory/gctransform/asmgcroot.py
--- a/pypy/rpython/memory/gctransform/asmgcroot.py
+++ b/pypy/rpython/memory/gctransform/asmgcroot.py
@@ -149,52 +149,9 @@
             self._extra_mark_sorted = lambda: True
 
     def need_tealet_support(self, gctransformer, getfn):
-        # tealet support: hooks to save and restore the GC pointers
-        # from the stack before it is whisked away by "tealet.c".
-        GCPTR_ARRAY  = lltype.Ptr(lltype.GcArray(llmemory.GCREF))
-        SIGNED_ARRAY = lltype.Ptr(lltype.GcArray(lltype.Signed))
-        WALKER_PTR   = lltype.Ptr(lltype.Struct('walker',
-                           ('gcptr_array', GCPTR_ARRAY),
-                           ('signed_array', SIGNED_ARRAY)))
-        gcdata = self.gcdata
-        #
-        def ll_count_locations(gc, addr):
-            gcdata._gc_tealet_count += 1
-        #
-        def ll_save_locations(gc, addr):
-            gcref = llmemory.cast_adr_to_ptr(addr.address[0], llmemory.GCREF)
-            gcdata._gc_tealet_array[gcdata._gc_tealet_count] = gcref
-            gcdata._gc_tealet_count += 1
-        #
-        def ll_restore_locations(gc, addr):
-            gcref = gcdata._gc_tealet_array[gcdata._gc_tealet_count]
-            gcdata._gc_tealet_count += 1
-            addr.address[0] = llmemory.cast_ptr_to_adr(gcref)
-        #
-        def ll_save_stack_roots(walker):
-            gcdata._gc_tealet_count = 0
-            self.walk_stack_roots(ll_count_locations)
-            count = gcdata._gc_tealet_count
-            gcdata._gc_tealet_count = 0
-            gcdata._gc_tealet_array = lltype.malloc(GCPTR_ARRAY.TO, count)
-            self.walk_stack_roots(ll_save_locations)
-            walker.gcptr_array = gcdata._gc_tealet_array
-            gcdata._gc_tealet_array = lltype.nullptr(GCPTR_ARRAY.TO)
-        #
-        def ll_restore_stack_roots(walker):
-            gcdata._gc_tealet_array = walker.gcptr_array
-            gcdata._gc_tealet_count = 0
-            self.walk_stack_roots(ll_restore_locations)
-            gcdata._gc_tealet_array = lltype.nullptr(GCPTR_ARRAY.TO)
-        #
-        self.ll_save_stack_roots_ptr = getfn(ll_save_stack_roots,
-                                             [annmodel.SomePtr(WALKER_PTR)],
-                                             annmodel.s_None,
-                                             minimal_transform=False)
-        self.ll_restore_stack_roots_ptr = getfn(ll_restore_stack_roots,
-                                                [annmodel.SomePtr(WALKER_PTR)],
-                                                annmodel.s_None,
-                                                minimal_transform=False)
+        # tealet support: BIG HACK for rlib.rtealet
+        from pypy.rlib import rtealet
+        rtealet._asmstackrootwalker = self     # as a global! argh
 
     def need_thread_support(self, gctransformer, getfn):
         # Threads supported "out of the box" by the rest of the code.
diff --git a/pypy/translator/c/gcc/trackgcroot.py 
b/pypy/translator/c/gcc/trackgcroot.py
--- a/pypy/translator/c/gcc/trackgcroot.py
+++ b/pypy/translator/c/gcc/trackgcroot.py
@@ -1593,31 +1593,20 @@
             {
                __asm {
                 mov\tedx, DWORD PTR [esp+4]\t; 1st argument, which is the 
callback
-                mov\tecx, DWORD PTR [esp+8]\t; 2nd argument, which is 
gcrootanchor
                 mov\teax, esp\t\t; my frame top address
                 push\teax\t\t\t; ASM_FRAMEDATA[6]
                 push\tebp\t\t\t; ASM_FRAMEDATA[5]
                 push\tedi\t\t\t; ASM_FRAMEDATA[4]
                 push\tesi\t\t\t; ASM_FRAMEDATA[3]
                 push\tebx\t\t\t; ASM_FRAMEDATA[2]
-
-            ; Add this ASM_FRAMEDATA to the front of the circular linked
-            ; list.  Let's call it 'self'.
-
-                mov\teax, DWORD PTR [ecx+4]\t\t; next = gcrootanchor->next
-                push\teax\t\t\t\t\t\t\t\t\t; self->next = next
-                push\tecx              ; self->prev = gcrootanchor
-                mov\tDWORD PTR [ecx+4], esp\t\t; gcrootanchor->next = self
-                mov\tDWORD PTR [eax+0], esp\t\t\t\t\t; next->prev = self
+                xor\teax, eax
+                push\teax\t\t\t; ASM_FRAMEDATA[1]
+                push\teax\t\t\t; ASM_FRAMEDATA[0]
 
                 call\tedx\t\t\t\t\t\t; invoke the callback
 
-            ; Detach this ASM_FRAMEDATA from the circular linked list
-                pop\tesi\t\t\t\t\t\t\t; prev = self->prev
-                pop\tedi\t\t\t\t\t\t\t; next = self->next
-                mov\tDWORD PTR [esi+4], edi\t\t; prev->next = next
-                mov\tDWORD PTR [edi+0], esi\t\t; next->prev = prev
-
+                pop\tecx\t\t\t\t; ignored      ASM_FRAMEDATA[0]
+                pop\tecx\t\t\t\t; ignored      ASM_FRAMEDATA[1]
                 pop\tebx\t\t\t\t; restore from ASM_FRAMEDATA[2]
                 pop\tesi\t\t\t\t; restore from ASM_FRAMEDATA[3]
                 pop\tedi\t\t\t\t; restore from ASM_FRAMEDATA[4]
@@ -1640,7 +1629,6 @@
             /* See description in asmgcroot.py */
             .cfi_startproc
             /* %rdi is the 1st argument, which is the callback */
-            /* %rsi is the 2nd argument, which is gcrootanchor */
             movq\t%rsp, %rax\t/* my frame top address */
             pushq\t%rax\t\t/* ASM_FRAMEDATA[8] */
             pushq\t%rbp\t\t/* ASM_FRAMEDATA[7] */
@@ -1649,26 +1637,17 @@
             pushq\t%r13\t\t/* ASM_FRAMEDATA[4] */
             pushq\t%r12\t\t/* ASM_FRAMEDATA[3] */
             pushq\t%rbx\t\t/* ASM_FRAMEDATA[2] */
+            xorq\t%rax,%rax
+            pushq\t%rax\t\t/* ASM_FRAMEDATA[1] */
+            pushq\t%rax\t\t/* ASM_FRAMEDATA[0] */
 
-            /* Add this ASM_FRAMEDATA to the front of the circular linked */
-            /* list.  Let's call it 'self'.                               */
-
-            movq\t8(%rsi), %rax\t/* next = gcrootanchor->next */
-            pushq\t%rax\t\t\t\t/* self->next = next */
-            pushq\t%rsi\t\t\t/* self->prev = gcrootanchor */
-            movq\t%rsp, 8(%rsi)\t/* gcrootanchor->next = self */
-            movq\t%rsp, 0(%rax)\t\t\t/* next->prev = self */
             .cfi_def_cfa_offset 80\t/* 9 pushes + the retaddr = 80 bytes */
 
             /* note: the Mac OS X 16 bytes aligment must be respected. */
             call\t*%rdi\t\t/* invoke the callback */
 
-            /* Detach this ASM_FRAMEDATA from the circular linked list */
-            popq\t%rsi\t\t/* prev = self->prev */
-            popq\t%rdi\t\t/* next = self->next */
-            movq\t%rdi, 8(%rsi)\t/* prev->next = next */
-            movq\t%rsi, 0(%rdi)\t/* next->prev = prev */
-
+            popq\t%rcx\t\t/* ignored      ASM_FRAMEDATA[0] */
+            popq\t%rcx\t\t/* ignored      ASM_FRAMEDATA[1] */
             popq\t%rbx\t\t/* restore from ASM_FRAMEDATA[2] */
             popq\t%r12\t\t/* restore from ASM_FRAMEDATA[3] */
             popq\t%r13\t\t/* restore from ASM_FRAMEDATA[4] */
@@ -1701,32 +1680,21 @@
             print >> output, """\
             /* See description in asmgcroot.py */
             movl\t4(%esp), %edx\t/* 1st argument, which is the callback */
-            movl\t8(%esp), %ecx\t/* 2nd argument, which is gcrootanchor */
             movl\t%esp, %eax\t/* my frame top address */
             pushl\t%eax\t\t/* ASM_FRAMEDATA[6] */
             pushl\t%ebp\t\t/* ASM_FRAMEDATA[5] */
             pushl\t%edi\t\t/* ASM_FRAMEDATA[4] */
             pushl\t%esi\t\t/* ASM_FRAMEDATA[3] */
             pushl\t%ebx\t\t/* ASM_FRAMEDATA[2] */
-
-            /* Add this ASM_FRAMEDATA to the front of the circular linked */
-            /* list.  Let's call it 'self'.                               */
-
-            movl\t4(%ecx), %eax\t/* next = gcrootanchor->next */
-            pushl\t%eax\t\t\t\t/* self->next = next */
-            pushl\t%ecx\t\t\t/* self->prev = gcrootanchor */
-            movl\t%esp, 4(%ecx)\t/* gcrootanchor->next = self */
-            movl\t%esp, 0(%eax)\t\t\t/* next->prev = self */
+            xorl\t%eax,%eax
+            pushl\t%eax\t\t/* ASM_FRAMEDATA[1] */
+            pushl\t%eax\t\t/* ASM_FRAMEDATA[0] */
 
             /* note: the Mac OS X 16 bytes aligment must be respected. */
             call\t*%edx\t\t/* invoke the callback */
 
-            /* Detach this ASM_FRAMEDATA from the circular linked list */
-            popl\t%esi\t\t/* prev = self->prev */
-            popl\t%edi\t\t/* next = self->next */
-            movl\t%edi, 4(%esi)\t/* prev->next = next */
-            movl\t%esi, 0(%edi)\t/* next->prev = prev */
-
+            popl\t%ecx\t\t/* ignored      ASM_FRAMEDATA[0] */
+            popl\t%ecx\t\t/* ignored      ASM_FRAMEDATA[1] */
             popl\t%ebx\t\t/* restore from ASM_FRAMEDATA[2] */
             popl\t%esi\t\t/* restore from ASM_FRAMEDATA[3] */
             popl\t%edi\t\t/* restore from ASM_FRAMEDATA[4] */
diff --git a/pypy/translator/c/src/mem.h b/pypy/translator/c/src/mem.h
--- a/pypy/translator/c/src/mem.h
+++ b/pypy/translator/c/src/mem.h
@@ -6,7 +6,7 @@
 extern char __gcmapstart;
 extern char __gcmapend;
 extern char __gccallshapes;
-extern long pypy_asm_stackwalk(void*, void*);
+extern long pypy_asm_stackwalk(void*);
 #define __gcnoreorderhack __gcmapend
 
 /* The following pseudo-instruction is used by --gcrootfinder=asmgcc
@@ -52,7 +52,7 @@
 extern void* __gcmapstart;
 extern void* __gcmapend;
 extern char* __gccallshapes;
-extern long pypy_asm_stackwalk(void*, void*);
+extern long pypy_asm_stackwalk(void*);
 
 /* With the msvc Microsoft Compiler, the optimizer seems free to move
    any code (even asm) that involves local memory (registers and stack).
diff --git a/pypy/translator/c/src/tealet/tealet.c 
b/pypy/translator/c/src/tealet/tealet.c
--- a/pypy/translator/c/src/tealet/tealet.c
+++ b/pypy/translator/c/src/tealet/tealet.c
@@ -598,3 +598,21 @@
     stack_free(g_main, g_target->stack_copy);
     g_free(g_main, g_target);
 }
+
+#if STACK_DIRECTION != 0
+#  error "fix _tealet_translate_pointer below"
+#endif
+char **_tealet_translate_pointer(tealet_t *context, char **ptr)
+{
+  tealet_sub_t *g_tealet = (tealet_sub_t *)context;
+  /* if g_tealet is not suspended, then stack_start is probably NULL,
+     giving nonsense in the following computation.  But then stack_saved
+     is 0, so the following test can never be true. */
+  char *p = (char *)ptr;
+  long delta = p - g_tealet->stack_start;
+  if (((unsigned long)delta) < ((unsigned long)g_tealet->stack_saved)) {
+    /* a pointer to a saved away word */
+    return (char **)(g_tealet->stack_copy + delta);
+  }
+  return ptr;
+}
diff --git a/pypy/translator/c/src/tealet/tealet.h 
b/pypy/translator/c/src/tealet/tealet.h
--- a/pypy/translator/c/src/tealet/tealet.h
+++ b/pypy/translator/c/src/tealet/tealet.h
@@ -144,4 +144,10 @@
 TEALET_API
 int tealet_stub_run(tealet_t *stub, tealet_run_t run, void *run_arg);
 
+/* Hack: translate a pointer into the stack of a tealet into a pointer
+ * to where it is really stored so far.  Only to access word-sized data.
+ */
+TEALET_API
+char **_tealet_translate_pointer(tealet_t *context, char **ptr);
+
 #endif /* _TEALET_H_ */
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to