[pypy-svn] r71506 - in pypy/branch/asmgcc-cantcollect/pypy: rpython/memory/gctransform translator/c/gcc translator/c/src

afa at codespeak.net afa at codespeak.net
Thu Feb 25 19:18:12 CET 2010


Author: afa
Date: Thu Feb 25 19:18:10 2010
New Revision: 71506

Modified:
   pypy/branch/asmgcc-cantcollect/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/asmgcc-cantcollect/pypy/translator/c/gcc/trackgcroot.py
   pypy/branch/asmgcc-cantcollect/pypy/translator/c/src/mem.h
Log:
Follow Armin's suggestion and move the special case of pypy_asm_stackwalk in the gc transformer

Also replace gcmaptable.s by gcmaptable.c on windows:
the MASM assembler cannot handle more than 65536 externals...


Modified: pypy/branch/asmgcc-cantcollect/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/asmgcc-cantcollect/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/asmgcc-cantcollect/pypy/rpython/memory/gctransform/framework.py	Thu Feb 25 19:18:10 2010
@@ -40,7 +40,12 @@
                 return True
         return graphanalyze.GraphAnalyzer.analyze_direct_call(self, graph,
                                                               seen)
-    
+    def analyze_external_call(self, op, seen=None):
+        funcobj = op.args[0].value._obj
+        if funcobj._name == 'pypy_asm_stackwalk':
+            return True
+        return graphanalyze.GraphAnalyzer.analyze_external_call(self, op,
+                                                                seen)
     def analyze_simple_operation(self, op):
         if op.opname in ('malloc', 'malloc_varsize'):
             flags = op.args[1].value

Modified: pypy/branch/asmgcc-cantcollect/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/asmgcc-cantcollect/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/asmgcc-cantcollect/pypy/translator/c/gcc/trackgcroot.py	Thu Feb 25 19:18:10 2010
@@ -126,8 +126,6 @@
             match = self.r_gcnocollect_marker.search(line)
             if match:
                 name = match.group(1)
-                if name in ('pypy_g_walk_roots', 'pypy_asm_stackwalk'):
-                    continue
                 if self.format in ('darwin', 'mingw32', 'msvc'):
                     name = '_' + name
                 self.cannot_collect[name] = True
@@ -1201,9 +1199,7 @@
 
     def dump(self, output):
         assert self.seen_main
-        shapes = {}
-        shapelines = []
-        shapeofs = 0
+
         def _globalname(name, disp=""):
             if self.format in ('darwin', 'mingw32', 'msvc'):
                 name = '_' + name
@@ -1267,103 +1263,127 @@
                 else:
                     return '%' + name
 
-        def _offset(name):
-            if self.format == 'msvc':
-                return "OFFSET %s" % _globalname(name)
-            else:
-                return "$%s" % _globalname(name)
-
         def _call(arg, comment):
             if self.format == 'msvc':
                 print >> output, "\tcall\t%s\t\t;%s" % (arg, comment)
             else:
                 print >> output, "\tcall\t%s\t\t/* %s */" % (arg, comment)
 
-        def _indirectjmp(arg):
-            if self.format == 'msvc':
-                return "DWORD PTR " + arg
-            else:
-                return "*%" + arg
-
         if self.format == 'msvc':
             print >> output, """\
-            TITLE\tgcmaptable.s
-            .686P
-            .XMM
-            .model\tflat
+            /* A circular doubly-linked list of all
+             * the ASM_FRAMEDATAs currently alive
+             */
+            struct asm_framedata {
+                struct asm_framedata* prev;
+                struct asm_framedata* next;
+            } __gcrootanchor = { &__gcrootanchor, &__gcrootanchor };
+
+            /* See description in asmgcroot.py */
+            __declspec(naked)
+            long pypy_asm_stackwalk(void *callback)
+            {
+               __asm {
+                mov	edx, DWORD PTR [esp+4]		; my argument, which is the callback
+                ;mov	edx, callback	; my argument, which is the callback
+                mov	eax, esp		; my frame top address
+                push	eax			; ASM_FRAMEDATA[6]
+                push	ebp			; ASM_FRAMEDATA[5]
+                push	edi			; ASM_FRAMEDATA[4]
+                push	esi			; ASM_FRAMEDATA[3]
+                push	ebx			; ASM_FRAMEDATA[2]
+
+            ; Add this ASM_FRAMEDATA to the front of the circular linked
+            ; list.  Let's call it 'self'.
+
+                mov	eax, DWORD PTR [__gcrootanchor+4]		; next = gcrootanchor->next
+                push	eax									; self->next = next
+                push	OFFSET __gcrootanchor              ; self->prev = gcrootanchor
+                mov	DWORD PTR [__gcrootanchor+4], esp		; gcrootanchor->next = self
+                mov	DWORD PTR [eax+0], esp					; next->prev = self
+
+                call	edx						; invoke the callback
+
+            ; Detach this ASM_FRAMEDATA from the circular linked list
+                pop	esi							; prev = self->prev
+                pop	edi							; next = self->next
+                mov	DWORD PTR [esi+4], edi		; prev->next = next
+                mov	DWORD PTR [edi+0], esi		; next->prev = prev
+
+                pop	ebx				; restore from ASM_FRAMEDATA[2]
+                pop	esi				; restore from ASM_FRAMEDATA[3]
+                pop	edi				; restore from ASM_FRAMEDATA[4]
+                pop	ebp				; restore from ASM_FRAMEDATA[5]
+                pop	ecx				; ignored      ASM_FRAMEDATA[6]
+            ; the return value is the one of the 'call' above,
+            ; because %eax (and possibly %edx) are unmodified
+                ret
+               }
+            }
             """
 
