def collectDB(self, liveCode): self.allReads = set() self.allModifies = set() self.opReadDB = opDataflowSchema.instance() self.opModifyDB = opDataflowSchema.instance() self.allocations = collections.defaultdict(set) # Copy modifies for code in liveCode: self.handleModifies(code, None, code.annotation.codeModifies) ops, lcls = getOps(code) for op in ops: self.handleModifies(code, op, op.annotation.opModifies) # Copy reads for code in liveCode: self.handleReads(code, None, code.annotation.codeReads) self.handleAllocates(code, None, code.annotation.codeAllocates) ops, lcls = getOps(code) for op in ops: self.handleReads(code, op, op.annotation.opReads) self.handleAllocates(code, op, op.annotation.opAllocates)
def annotate(self): if self.clone: cloner = codecloner.FunctionCloner(self.codeContexts.iterkeys()) # Translate the live code self.liveCode = set([cloner.code(code) for code in self.liveCode]) else: cloner = codecloner.NullCloner(self.codeContexts.iterkeys()) self.annotationCount = 0 self.annotationCache = {} self.reindexAnnotations(cloner) self.annotateEntryPoints(cloner) for code, contexts in self.codeContexts.iteritems(): if code is self.externalFunction: continue cloner.process(code) contexts = self.annotateCode(code, contexts, cloner) ops, lcls = getOps(code) self.annotateOps(code, contexts, ops, cloner) self.annotateLocals(code, contexts, lcls, cloner) self.mergeAbstractCode(code, cloner) self.console.output("Annotation compression %f - %d" % (float(len(self.annotationCache))/max(self.annotationCount, 1), self.annotationCount)) del self.annotationCache del self.annotationCount
def process(self): # TODO get all fields from heap? # Local references for code in self.liveCode: self.liveObjs[code] = set() self.liveFields[code] = set() ops, lcls = getOps(code) for op in ops: self.liveFields[code].update(op.annotation.reads[0]) self.liveFields[code].update(op.annotation.modifies[0]) if not op.annotation.invokes[0]: # If the op does not invoke, it does real work. self.merge(op.annotation.reads[0]) self.merge(op.annotation.modifies[0]) # TODO seperate by concrete field type before merge for cobj in op.annotation.allocates[0]: if not cobj.leaks: self.liveObjs[code].add(cobj) for lcl in lcls: for ref in lcl.annotation.references[0]: if not ref.leaks: self.liveObjs[code].add(ref)
def children(self, node): code, context = node self.liveFunc.add(code) if code not in self.liveFuncContext: self.liveFuncContext[code] = set() self.liveFuncContext[code].add(context) if code not in self.invokes: self.invokes[code] = set() if node not in self.invokesContext: self.invokesContext[node] = set() cindex = code.annotation.contexts.index(context) children = [] ops, _lcls = getOps(code) for op in ops: assert hasattr(op.annotation, "invokes"), op invokes = op.annotation.invokes if invokes is not None: cinvokes = invokes[1][cindex] for dstf, dstc in cinvokes: child = (dstf, dstc) self.invokes[code].add(dstf) self.invokesContext[node].add(child) children.append(child) return children
def children(self, node): code, context = node self.liveFunc.add(code) if code not in self.liveFuncContext: self.liveFuncContext[code] = set() self.liveFuncContext[code].add(context) if code not in self.invokes: self.invokes[code] = set() if node not in self.invokesContext: self.invokesContext[node] = set() cindex = code.annotation.contexts.index(context) children = [] ops, _lcls = getOps(code) for op in ops: assert hasattr(op.annotation, 'invokes'), op invokes = op.annotation.invokes if invokes is not None: cinvokes = invokes[1][cindex] for dstf, dstc in cinvokes: child = (dstf, dstc) self.invokes[code].add(dstf) self.invokesContext[node].add(child) children.append(child) return children
def gatherSlots(self, liveCode, entryContexts): searcher = ObjectSearcher(self) for code in liveCode: callee = code.codeParameters() ops, lcls = getOps(code) for lcl in lcls: for ref in lcl.annotation.references[0]: searcher.enqueue(ref) # Mark the return parameters for external contexts as visible. for cindex, context in enumerate(code.annotation.contexts): if context in entryContexts: for param in callee.returnparams: self.markVisible(param, cindex) searcher.process()
def process(self, node): if node not in self.processed: assert node.isCode(), type(node) self.processed.add(node) self.trace.add(node) self.modified = False self.code = node if node.isStandardCode(): result = self(node.ast) if self.modified: node.ast = result # Always done immediately after inlining, so if we inline # this function, less needs to be processed. optimization.simplify.evaluateCode(self.compiler, self.prgm, node) else: ops, lcls = getOps(node) for op in ops: self.processInvocations(op) self.code = None self.trace.remove(node)
def annotate(self): if self.clone: cloner = codecloner.FunctionCloner(self.codeContexts.iterkeys()) # Translate the live code self.liveCode = set([cloner.code(code) for code in self.liveCode]) else: cloner = codecloner.NullCloner(self.codeContexts.iterkeys()) self.annotationCount = 0 self.annotationCache = {} self.reindexAnnotations(cloner) self.annotateEntryPoints(cloner) for code, contexts in self.codeContexts.iteritems(): if code is self.externalFunction: continue cloner.process(code) contexts = self.annotateCode(code, contexts, cloner) ops, lcls = getOps(code) self.annotateOps(code, contexts, ops, cloner) self.annotateLocals(code, contexts, lcls, cloner) self.mergeAbstractCode(code, cloner) self.console.output( "Annotation compression %f - %d" % (float(len(self.annotationCache)) / max(self.annotationCount, 1), self.annotationCount)) del self.annotationCache del self.annotationCount
def gatherInvokes(self, liveCode, entryContexts): invokesDB = invokesSchema.instance() self.entries = set() for code in liveCode: for context in code.annotation.contexts: if context in entryContexts: self.entries.add((code, context)) assert code.isCode(), type(code) ops, lcls = getOps(code) for op in ops: invokes = op.annotation.invokes if invokes is not None: for cindex, context in enumerate(code.annotation.contexts): opInvokes = invokes[1][cindex] for dstF, dstC in opInvokes: assert dstF.isCode(), type(dstF) invokesDB[code][op][context].add(dstF, dstC) for lcl in lcls: refs = lcl.annotation.references if refs is None: continue for cindex, context in enumerate(code.annotation.contexts): for ref in refs[1][cindex]: obj = self.getObjectInfo(ref) obj.localReference.add(code) self.codeRefersToHeap[(code, context)].add(ref) self.invokes = invokesDB self.invokeSources = invertInvokes(invokesDB)
def createDB(self, compiler, prgm): self.annotationCount = 0 self.annotationCache = {} readDB = self.rm.opReadDB modifyDB = self.rm.opModifyDB self.allocations = self.rm.allocations for code in prgm.liveCode: # Annotate the code live = [] killed = [] for cindex, context in enumerate(code.annotation.contexts): key = (code, context) live.append(annotations.annotationSet(self.live[key])) killed.append(annotations.annotationSet(self.contextKilled[key])) code.rewriteAnnotation( live=annotations.makeContextualAnnotation(live), killed=annotations.makeContextualAnnotation(killed) ) # Annotate the ops ops, lcls = getOps(code) for op in ops: # TODO is this a good HACK? # if not op.annotation.invokes[0]: continue reads = readDB[code][op] modifies = modifyDB[code][op] rout = [] mout = [] aout = [] for cindex, context in enumerate(code.annotation.contexts): # HACK if an operation directly reads a field, but it is never modified # it still must appear in the reads annotation so cloning behaves correctly! reads.merge(context, op.annotation.opReads[1][cindex]) creads = reads[context] creads = annotations.annotationSet(creads) if creads else () rout.append(creads) cmod = modifies[context] cmod = annotations.annotationSet(cmod) if cmod else () mout.append(cmod) kills = self.killed[(code, op, context)] calloc = set() for dstCode, dstContext in op.annotation.invokes[1][cindex]: live = self.live[(dstCode, dstContext)] killed = kills[(dstCode, dstContext)] calloc.update(live - killed) calloc.update(op.annotation.opAllocates[1][cindex]) aout.append(annotations.annotationSet(calloc)) opReads = annotations.makeContextualAnnotation(rout) opModifies = annotations.makeContextualAnnotation(mout) opAllocates = annotations.makeContextualAnnotation(aout) opReads = self.annotationCache.setdefault(opReads, opReads) opModifies = self.annotationCache.setdefault(opModifies, opModifies) opAllocates = self.annotationCache.setdefault(opAllocates, opAllocates) self.annotationCount += 3 op.rewriteAnnotation(reads=opReads, modifies=opModifies, allocates=opAllocates) compiler.console.output( "Annotation compression %f - %d" % (float(len(self.annotationCache)) / max(self.annotationCount, 1), self.annotationCount) ) del self.annotationCache del self.annotationCount
def createDB(self, compiler, prgm): self.annotationCount = 0 self.annotationCache = {} readDB = self.rm.opReadDB modifyDB = self.rm.opModifyDB self.allocations = self.rm.allocations for code in prgm.liveCode: # Annotate the code live = [] killed = [] for cindex, context in enumerate(code.annotation.contexts): key = (code, context) live.append(annotations.annotationSet(self.live[key])) killed.append( annotations.annotationSet(self.contextKilled[key])) code.rewriteAnnotation( live=annotations.makeContextualAnnotation(live), killed=annotations.makeContextualAnnotation(killed)) # Annotate the ops ops, lcls = getOps(code) for op in ops: # TODO is this a good HACK? # if not op.annotation.invokes[0]: continue reads = readDB[code][op] modifies = modifyDB[code][op] rout = [] mout = [] aout = [] for cindex, context in enumerate(code.annotation.contexts): # HACK if an operation directly reads a field, but it is never modified # it still must appear in the reads annotation so cloning behaves correctly! reads.merge(context, op.annotation.opReads[1][cindex]) creads = reads[context] creads = annotations.annotationSet(creads) if creads else ( ) rout.append(creads) cmod = modifies[context] cmod = annotations.annotationSet(cmod) if cmod else () mout.append(cmod) kills = self.killed[(code, op, context)] calloc = set() for dstCode, dstContext in op.annotation.invokes[1][ cindex]: live = self.live[(dstCode, dstContext)] killed = kills[(dstCode, dstContext)] calloc.update(live - killed) calloc.update(op.annotation.opAllocates[1][cindex]) aout.append(annotations.annotationSet(calloc)) opReads = annotations.makeContextualAnnotation(rout) opModifies = annotations.makeContextualAnnotation(mout) opAllocates = annotations.makeContextualAnnotation(aout) opReads = self.annotationCache.setdefault(opReads, opReads) opModifies = self.annotationCache.setdefault( opModifies, opModifies) opAllocates = self.annotationCache.setdefault( opAllocates, opAllocates) self.annotationCount += 3 op.rewriteAnnotation(reads=opReads, modifies=opModifies, allocates=opAllocates) compiler.console.output( "Annotation compression %f - %d" % (float(len(self.annotationCache)) / max(self.annotationCount, 1), self.annotationCount)) del self.annotationCache del self.annotationCount