[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