-        _variant(elf='\t.text',
-                 darwin='\t.text',
-                 mingw32='\t.text',
-                 msvc='_TEXT\tSEGMENT')
-
-        _globl('pypy_asm_stackwalk')
-        _variant(elf='.type pypy_asm_stackwalk, @function',
-                 darwin='',
-                 mingw32='',
-                 msvc='')
-        _label('pypy_asm_stackwalk')
-        _comment("See description in asmgcroot.py")
-        _movl(_register("esp", disp="4"), _register("edx"), "my argument, which is the callback")
-        _movl(_register("esp"), _register("eax"), "my frame top address")
-        _pushl(_register("eax"), "ASM_FRAMEDATA[6]")
-        _pushl(_register("ebp"), "ASM_FRAMEDATA[5]")
-        _pushl(_register("edi"), "ASM_FRAMEDATA[4]")
-        _pushl(_register("esi"), "ASM_FRAMEDATA[3]")
-        _pushl(_register("ebx"), "ASM_FRAMEDATA[2]")
-
-        print >> output
-        _comment("Add this ASM_FRAMEDATA to the front of the circular linked")
-        _comment("list.  Let's call it 'self'.")
-        print >> output
-        _movl(_globalname("__gcrootanchor", disp=4), _register("eax"), "next = gcrootanchor->next")
-        _pushl(_register("eax"),                                       "self->next = next")
-        _pushl(_offset("__gcrootanchor"),                              "self->prev = gcrootanchor")
-        _movl(_register("esp"), _globalname("__gcrootanchor", disp=4), "gcrootanchor->next = self")
-        _movl(_register("esp"), _register("eax", "0"),                 "next->prev = self")
-        print >> output
-
-        _comment("note: the Mac OS X 16 bytes aligment must be respected.")
-        _call(_indirectjmp("edx"),                                    "invoke the callback")
-        print >> output
-
-        _comment("Detach this ASM_FRAMEDATA from the circular linked list")
-        _popl(_register("esi"),                                       "prev = self->prev")
-        _popl(_register("edi"),                                       "next = self->next")
-        _movl(_register("edi"), _register("esi", disp="4"),           "prev->next = next")
-        _movl(_register("esi"), _register("edi", disp="0"),           "next->prev = prev")
-        print >> output
-
-        _popl(_register("ebx"),                                       "restore from ASM_FRAMEDATA[2]")
-        _popl(_register("esi"),                                       "restore from ASM_FRAMEDATA[3]")
-        _popl(_register("edi"),                                       "restore from ASM_FRAMEDATA[4]")
-        _popl(_register("ebp"),                                       "restore from ASM_FRAMEDATA[5]")
-        _popl(_register("ecx"),                                       "ignored      ASM_FRAMEDATA[6]")
-        _comment("the return value is the one of the 'call' above,")
-        _comment("because %eax (and possibly %edx) are unmodified")
-
-        print >> output, "\tret"
-
-        _variant(elf='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
-                 darwin='',
-                 mingw32='',
-                 msvc='')
+        else:
+            _variant(elf='\t.text',
+                     darwin='\t.text',
+                     mingw32='\t.text')
+
+            _globl('pypy_asm_stackwalk')
+            _variant(elf='.type pypy_asm_stackwalk, @function',
+                     darwin='',
+                     mingw32='')
+            _label('pypy_asm_stackwalk')
+            _comment("See description in asmgcroot.py")
+            _movl(_register("esp", disp="4"), _register("edx"), "my argument, which is the callback")
+            _movl(_register("esp"), _register("eax"), "my frame top address")
+            _pushl(_register("eax"), "ASM_FRAMEDATA[6]")
+            _pushl(_register("ebp"), "ASM_FRAMEDATA[5]")
+            _pushl(_register("edi"), "ASM_FRAMEDATA[4]")
+            _pushl(_register("esi"), "ASM_FRAMEDATA[3]")
+            _pushl(_register("ebx"), "ASM_FRAMEDATA[2]")
+
+            print >> output
+            _comment("Add this ASM_FRAMEDATA to the front of the circular linked")
+            _comment("list.  Let's call it 'self'.")
+            print >> output
+            _movl(_globalname("__gcrootanchor", disp=4), _register("eax"), "next = gcrootanchor->next")
+            _pushl(_register("eax"),                                       "self->next = next")
+            _pushl("$%s" % _globalname("__gcrootanchor"),                  "self->prev = gcrootanchor")
+            _movl(_register("esp"), _globalname("__gcrootanchor", disp=4), "gcrootanchor->next = self")
+            _movl(_register("esp"), _register("eax", "0"),                 "next->prev = self")
+            print >> output
+
+            _comment("note: the Mac OS X 16 bytes aligment must be respected.")
+            _call("*%edx",                               "invoke the callback")
+            print >> output
+
+            _comment("Detach this ASM_FRAMEDATA from the circular linked list")
+            _popl(_register("esi"),                                       "prev = self->prev")
+            _popl(_register("edi"),                                       "next = self->next")
+            _movl(_register("edi"), _register("esi", disp="4"),           "prev->next = next")
+            _movl(_register("esi"), _register("edi", disp="0"),           "next->prev = prev")
+            print >> output
+
+            _popl(_register("ebx"),                                       "restore from ASM_FRAMEDATA[2]")
+            _popl(_register("esi"),                                       "restore from ASM_FRAMEDATA[3]")
+            _popl(_register("edi"),                                       "restore from ASM_FRAMEDATA[4]")
+            _popl(_register("ebp"),                                       "restore from ASM_FRAMEDATA[5]")
+            _popl(_register("ecx"),                                       "ignored      ASM_FRAMEDATA[6]")
+            _comment("the return value is the one of the 'call' above,")
+            _comment("because %eax (and possibly %edx) are unmodified")
+
+            print >> output, "\tret"
+
+            _variant(elf='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
+                     darwin='',
+                     mingw32='')
 
         if self.format == 'msvc':
             for label, state, is_range in self.gcmaptable:
