[pypy-commit] pypy release-1.6.x: Test and (90% of a) fix.
arigo
noreply at buildbot.pypy.org
Sat Aug 13 12:17:38 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: release-1.6.x
Changeset: r46475:6fa38d806a56
Date: 2011-08-13 11:08 +0200
http://bitbucket.org/pypy/pypy/changeset/6fa38d806a56/
Log: Test and (90% of a) fix.
diff --git a/pypy/translator/c/gcc/instruction.py b/pypy/translator/c/gcc/instruction.py
--- a/pypy/translator/c/gcc/instruction.py
+++ b/pypy/translator/c/gcc/instruction.py
@@ -68,15 +68,21 @@
class Insn(object):
_args_ = []
_locals_ = []
+ hack = None
def __repr__(self):
- return '%s(%s)' % (self.__class__.__name__,
+ return '%s(%s) --- %r' % (self.__class__.__name__,
', '.join([str(getattr(self, name))
- for name in self._args_]))
+ for name in self._args_]),
+ self.hack)
def requestgcroots(self, tracker):
return {}
def source_of(self, localvar, tag):
+ if tag is None:
+ if self.hack is None:
+ self.hack = set()
+ self.hack.add(localvar)
return localvar
def all_sources_of(self, localvar):
@@ -139,7 +145,7 @@
def source_of(self, localvar, tag):
if localvar == self.target:
return somenewvalue
- return localvar
+ return Insn.source_of(self, localvar, tag)
def all_sources_of(self, localvar):
if localvar == self.target:
@@ -157,7 +163,7 @@
def source_of(self, localvar, tag):
if localvar == self.target:
return self.source
- return localvar
+ return Insn.source_of(self, localvar, tag)
def all_sources_of(self, localvar):
if localvar == self.target:
diff --git a/pypy/translator/c/gcc/test/elf64/track_zero.s b/pypy/translator/c/gcc/test/elf64/track_zero.s
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/gcc/test/elf64/track_zero.s
@@ -0,0 +1,18 @@
+ .type pypy_g_do_call_1, @function
+pypy_g_do_call_1:
+ pushq %rbx
+ pushq %r12
+ movq %rdi, %rbx
+ movq %rsi, %r12
+ call number1
+ ;; expected {16(%rsp) | 8(%rsp), (%rsp), %r13, %r14, %r15, %rbp | %r12}
+ testq %rbx, %rbx ; here rbx is an integer, not a gc ref
+ je .L1 ; if rbx==0, jump to L1, where rbx==NULLGCREF
+ movq (%rax), %rbx ; else load a gc ref
+.L1:
+ /* GCROOT %rbx */
+ /* GCROOT %r12 */
+ popq %r12
+ popq %rbx
+ ret
+ .size pypy_g_do_call_1, .-pypy_g_do_call_1
diff --git a/pypy/translator/c/gcc/test/elf64/track_zero_2.s b/pypy/translator/c/gcc/test/elf64/track_zero_2.s
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/gcc/test/elf64/track_zero_2.s
@@ -0,0 +1,18 @@
+ .type pypy_g_do_call_1, @function
+pypy_g_do_call_1:
+ pushq %rbx
+ pushq %r12
+ movq %rdi, %rbx
+ movq %rsi, %r12
+ call number1
+ ;; expected {16(%rsp) | 8(%rsp), (%rsp), %r13, %r14, %r15, %rbp | %rbx, %r12}
+ testq %rbx, %rbx
+ je .L1
+ movq (%rax), %r12
+.L1:
+ /* GCROOT %rbx */
+ /* GCROOT %r12 */
+ popq %r12
+ popq %rbx
+ ret
+ .size pypy_g_do_call_1, .-pypy_g_do_call_1
diff --git a/pypy/translator/c/gcc/test/elf64/track_zero_3.s b/pypy/translator/c/gcc/test/elf64/track_zero_3.s
new file mode 100644
--- /dev/null
+++ b/pypy/translator/c/gcc/test/elf64/track_zero_3.s
@@ -0,0 +1,14 @@
+ .type pypy_g_do_call_1, @function
+pypy_g_do_call_1:
+ pushq %rbx
+ movq %rdi, %rbx
+ call number1
+ ;; expected {8(%rsp) | (%rsp), %r12, %r13, %r14, %r15, %rbp | %rbx}
+ testq %rax, %rax
+ je .L1
+ call RPyAssertFailed
+.L1:
+ /* GCROOT %rbx */
+ popq %rbx
+ ret
+ .size pypy_g_do_call_1, .-pypy_g_do_call_1
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
@@ -173,6 +173,7 @@
def parse_instructions(self):
self.insns = [InsnFunctionStart(self.CALLEE_SAVE_REGISTERS, self.WORD)]
+ self.tested_for_zero = None
ignore_insns = False
for lineno, line in enumerate(self.lines):
if lineno < self.skip:
@@ -186,6 +187,14 @@
elif match:
if not ignore_insns:
opname = match.group(1)
+ #
+ try:
+ cf = self.OPS_WITH_PREFIXES_CHANGING_FLAGS[opname]
+ except KeyError:
+ cf = self.find_missing_changing_flags(opname)
+ if cf:
+ self.tested_for_zero = None
+ #
try:
meth = getattr(self, 'visit_' + opname)
except AttributeError:
@@ -222,6 +231,15 @@
raise UnrecognizedOperation(opname)
setattr(cls, 'visit_' + opname, cls.visit_nop)
+ @classmethod
+ def find_missing_changing_flags(cls, opname):
+ prefix = opname
+ while prefix and prefix not in cls.OPS_WITH_PREFIXES_CHANGING_FLAGS:
+ prefix = prefix[:-1]
+ cf = cls.OPS_WITH_PREFIXES_CHANGING_FLAGS.get(prefix, False)
+ cls.OPS_WITH_PREFIXES_CHANGING_FLAGS[opname] = cf
+ return cf
+
def list_collecting_call_insns(self):
return [insn for insn in self.insns if isinstance(insn, InsnCall)
if insn.name not in self.cannot_collect]
@@ -467,6 +485,19 @@
'movz',
])
+ # a partial list is hopefully good enough for now; it's all to support
+ # only one corner case, tested in elf64/track_zero.s
+ OPS_WITH_PREFIXES_CHANGING_FLAGS = dict.fromkeys([
+ 'cmp', 'test', 'lahf', 'cld', 'std', 'rep',
+ 'ucomi', 'comi',
+ 'add', 'sub', 'xor',
+ 'inc', 'dec', 'not', 'neg', 'or', 'and', 'sbb', 'adc',
+ 'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'mul', 'imul', 'div', 'idiv',
+ 'bt', 'call', 'int',
+ 'jmp', # not really changing flags, but we shouldn't assume
+ # anything about the operations on the following lines
+ ], True)
+
visit_movb = visit_nop
visit_movw = visit_nop
visit_addb = visit_nop
@@ -687,11 +718,13 @@
return InsnRet(self.CALLEE_SAVE_REGISTERS)
return InsnStop("jump")
- def register_jump_to(self, label):
- if not isinstance(self.insns[-1], InsnStop):
- self.labels[label].previous_insns.append(self.insns[-1])
+ def register_jump_to(self, label, lastinsn=None):
+ if lastinsn is None:
+ lastinsn = self.insns[-1]
+ if not isinstance(lastinsn, InsnStop):
+ self.labels[label].previous_insns.append(lastinsn)
- def conditional_jump(self, line):
+ def conditional_jump(self, line, je=False, jne=False):
match = self.r_jump.match(line)
if not match:
match = self.r_jump_rel_label.match(line)
@@ -708,12 +741,22 @@
i += 1
else:
label = match.group(1)
- self.register_jump_to(label)
- return [InsnCondJump(label)]
+ prefix = []
+ lastinsn = None
+ postfix = []
+ if self.tested_for_zero is not None:
+ if je:
+ # generate pseudo-code...
+ prefix = [InsnCopyLocal(self.tested_for_zero, '%tmp'),
+ InsnSetLocal(self.tested_for_zero)]
+ postfix = [InsnCopyLocal('%tmp', self.tested_for_zero)]
+ lastinsn = prefix[-1]
+ elif jne:
+ postfix = [InsnSetLocal(self.tested_for_zero)]
+ self.register_jump_to(label, lastinsn)
+ return prefix + [InsnCondJump(label)] + postfix
visit_jmpl = visit_jmp
- visit_je = conditional_jump
- visit_jne = conditional_jump
visit_jg = conditional_jump
visit_jge = conditional_jump
visit_jl = conditional_jump
@@ -731,6 +774,20 @@
visit_jc = conditional_jump
visit_jnc = conditional_jump
+ def visit_je(self, line):
+ return self.conditional_jump(line, je=True)
+
+ def visit_jne(self, line):
+ return self.conditional_jump(line, jne=True)
+
+ def _visit_test(self, line):
+ match = self.r_binaryinsn.match(line)
+ source = match.group("source")
+ target = match.group("target")
+ if source == target:
+ self.tested_for_zero = source
+ return []
+
def _visit_xchg(self, line):
# only support the format used in VALGRIND_DISCARD_TRANSLATIONS
# which is to use a marker no-op "xchgl %ebx, %ebx"
@@ -884,6 +941,7 @@
visit_and = FunctionGcRootTracker._visit_and
visit_xchgl = FunctionGcRootTracker._visit_xchg
+ visit_testl = FunctionGcRootTracker._visit_test
# used in "xor reg, reg" to create a NULL GC ptr
visit_xorl = FunctionGcRootTracker.binary_insn
@@ -942,6 +1000,7 @@
visit_xorq = FunctionGcRootTracker.binary_insn
visit_xchgq = FunctionGcRootTracker._visit_xchg
+ visit_testq = FunctionGcRootTracker._visit_test
# FIXME: similar to visit_popl for 32-bit
def visit_popq(self, line):
More information about the pypy-commit
mailing list