[pypy-svn] r50266 - in pypy/branch/asmgcroot/pypy: config rpython/memory/gctransform translator/c translator/c/src
arigo at codespeak.net
arigo at codespeak.net
Wed Jan 2 17:52:50 CET 2008
Author: arigo
Date: Wed Jan 2 17:52:49 2008
New Revision: 50266
Added:
pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py
- copied, changed from r50261, pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/llvmgcroot.py
Modified:
pypy/branch/asmgcroot/pypy/config/translationoption.py
pypy/branch/asmgcroot/pypy/translator/c/funcgen.py
pypy/branch/asmgcroot/pypy/translator/c/gc.py
pypy/branch/asmgcroot/pypy/translator/c/genc.py
pypy/branch/asmgcroot/pypy/translator/c/src/mem.h
pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py
Log:
Another in-progress check-in.
Modified: pypy/branch/asmgcroot/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/config/translationoption.py (original)
+++ pypy/branch/asmgcroot/pypy/config/translationoption.py Wed Jan 2 17:52:49 2008
@@ -64,8 +64,12 @@
suggests=[("translation.gc", "marksweep")]),
BoolOption("llvmgcroot", "Use the 'llvm.gcroot' primitive to find roots",
default=False, cmdline="--llvmgcroot",
- requires=[("translation.gctransformer", "framework")],
- suggests=[("translation.backend", "llvm")]),
+ requires=[("translation.gctransformer", "framework"),
+ ("translation.backend", "llvm")]),
+ BoolOption("asmgcroot", "Use the 'trackgcroot' asm hack to find roots",
+ default=False, cmdline="--asmgcroot",
+ requires=[("translation.gctransformer", "framework"),
+ ("translation.backend", "c")]),
BoolOption("thread", "enable use of threading primitives",
default=False, cmdline="--thread",
requires=[("translation.gc", "boehm")]),
Modified: pypy/branch/asmgcroot/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/funcgen.py (original)
+++ pypy/branch/asmgcroot/pypy/translator/c/funcgen.py Wed Jan 2 17:52:49 2008
@@ -217,16 +217,6 @@
def cfunction_body(self):
graph = self.graph
-
- gcrootscount = 0
- for block in graph.iterblocks():
- for op in block.operations:
- if op.opname == 'llvm_store_gcroot':
- index = op.args[0].value
- gcrootscount = max(gcrootscount, index+1)
- for i in range(gcrootscount):
- yield 'void* gcroot%d;' % i
-
# generate the body of each block
for block in graph.iterblocks():
self.currentblock = block
@@ -732,16 +722,8 @@
def OP_IS_EARLY_CONSTANT(self, op):
return self.expr(op.result) + ' = 0;' # Allways false
- def OP_LLVM_STORE_GCROOT(self, op):
- index = op.args[0].value
- value = self.expr(op.args[1])
- return ('gcroot%d = %s; ' % (index, value) +
- 'asm volatile ("/*STORE GCROOT %%0*/"::"m"(gcroot%d));' % (index,))
-
- def OP_LLVM_LOAD_GCROOT(self, op):
- index = op.args[0].value
- result = self.expr(op.result)
- return ('%s = gcroot%d; ' % (result, index) +
- 'asm volatile ("/*LOAD GCROOT %%0*/"::"m"(gcroot%d));' % (index,))
+ def OP_ASM_GCROOT(self, op):
+ value = self.expr(op.args[0])
+ return 'PYPY_GCROOT(%s);' % (value,)
assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)
Modified: pypy/branch/asmgcroot/pypy/translator/c/gc.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/gc.py (original)
+++ pypy/branch/asmgcroot/pypy/translator/c/gc.py Wed Jan 2 17:52:49 2008
@@ -5,7 +5,7 @@
typeOf, Ptr, ContainerType, RttiStruct, \
RuntimeTypeInfo, getRuntimeTypeInfo, top_container
from pypy.rpython.memory.gctransform import \
- refcounting, boehm, framework, stacklessframework, llvmgcroot
+ refcounting, boehm, framework, stacklessframework, llvmgcroot, asmgcroot
from pypy.rpython.lltypesystem import lltype, llmemory
class BasicGcPolicy(object):
@@ -308,6 +308,9 @@
class LLVMGcRootFrameworkGcPolicy(FrameworkGcPolicy):
transformerclass = llvmgcroot.LLVMGcRootFrameworkGCTransformer
+class AsmGcRootFrameworkGcPolicy(FrameworkGcPolicy):
+ transformerclass = asmgcroot.AsmGcRootFrameworkGCTransformer
+
name_to_gcpolicy = {
'boehm': BoehmGcPolicy,
@@ -316,6 +319,7 @@
'framework': FrameworkGcPolicy,
'framework+stacklessgc': StacklessFrameworkGcPolicy,
'framework+llvmgcroot': LLVMGcRootFrameworkGcPolicy,
+ 'framework+asmgcroot': AsmGcRootFrameworkGcPolicy,
}
Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/genc.py (original)
+++ pypy/branch/asmgcroot/pypy/translator/c/genc.py Wed Jan 2 17:52:49 2008
@@ -95,6 +95,8 @@
name = "%s+stacklessgc" % (name,)
if self.config.translation.llvmgcroot:
name = "%s+llvmgcroot" % (name,)
+ if self.config.translation.asmgcroot:
+ name = "%s+asmgcroot" % (name,)
return gc.name_to_gcpolicy[name]
return self.gcpolicy
@@ -275,8 +277,8 @@
self.eci, compiler_exe = cc, profbased = profbased)
def compile(self):
- if self.config.translation.llvmgcroot:
- raise Exception("Dunno how to compile with --llvmgcroot. "
+ if self.config.translation.asmgcroot:
+ raise Exception("Dunno how to compile with --asmgcroot. "
"Just go to the %s directory and type 'make'."
% (self.targetdir,))
assert self.c_source_filename
@@ -318,6 +320,7 @@
compiler.compile_extra.append(self.config.translation.compilerflags)
if self.config.translation.linkerflags:
compiler.link_extra.append(self.config.translation.linkerflags)
+ assert not self.config.translation.llvmgcroot
cfiles = []
ofiles = []
for fn in compiler.cfilenames:
@@ -328,7 +331,7 @@
assert fn.dirpath().dirpath() == udir
name = '../' + fn.relto(udir)
cfiles.append(name)
- if self.config.translation.llvmgcroot:
+ if self.config.translation.asmgcroot:
ofiles.append(name[:-2] + '.s')
else:
ofiles.append(name[:-2] + '.o')
@@ -349,13 +352,13 @@
print >> f
write_list(cfiles, 'SOURCES =')
print >> f
- if self.config.translation.llvmgcroot:
+ if self.config.translation.asmgcroot:
write_list(ofiles, 'ASMFILES =')
print >> f, 'OBJECTS = $(ASMFILES) gcmaptable.s'
else:
write_list(ofiles, 'OBJECTS =')
print >> f
- if self.config.translation.llvmgcroot:
+ if self.config.translation.asmgcroot:
print >> f, 'TRACKGCROOT="%s"' % (os.path.join(autopath.this_dir,
'trackgcroot.py'),)
print >> f
Modified: pypy/branch/asmgcroot/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/src/mem.h (original)
+++ pypy/branch/asmgcroot/pypy/translator/c/src/mem.h Wed Jan 2 17:52:49 2008
@@ -12,6 +12,7 @@
extern char __gcmapend;
extern char* __gcmap_frame_address(void);
+#define PYPY_GCROOT(p) asm ("/* GCROOT %0 */" : "=g" (p) : "0" (p) : "memory")
#define OP_LLVM_GCMAPSTART(r) r = &__gcmapstart
#define OP_LLVM_GCMAPEND(r) r = &__gcmapend
#define OP_LLVM_FRAMEADDRESS(r) asm ("pypygetframeaddress %0" : "=r" (r))
Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py (original)
+++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py Wed Jan 2 17:52:49 2008
@@ -27,7 +27,7 @@
class GcRootTracker(object):
- def __init__(self, verbose=False):
+ def __init__(self, verbose=0):
self.gcmaptable = []
self.verbose = verbose
@@ -85,10 +85,10 @@
if self.verbose:
print >> sys.stderr, '[trackgcroot:%s] %s' % (filename,
tracker.funcname)
- table = tracker.computegcmaptable()
- #if self.verbose:
- # for label, state in table:
- # print >> sys.stderr, label, '\t', state
+ table = tracker.computegcmaptable(self.verbose)
+ if self.verbose > 1:
+ for label, state in table:
+ print >> sys.stderr, label, '\t', state
if tracker.can_use_frame_pointer:
# XXX for now we have no logic to track the gc roots of
# functions using %ebp
@@ -98,7 +98,7 @@
if tracker.funcname == entrypoint:
table = [(label, (-1,)) for label, _ in table]
# ^^^ we set the framesize of the entry point to -1 as a marker
- # (the code in llvmgcroot.py actually takes any odd-valued number
+ # (the code in asmgcroot.py actually takes any odd-valued number
# as marker.)
self.gcmaptable.extend(table)
newfile.writelines(tracker.lines)
@@ -116,28 +116,45 @@
self.inconsistent_state = {}
self.can_use_frame_pointer = False # unless changed by caller
- def computegcmaptable(self):
+ def computegcmaptable(self, verbose=0):
self.findlabels()
self.parse_instructions()
+ if not self.enumerate_call_insns():
+ return []
+ self.makeprevmap()
self.findframesize()
self.fixlocalvars()
self.trackgcroots()
- self.dump()
- xxx
- self.follow_control_flow()
- table = self.gettable()
self.extend_calls_with_labels()
- return table
+ if verbose > 2:
+ self.dump()
+ return self.gettable()
def gettable(self):
"Returns a list [(label_after_call, (framesize, gcroot0, gcroot1,..))]"
- table = self.calls.items()
- table.sort() # by line number
- table = [value for key, value in table]
+ table = []
+ for i, insn in self.enumerate_call_insns():
+ info = [self.framesize[i]]
+ # the first gcroots are always the ones corresponding to
+ # the callee-saved registers
+ for reg in CALLEE_SAVE_REGISTERS:
+ info.append(None)
+ for loc, tag in insn.gcroots.items():
+ if not isinstance(loc, int):
+ # a special representation for a register location,
+ # as an odd-valued number
+ loc = CALLEE_SAVE_REGISTERS.index(loc) * 2 + 1
+ if tag is None:
+ info.append(loc)
+ else:
+ regindex = CALLEE_SAVE_REGISTERS.index(tag)
+ info[1 + regindex] = loc
+ assert None not in info
+ table.append((insn.global_label, tuple(info)))
return table
def findlabels(self):
- self.labels = {}
+ self.labels = {} # {name: line number}
for i, line in enumerate(self.lines):
match = r_label.match(line)
if match:
@@ -145,52 +162,69 @@
assert label not in self.labels, "duplicate label"
self.labels[label] = i
- def extend_calls_with_labels(self):
- self.missing_labels_after_call.sort()
- self.missing_labels_after_call.reverse()
- for linenum, label in self.missing_labels_after_call:
- self.lines.insert(linenum, '%s:\n' % (label,))
- self.lines.insert(linenum, '\t.globl\t%s\n' % (label,))
-
def parse_instructions(self):
+ self.jumpsto = {} # {label: [list-of-source-node-indices]}
+ for label in self.labels:
+ self.jumpsto[label] = []
self.insns = [InsnFunctionStart()]
- self.linenum = 0
+ self.line2nodeindex = {0: 0}
in_APP = False
for lin in range(1, len(self.lines)):
- self.linenum = lin
- insn = no_op
+ self.currentlineno = lin
+ insn = []
line = self.lines[lin]
match = r_insn.match(line)
if match:
if not in_APP:
- insn = match.group(1)
- meth = getattr(self, 'visit_' + insn)
+ opname = match.group(1)
+ meth = getattr(self, 'visit_' + opname)
insn = meth(line)
elif r_gcroot_marker.match(line):
- insn = self.handle_gcroot_marker(line)
+ insn = self._visit_gcroot_marker(line)
elif line == '#APP\n':
in_APP = True
elif line == '#NO_APP\n':
in_APP = False
- self.insns.append(insn)
- del self.linenum
+ self.line2nodeindex.setdefault(lin, len(self.insns))
+ if isinstance(insn, list):
+ self.insns.extend(insn)
+ else:
+ self.insns.append(insn)
+ del self.currentlineno
+
+ def makeprevmap(self):
+ # builds the prevmap, which only accounts for jumps. Each insn node
+ # has an implicit previous node, which is (obviously) the previous
+ # one in self.insns -- unless the previous one is an InsnStop.
+ self.prevmap = {} # {node-index: [list-of-previous-node-indices]}
+ for label, sourceindices in self.jumpsto.items():
+ line = self.labels[label]
+ while line not in self.line2nodeindex:
+ assert line < len(self.lines), (
+ "no Insn found after label %r" % (label,))
+ line += 1
+ self.prevmap[self.line2nodeindex[line]] = sourceindices
+
+ def enumerate_call_insns(self):
+ return [(i, insn) for (i, insn) in enumerate(self.insns)
+ if isinstance(insn, InsnCall)]
def findframesize(self):
self.framesize = {0: 0}
- def walker(lin, insn, size_delta):
- check = deltas.setdefault(lin, size_delta)
+ def walker(i, insn, size_delta):
+ check = deltas.setdefault(i, size_delta)
assert check == size_delta, (
- "inconsistent frame size at function line %d" % (lin,))
+ "inconsistent frame size at instruction %d: %s" % (i, insn))
if isinstance(insn, InsnStackAdjust):
size_delta -= insn.delta
- if lin not in self.framesize:
+ if i not in self.framesize:
yield size_delta # continue walking backwards
- for lin, insn in enumerate(self.insns):
+ for i, insn in enumerate(self.insns):
if insn.requestgcroots():
deltas = {}
- self.walk_instructions_backwards(walker, lin, 0)
+ self.walk_instructions_backwards(walker, i, 0)
size_at_insn = []
for n in deltas:
if n in self.framesize:
@@ -202,32 +236,33 @@
size_at_n = size_at_insn - deltas[n]
check = self.framesize.setdefault(n, size_at_n)
assert check == size_at_n, (
- "inconsistent frame size at function line %d" % (n,))
+ "inconsistent frame size at instruction %d: %s" % (
+ n, self.insns[n]))
def fixlocalvars(self):
- for lin, insn in enumerate(self.insns):
- if lin in self.framesize:
+ for i, insn in enumerate(self.insns):
+ if i in self.framesize:
for name in insn._locals_:
localvar = getattr(insn, name)
match = r_localvar_esp.match(localvar)
if match:
ofs_from_esp = int(match.group(1) or '0')
- localvar = ofs_from_esp - self.framesize[lin]
+ localvar = ofs_from_esp - self.framesize[i]
assert localvar != 0 # that's the return address
setattr(insn, name, localvar)
def trackgcroots(self):
- def walker(lin, insn, loc):
+ def walker(i, insn, loc):
source = insn.source_of(loc, tag)
if isinstance(source, Value):
pass # done
else:
yield source
- for lin, insn in enumerate(self.insns):
+ for i, insn in enumerate(self.insns):
for loc, tag in insn.requestgcroots().items():
- self.walk_instructions_backwards(walker, lin, loc)
+ self.walk_instructions_backwards(walker, i, loc)
def dump(self):
for n, insn in enumerate(self.insns):
@@ -237,117 +272,72 @@
size = '?'
print '%4s %s' % (size, insn)
- def walk_instructions_backwards(self, walker, initial_line, initial_state):
+ def walk_instructions_backwards(self, walker, initial_i, initial_state):
pending = []
seen = {}
- def schedule(line, state):
- assert 0 <= line < len(self.insns)
- key = line, state
+ def schedule(i, state):
+ assert 0 <= i < len(self.insns)
+ key = i, state
if key not in seen:
seen[key] = True
pending.append(key)
- schedule(initial_line, initial_state)
+ schedule(initial_i, initial_state)
while pending:
- line, state = pending.pop()
- for prevstate in walker(line, self.insns[line], state):
- schedule(line - 1, prevstate)
-
- def follow_control_flow(self):
- # 'states' is a list [(framesize, gcroot0, gcroot1, gcroot2...)]
- self.states = [None] * len(self.lines)
- self.pending = []
- self.framesize = 0
- self.gcroots = {}
- self.propagate_state_to(1)
- while self.pending:
- lin = self.pending.pop()
- self.follow_basic_block(lin)
- self.check_all_calls_seen()
-
- def getstate(self):
- if self.gcroots is Bogus:
- gcroots = ()
- else:
- gcroots = self.gcroots.keys()
- gcroots.sort()
- return (self.framesize,) + tuple(gcroots)
-
- def propagate_state_to(self, lin):
- state = self.getstate()
- if self.states[lin] is None:
- self.states[lin] = state
- self.pending.append(lin)
- elif self.states[lin] != state:
- if lin not in self.inconsistent_state:
- self.inconsistent_state[lin] = (self.states[lin], state)
- raise ReflowCompletely
-
- def follow_basic_block(self, lin):
- state = self.states[lin]
- self.framesize = state[0]
- self.gcroots = dict.fromkeys(state[1:])
- if lin in self.inconsistent_state: # in case of inconsistent gcroots,
- self.framesize = Bogus # assume that we're about to leave
- if self.framesize is Bogus: # the function or fail an assert
- self.gcroots = Bogus
- line = '?'
- self.in_APP = False
- while 1:
- try:
- self.currentlinenum = lin
- line = self.lines[lin]
- match = r_insn.match(line)
- if match:
- insn = match.group(1)
- try:
- meth = self.VISIT_OPERATION[insn]
- except KeyError:
- meth = self.find_visitor(insn)
- meth(self, line)
- elif r_label.match(line):
- if not self.in_APP: # ignore labels inside #APP/#NO_APP
- self.propagate_state_to(lin+1)
- break
- elif r_gcroot_marker.match(line):
- self.handle_gcroot_marker(line)
- elif line == '#APP\n':
- self.in_APP = True
- elif line == '#NO_APP\n':
- self.in_APP = False
- lin += 1
- except LeaveBasicBlock:
- if self.in_APP: # ignore control flow inside #APP/#NO_APP
- lin += 1
- continue
- break
- except UnrecognizedOperation:
- if self.in_APP: # ignore strange ops inside #APP/#NO_APP
- lin += 1
- continue
- raise
- except ReflowCompletely:
- raise
- except Exception, e:
- print >> sys.stderr, '*'*60
- print >> sys.stderr, "%s while processing line:" % (
- e.__class__.__name__,)
- print >> sys.stderr, line
- raise
+ i, state = pending.pop()
+ for prevstate in walker(i, self.insns[i], state):
+ if not isinstance(self.insns[i - 1], InsnStop):
+ schedule(i - 1, prevstate)
+ if i in self.prevmap:
+ for previndex in self.prevmap[i]:
+ schedule(previndex, prevstate)
- def check_all_calls_seen(self):
- for i, line in enumerate(self.lines):
- match = r_insn.match(line)
+ def extend_calls_with_labels(self):
+ # walk backwards, because inserting the global labels in self.lines
+ # is going to invalidate the lineno of all the InsnCall objects
+ # after the current one.
+ for i, call in self.enumerate_call_insns()[::-1]:
+ self.create_global_label(call)
+
+ def create_global_label(self, call):
+ # we need a globally-declared label just after the call.
+ # Reuse one if it is already there (e.g. from a previous run of this
+ # script); otherwise invent a name and add the label to tracker.lines.
+ label = None
+ # this checks for a ".globl NAME" followed by "NAME:"
+ match = r_globl.match(self.lines[call.lineno+1])
+ if match:
+ label1 = match.group(1)
+ match = r_label.match(self.lines[call.lineno+2])
if match:
- insn = match.group(1)
- if insn == 'call':
- assert i in self.calls or i in self.ignore_calls, (
- "unreachable call!" + line)
+ label2 = match.group(1)
+ if label1 == label2:
+ label = label2
+ if label is None:
+ k = call.lineno
+ while 1:
+ label = '__gcmap_IN_%s_%d' % (self.funcname, k)
+ if label not in self.labels:
+ break
+ k += 1
+ self.labels[label] = call.lineno+1
+ self.lines.insert(call.lineno+1, '%s:\n' % (label,))
+ self.lines.insert(call.lineno+1, '\t.globl\t%s\n' % (label,))
+ call.global_label = label
+
+ # ____________________________________________________________
- def handle_gcroot_marker(self, line):
+ def _visit_gcroot_marker(self, line):
match = r_gcroot_marker.match(line)
loc = match.group(1)
return InsnGCROOT(loc)
+ def visit_nop(self, line):
+ return []
+
+ NOP_PREFIXES = dict.fromkeys(['cmp', 'test', 'set',
+ 'f', # floating-point operations
+ ])
+
def visit_addl(self, line, sign=+1):
match = r_binaryinsn.match(line)
target = match.group(2)
@@ -363,29 +353,63 @@
def visit_subl(self, line):
return self.visit_addl(line, sign=-1)
- def visit_movl(self, line):
+ def unary_insn(self, line):
+ match = r_unaryinsn.match(line)
+ target = match.group(1)
+ if r_localvar.match(target):
+ return InsnSetLocal(Value(), target)
+ else:
+ raise UnrecognizedOperation(line)
+
+ visit_incl = unary_insn
+
+ def binary_insn(self, line):
match = r_binaryinsn.match(line)
- source = match.group(1)
target = match.group(2)
if r_localvar.match(target):
+ return InsnSetLocal(Value(), target)
+ else:
+ raise UnrecognizedOperation(line)
+
+ visit_xorl = binary_insn
+ visit_movzbl = binary_insn
+ visit_leal = binary_insn
+ visit_imull = binary_insn
+
+ def insns_for_copy(self, source, target):
+ if r_localvar.match(target):
if r_localvar.match(source):
- return InsnCopyLocal(source, target)
+ return [InsnCopyLocal(source, target)]
else:
- return InsnSetLocal(Value(), target)
+ return [InsnSetLocal(Value(), target)]
elif target == '%esp':
raise UnrecognizedOperation
else:
- return no_op
+ return []
+
+ def visit_movl(self, line):
+ match = r_binaryinsn.match(line)
+ source = match.group(1)
+ target = match.group(2)
+ return self.insns_for_copy(source, target)
+
+ def visit_pushl(self, line):
+ match = r_unaryinsn.match(line)
+ source = match.group(1)
+ return [InsnStackAdjust(-4)] + self.insns_for_copy(source, '(%esp)')
+
+ def visit_popl(self, line):
+ match = r_unaryinsn.match(line)
+ target = match.group(1)
+ return self.insns_for_copy('(%esp)', target) + [InsnStackAdjust(+4)]
def visit_ret(self, line):
return InsnRet()
def visit_jmp(self, line):
- xxx
- if self.in_APP:
- return # ignore jumps inside a #APP/#NO_APP block
match = r_jmp_switch.match(line)
if match:
+ xxx
# this is a jmp *Label(%index), used for table-based switches.
# Assume that the table is just a list of lines looking like
# .long LABEL or .long 0, ending in a .text.
@@ -401,7 +425,7 @@
raise LeaveBasicBlock
if r_unaryinsn_star.match(line):
# that looks like an indirect tail-call.
- raise LeaveBasicBlock
+ return InsnStop()
try:
self.conditional_jump(line)
except KeyError:
@@ -409,16 +433,17 @@
match = r_unaryinsn.match(line)
target = match.group(1)
assert not target.startswith('.')
- raise LeaveBasicBlock
+ return InsnStop()
+
+ def register_jump_to(self, label):
+ currentpos = len(self.insns)
+ self.jumpsto[label].append(currentpos)
def conditional_jump(self, line):
- xxx
- if self.in_APP:
- return # ignore jumps inside a #APP/#NO_APP block
match = r_jump.match(line)
label = match.group(1)
- targetlin = self.labels[label]
- self.propagate_state_to(targetlin)
+ self.register_jump_to(label)
+ return []
visit_je = conditional_jump
visit_jne = conditional_jump
@@ -445,7 +470,7 @@
target = match.group(1)
if target in FUNCTIONS_NOT_RETURNING:
return InsnStop()
- return InsnCall()
+ return InsnCall(self.currentlineno)
def visit_pypygetframeaddress(self, line):
xxx
@@ -501,10 +526,6 @@
self.arguments[localvar] = Value()
return self.arguments[localvar]
-class NoOp(Insn):
- pass
-no_op = NoOp()
-
class InsnSetLocal(Insn):
_args_ = ['value', 'target']
_locals_ = ['target']
@@ -542,8 +563,8 @@
return dict(zip(CALLEE_SAVE_REGISTERS, CALLEE_SAVE_REGISTERS))
class InsnCall(Insn):
- _args_ = ['gcroots']
- def __init__(self):
+ _args_ = ['lineno', 'gcroots']
+ def __init__(self, lineno):
# 'gcroots' is a dict built by side-effect during the call to
# FunctionGcRootTracker.trackgcroots(). Its meaning is as follows:
# the keys are the location that contain gc roots (either register
@@ -565,6 +586,8 @@
# epilogue).
#
self.gcroots = {}
+ self.lineno = lineno
+
def source_of(self, localvar, tag):
self.gcroots[localvar] = tag
return localvar
@@ -587,7 +610,7 @@
if __name__ == '__main__':
- tracker = GcRootTracker(verbose=True)
+ tracker = GcRootTracker(verbose=sys.maxint)
for fn in sys.argv[1:]:
tmpfn = fn + '.TMP'
f = open(fn, 'r')
More information about the pypy-svn
mailing list