-                print >> output, "EXTERN %s:NEAR" % label
-
-        if self.format == 'msvc':
-            print >> output, '_DATA SEGMENT'
-
-        _comment("A circular doubly-linked list of all")
-        _comment("the ASM_FRAMEDATAs currently alive")
-        if self.format == 'msvc':
-            _globl('__gcrootanchor')
-            print >> output, '%s\tDD FLAT:___gcrootanchor  ; prev' % _globalname("__gcrootanchor")
-            print >> output, '\tDD FLAT:___gcrootanchor  ; next'
+                label = label[1:]
+                print >> output, "extern void* %s;" % label
         else:
+            _comment("A circular doubly-linked list of all")
+            _comment("the ASM_FRAMEDATAs currently alive")
             print >> output, '\t.data'
             print >> output, '\t.align\t4'
             _globl('__gcrootanchor')
@@ -1371,59 +1391,71 @@
             print >> output, """\
             .long\t__gcrootanchor       /* prev */
             .long\t__gcrootanchor       /* next */
-""".replace("__gcrootanchor", _globalname("__gcrootanchor"))
+            """.replace("__gcrootanchor", _globalname("__gcrootanchor"))
+
+        shapes = {}
+        shapelines = []
+        shapeofs = 0
 
-        _globl('__gcmapstart')
         if self.format == 'msvc':
-            print >> output, '%s' % _globalname('__gcmapstart'),
+            print >> output, """\
+            struct { void* addr; long shape; } __gcmap[%d] = {
+            """ % (len(self.gcmaptable),)
+            for label, state, is_range in self.gcmaptable:
+                label = label[1:]
+                try:
+                    n = shapes[state]
+                except KeyError:
+                    n = shapes[state] = shapeofs
+                    bytes = [str(b) for b in compress_callshape(state)]
+                    shapelines.append('\t%s,\t/* %s */\n' % (
+                            ', '.join(bytes),
+                            shapeofs))
+                    shapeofs += len(bytes)
+                if is_range:
+                    n = ~ n
+                print >> output, '{ &%s, %d},' % (label, n)
+            print >> output, """\
+            };
+            void* __gcmapstart = &__gcmap;
+            void* __gcmapend = (char*)(&__gcmap) + 8 * %d;
+
+            char __gccallshapes[] = {
+            """ % (len(self.gcmaptable),)
+            output.writelines(shapelines)
+            print >> output, """\
+            };
+            """
         else:
+            _globl('__gcmapstart')
             _label('__gcmapstart')
-        for label, state, is_range in self.gcmaptable:
-            try:
-                n = shapes[state]
-            except KeyError:
-                n = shapes[state] = shapeofs
-                bytes = [str(b) for b in compress_callshape(state)]
-                if self.format == 'msvc':
-                    shapelines.append('\tDB\t%s\t;%s\n' % (
-                        ', '.join(bytes),
-                        shapeofs))
-                else:
+            for label, state, is_range in self.gcmaptable:
+                try:
+                    n = shapes[state]
+                except KeyError:
+                    n = shapes[state] = shapeofs
+                    bytes = [str(b) for b in compress_callshape(state)]
                     shapelines.append('\t/*%d*/\t.byte\t%s\n' % (
                         shapeofs,
                         ', '.join(bytes)))
-                shapeofs += len(bytes)
-            if is_range:
-                n = ~ n
-            if self.format == 'msvc':
-                print >> output, '\tDD\t%s' % (label,)
-                print >> output, '\tDD\t%d' % (n,)
-            else:
+                    shapeofs += len(bytes)
+                if is_range:
+                    n = ~ n
                 print >> output, '\t.long\t%s-%d' % (
                     label,
                     PARSERS[self.format].FunctionGcRootTracker.OFFSET_LABELS)
                 print >> output, '\t.long\t%d' % (n,)
 
-        _globl('__gcmapend')
-        if self.format == 'msvc':
-            print >> output, '%s DD ?' % _globalname('__gcmapend')
-        else:
+            _globl('__gcmapend')
             _label('__gcmapend')
-        _variant(elf='.section\t.rodata',
-                 darwin='.const',
-                 mingw32='',
-                 msvc='')
 
-        _globl('__gccallshapes')
-        if self.format == 'msvc':
-            print >> output, _globalname('__gccallshapes'),
-        else:
-            _label('__gccallshapes')
-        output.writelines(shapelines)
+            _variant(elf='.section\t.rodata',
+                     darwin='.const',
+                     mingw32='')
 
-        if self.format == 'msvc':
-            print >> output, "_DATA\tENDS"
-            print >> output, "END"
+            _globl('__gccallshapes')
+            _label('__gccallshapes')
+            output.writelines(shapelines)
 
     def process(self, iterlines, newfile, entrypoint='main', filename='?'):
         parser = PARSERS[format](verbose=self.verbose, shuffle=self.shuffle)

Modified: pypy/branch/asmgcc-cantcollect/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/asmgcc-cantcollect/pypy/translator/c/src/mem.h	(original)
+++ pypy/branch/asmgcc-cantcollect/pypy/translator/c/src/mem.h	Thu Feb 25 19:18:10 2010
@@ -2,6 +2,7 @@
 /************************************************************/
  /***  C header subsection: operations on LowLevelTypes    ***/
 
+#ifndef _MSC_VER
 extern char __gcmapstart;
 extern char __gcmapend;
 extern char __gccallshapes;
@@ -18,7 +19,6 @@
    and one in a register), pass one to GCROOT, and later use the other
    one.  In practice the pypy_asm_gcroot() is often a no-op in the final
    machine code and doesn't prevent most optimizations. */
-#ifndef _MSC_VER
 
 /* With gcc, getting the asm() right was tricky, though.  The asm() is
    not volatile so that gcc is free to delete it if the output variable
@@ -43,7 +43,19 @@
 /* marker for trackgcroot.py */
 #define pypy_asm_stack_bottom()  asm volatile ("/* GC_STACK_BOTTOM */" : : )
 
+#define OP_GC_ASMGCROOT_STATIC(i, r)   r =      \
+               i == 0 ? (void*)&__gcmapstart :         \
+               i == 1 ? (void*)&__gcmapend :           \
+               i == 2 ? (void*)&__gccallshapes :       \
+               i == 3 ? (void*)&__gcrootanchor :       \
+               NULL
+
 #else
+extern void* __gcmapstart;
+extern void* __gcmapend;
+extern char* __gccallshapes;
+extern void* __gcrootanchor;
+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).
@@ -66,17 +78,17 @@
 #define pypy_asm_keepalive(v)    __asm { }
 static __declspec(noinline) void pypy_asm_stack_bottom() { }
 
-#endif
-
-
-
 #define OP_GC_ASMGCROOT_STATIC(i, r)   r =      \
-               i == 0 ? (void*)&__gcmapstart :         \
-               i == 1 ? (void*)&__gcmapend :           \
+               i == 0 ? (void*)__gcmapstart :         \
+               i == 1 ? (void*)__gcmapend :           \
                i == 2 ? (void*)&__gccallshapes :       \
                i == 3 ? (void*)&__gcrootanchor :       \
                NULL
 
+#endif
+
+
+
 #define RAW_MALLOC_ZERO_FILLED 0
 
 #if RAW_MALLOC_ZERO_FILLED



More information about the Pypy-commit mailing list