Bug 1696531: fix dmd.py and related tools to support python 3, r=bhearsum

Depends on D109729

Differential Revision: https://phabricator.services.mozilla.com/D109731
This commit is contained in:
Andrew Halberstadt 2021-06-14 15:31:42 +00:00
parent 3e6d6103de
commit 225e877c2b
4 changed files with 43 additions and 32 deletions

View File

@ -1,4 +1,4 @@
#! /usr/bin/env python
#! /usr/bin/env python3
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@ -11,6 +11,7 @@ from __future__ import absolute_import, print_function, division
import argparse
import collections
import gzip
import io
import json
import os
import platform
@ -19,6 +20,7 @@ import shutil
import sys
import tempfile
from bisect import bisect_right
from functools import cmp_to_key
# The DMD output version this script handles.
outputVersion = 5
@ -50,6 +52,10 @@ allocatorFns = [
]
def cmp(a, b):
return (a > b) - (a < b)
class Record(object):
"""A record is an aggregation of heap blocks that have identical stack
traces. It can also be used to represent the difference between two
@ -280,7 +286,7 @@ def fixStackTraces(inputFilename, isZipped, opener):
# get that now in order to move |tmpFile| at the end.
tmpFilename = tmpFile.name
if isZipped:
tmpFile = gzip.GzipFile(filename="", fileobj=tmpFile)
tmpFile = gzip.GzipFile(filename="", fileobj=tmpFile, mode="wb")
with opener(inputFilename, "rb") as inputFile:
for line in inputFile:
@ -355,7 +361,7 @@ def getDigestFromFile(args, inputFile):
# Trim the number of frames.
for traceKey, frameKeys in traceTable.items():
if len(frameKeys) > args.max_frames:
traceTable[traceKey] = frameKeys[: args.max_frames]
del frameKeys[args.max_frames :]
def buildTraceDescription(traceTable, frameTable, traceKey):
frameKeys = traceTable[traceKey]
@ -444,7 +450,7 @@ def getDigestFromFile(args, inputFile):
return recordKeyPartCache[traceKey]
recordKeyPart = str(
map(lambda frameKey: frameTable[frameKey], traceTable[traceKey])
list(map(lambda frameKey: frameTable[frameKey], traceTable[traceKey]))
)
recordKeyPartCache[traceKey] = recordKeyPart
return recordKeyPart
@ -500,7 +506,7 @@ def getDigestFromFile(args, inputFile):
def f(k):
return buildTraceDescription(traceTable, frameTable, k)
record.reportedAtDescs = map(f, reportedAtTraceKeys)
record.reportedAtDescs = list(map(f, reportedAtTraceKeys))
record.usableSizes[usableSize] += num
# All the processed data for a single DMD file is called a "digest".
@ -606,7 +612,9 @@ def printDigest(args, digest):
out(separator)
numRecords = len(records)
cmpRecords = sortByChoices[args.sort_by]
sortedRecords = sorted(records.values(), cmp=cmpRecords, reverse=True)
sortedRecords = sorted(
records.values(), key=cmp_to_key(cmpRecords), reverse=True
)
kindBlocks = 0
kindUsableSize = 0
maxRecord = 1000
@ -813,7 +821,7 @@ def prettyPrintDmdJson(out, j):
out.write(' "traceTable": {')
first = True
for k, l in j["traceTable"].iteritems():
for k, l in j["traceTable"].items():
out.write("" if first else ",")
out.write('\n "{0}": {1}'.format(k, json.dumps(l)))
first = False
@ -821,7 +829,7 @@ def prettyPrintDmdJson(out, j):
out.write(' "frameTable": {')
first = True
for k, v in j["frameTable"].iteritems():
for k, v in j["frameTable"].items():
out.write("" if first else ",")
out.write('\n "{0}": {1}'.format(k, json.dumps(v)))
first = False
@ -983,8 +991,8 @@ def clampBlockList(args, inputFileName, isZipped, opener):
tmpFile = tempfile.NamedTemporaryFile(delete=False)
tmpFilename = tmpFile.name
if isZipped:
tmpFile = gzip.GzipFile(filename="", fileobj=tmpFile)
prettyPrintDmdJson(tmpFile, j)
tmpFile = gzip.GzipFile(filename="", fileobj=tmpFile, mode="wb")
prettyPrintDmdJson(io.TextIOWrapper(tmpFile, encoding="utf-8"), j)
tmpFile.close()
shutil.move(tmpFilename, inputFileName)

View File

@ -54,17 +54,7 @@ Live {
}
Live {
0 blocks in heap block record 5 of 6
0 bytes (0 requested / 0 slop)
Individual block sizes: 20,480; -16,384; -8,192; 4,096
-0.00% of the heap (100.00% cumulative)
Allocated at {
#01: (no stack trace recorded due to --stacks=partial)
}
}
Live {
-2 blocks in heap block record 6 of 6
-2 blocks in heap block record 5 of 6
0 bytes (0 requested / 0 slop)
Individual block sizes: 8,192 x 2; -4,096 x 4
-0.00% of the heap (100.00% cumulative)
@ -73,6 +63,16 @@ Live {
}
}
Live {
0 blocks in heap block record 6 of 6
0 bytes (0 requested / 0 slop)
Individual block sizes: 20,480; -16,384; -8,192; 4,096
-0.00% of the heap (100.00% cumulative)
Allocated at {
#01: (no stack trace recorded due to --stacks=partial)
}
}
#-----------------------------------------------------------------
Summary {

View File

@ -664,7 +664,10 @@ class XPCShellTestThread(Thread):
def fix_text_output(self, line):
line = cleanup_encoding(line)
if self.stack_fixer_function is not None:
return self.stack_fixer_function(line)
line = self.stack_fixer_function(line)
if isinstance(line, bytes):
line = line.decode("utf-8")
return line
def log_line(self, line):

View File

@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python3
# vim:sw=4:ts=4:et:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@ -15,8 +15,6 @@ import platform
import re
import sys
import six
# Matches lines produced by MozFormatCodeAddress(), e.g.
# `#01: ???[tests/example +0x43a0]`.
line_re = re.compile("#\d+: .+\[.+ \+0x[0-9A-Fa-f]+\]")
@ -75,10 +73,9 @@ def initFixStacks(jsonMode, slowWarning, breakpadSymsDir, hide_errors):
def fixSymbols(
line, jsonMode=False, slowWarning=False, breakpadSymsDir=None, hide_errors=False
):
line = six.ensure_str(line)
result = line_re.search(line)
if result is None:
is_bytes = isinstance(line, bytes)
line_str = line.decode("utf-8") if is_bytes else line
if line_re.search(line_str) is None:
return line
if not fix_stacks:
@ -88,14 +85,17 @@ def fixSymbols(
# to `fix-stacks` it will wait until it receives a newline, causing this
# script to hang. So we add a newline if one is missing and then remove it
# from the output.
is_missing_newline = not line.endswith("\n")
is_missing_newline = not line_str.endswith("\n")
if is_missing_newline:
line = line + "\n"
fix_stacks.stdin.write(line)
line_str = line_str + "\n"
fix_stacks.stdin.write(line_str)
fix_stacks.stdin.flush()
out = fix_stacks.stdout.readline()
if is_missing_newline:
out = out[:-1]
if is_bytes and not isinstance(out, bytes):
out = out.encode("utf-8")
return out