Commit 4be85061 authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[Py3] Get blink_gc_plugin Py3 ready

Tested with:

python build.py --without-android --without-fuchsia \
  --run-tests --skip-checkout

With python == python3.7 (inside a pipenv).

- get maxint from sys.maxsize from Py3 (sys.maxint is removed)
- use StringIO from io
- use .values() instead of .itervalues()
- tweak lambda used in sort (became syntax error in Py3)
- check_output with universal newlines, will open stream as text

Bug: chromium:941669
Change-Id: I80ca9ae6d2f6d712c6e3cac5343627512ce84b86
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2261715Reviewed-by: default avatarAnton Bikineev <bikineev@chromium.org>
Reviewed-by: default avatarNico Weber <thakis@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#782053}
parent a2585c74
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# found in the LICENSE file. # found in the LICENSE file.
from __future__ import print_function from __future__ import print_function
import argparse, os, sys, json, subprocess, pickle, StringIO import argparse, io, os, sys, json, subprocess, pickle
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description = description =
...@@ -57,6 +57,14 @@ ignored_cycles = [] ...@@ -57,6 +57,14 @@ ignored_cycles = []
# Global flag to determine exit code. # Global flag to determine exit code.
global_reported_error = False global_reported_error = False
try:
# Python3 remove sys.maxint.
maxint = sys.maxint
except AttributeError:
# Also see https://stackoverflow.com/a/13795777/4052492.
maxint = sys.maxsize
def set_reported_error(value): def set_reported_error(value):
global global_reported_error global global_reported_error
global_reported_error = value global_reported_error = value
...@@ -109,18 +117,20 @@ class Node: ...@@ -109,18 +117,20 @@ class Node:
else: else:
self.edges[new_edge.key] = new_edge self.edges[new_edge.key] = new_edge
def super_edges(self): def super_edges(self):
return [ e for e in self.edges.itervalues() if e.is_super() ] return [e for e in self.edges.values() if e.is_super()]
def subclass_edges(self): def subclass_edges(self):
return [ e for e in self.edges.itervalues() if e.is_subclass() ] return [e for e in self.edges.values() if e.is_subclass()]
def reset(self): def reset(self):
self.cost = sys.maxint self.cost = maxint
self.visited = False self.visited = False
self.path = None self.path = None
self.counts = {} self.counts = {}
for ptr in ptr_types: for ptr in ptr_types:
self.counts[ptr] = 0 self.counts[ptr] = 0
def update_counts(self): def update_counts(self):
for e in self.edges.itervalues(): for e in self.edges.values():
inc_ptr(e.dst, e.ptr) inc_ptr(e.dst, e.ptr)
# Representation of directed graph edges. # Representation of directed graph edges.
...@@ -199,7 +209,7 @@ def copy_super_edges(edge): ...@@ -199,7 +209,7 @@ def copy_super_edges(edge):
copy_super_edges(e) copy_super_edges(e)
# Copy strong super-class edges (ignoring sub-class edges) to the sub class. # Copy strong super-class edges (ignoring sub-class edges) to the sub class.
sub_node = graph[edge.src] sub_node = graph[edge.src]
for e in super_node.edges.itervalues(): for e in super_node.edges.values():
if e.keeps_alive() and not e.is_subclass(): if e.keeps_alive() and not e.is_subclass():
new_edge = Edge( new_edge = Edge(
src = sub_node.name, src = sub_node.name,
...@@ -222,16 +232,16 @@ def copy_super_edges(edge): ...@@ -222,16 +232,16 @@ def copy_super_edges(edge):
super_node.edges[sub_edge.key] = sub_edge super_node.edges[sub_edge.key] = sub_edge
def complete_graph(): def complete_graph():
for node in graph.itervalues(): for node in graph.values():
for edge in node.super_edges(): for edge in node.super_edges():
copy_super_edges(edge) copy_super_edges(edge)
for edge in node.edges.itervalues(): for edge in node.edges.values():
if edge.is_root(): if edge.is_root():
roots.append(edge) roots.append(edge)
log("Copied edges down <super> edges for %d graph nodes" % global_inc_copy) log("Copied edges down <super> edges for %d graph nodes" % global_inc_copy)
def reset_graph(): def reset_graph():
for n in graph.itervalues(): for n in graph.values():
n.reset() n.reset()
def shortest_path(start, end): def shortest_path(start, end):
...@@ -243,7 +253,7 @@ def shortest_path(start, end): ...@@ -243,7 +253,7 @@ def shortest_path(start, end):
current.visited = True current.visited = True
if current == end or current.cost >= end.cost + 1: if current == end or current.cost >= end.cost + 1:
return return
for e in current.edges.itervalues(): for e in current.edges.values():
if not e.keeps_alive(): if not e.keeps_alive():
continue continue
dst = graph.get(e.dst) dst = graph.get(e.dst)
...@@ -276,7 +286,7 @@ def detect_cycles(): ...@@ -276,7 +286,7 @@ def detect_cycles():
continue continue
# Find the shortest path from the root target (dst) to its host (src) # Find the shortest path from the root target (dst) to its host (src)
shortest_path(dst, src) shortest_path(dst, src)
if src.cost < sys.maxint: if src.cost < maxint:
report_cycle(root_edge) report_cycle(root_edge)
def is_ignored_cycle(cycle): def is_ignored_cycle(cycle):
...@@ -307,7 +317,7 @@ def report_cycle(root_edge): ...@@ -307,7 +317,7 @@ def report_cycle(root_edge):
for p in path: for p in path:
if len(p.loc) > max_loc: if len(p.loc) > max_loc:
max_loc = len(p.loc) max_loc = len(p.loc)
out = StringIO.StringIO() out = io.StringIO()
for p in path[:-1]: for p in path[:-1]:
print((p.loc + ':').ljust(max_loc + 1), p, file=out) print((p.loc + ':').ljust(max_loc + 1), p, file=out)
sout = out.getvalue() sout = out.getvalue()
...@@ -370,7 +380,7 @@ def print_stats(): ...@@ -370,7 +380,7 @@ def print_stats():
gc_managed = [] gc_managed = []
hierarchies = [] hierarchies = []
for node in graph.itervalues(): for node in graph.values():
node.update_counts() node.update_counts()
for sup in node.super_edges(): for sup in node.super_edges():
if sup.dst in gcref_bases: if sup.dst in gcref_bases:
...@@ -395,7 +405,7 @@ def print_stats(): ...@@ -395,7 +405,7 @@ def print_stats():
hierarchies.append((base, stats)) hierarchies.append((base, stats))
print("\nHierarchies in transition (RefCountedGarbageCollected):") print("\nHierarchies in transition (RefCountedGarbageCollected):")
hierarchies.sort(key=lambda (n,s): -s['classes']) hierarchies.sort(key=lambda n: -n[1]['classes'])
for (node, stats) in hierarchies: for (node, stats) in hierarchies:
total = stats['mem'] + stats['ref'] + stats['raw'] total = stats['mem'] + stats['ref'] + stats['raw']
print( print(
......
...@@ -26,11 +26,13 @@ class BlinkGcPluginTest(plugin_testing.ClangPluginTest): ...@@ -26,11 +26,13 @@ class BlinkGcPluginTest(plugin_testing.ClangPluginTest):
# use the processed results as the actual results of the test. # use the processed results as the actual results of the test.
if os.path.exists('%s.graph.json' % test_name): if os.path.exists('%s.graph.json' % test_name):
try: try:
actual = subprocess.check_output( actual = subprocess.check_output([
['python', '../process-graph.py', '-c', 'python', '../process-graph.py', '-c',
'%s.graph.json' % test_name], '%s.graph.json' % test_name
stderr=subprocess.STDOUT) ],
except subprocess.CalledProcessError, e: stderr=subprocess.STDOUT,
universal_newlines=True)
except subprocess.CalledProcessError as e:
# The graph processing script returns a failure exit code if the graph # The graph processing script returns a failure exit code if the graph
# is bad (e.g. it has a cycle). The output still needs to be captured in # is bad (e.g. it has a cycle). The output still needs to be captured in
# that case, since the expected results capture the errors. # that case, since the expected results capture the errors.
......
...@@ -63,7 +63,7 @@ class ClangPluginTest(object): ...@@ -63,7 +63,7 @@ class ClangPluginTest(object):
cmd = clang_cmd[:] cmd = clang_cmd[:]
try: try:
# Some tests need to run with extra flags. # Some tests need to run with extra flags.
cmd.extend(file('%s.flags' % test_name).read().split()) cmd.extend(open('%s.flags' % test_name).read().split())
except IOError: except IOError:
pass pass
cmd.append(test) cmd.append(test)
...@@ -85,7 +85,9 @@ class ClangPluginTest(object): ...@@ -85,7 +85,9 @@ class ClangPluginTest(object):
def RunOneTest(self, test_name, cmd): def RunOneTest(self, test_name, cmd):
try: try:
actual = subprocess.check_output(cmd, stderr=subprocess.STDOUT) actual = subprocess.check_output(cmd,
stderr=subprocess.STDOUT,
universal_newlines=True)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
# Some plugin tests intentionally trigger compile errors, so just ignore # Some plugin tests intentionally trigger compile errors, so just ignore
# an exit code that indicates failure. # an exit code that indicates failure.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment