1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/trace-malloc/uncategorized.pl Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,117 @@ 1.4 +#!/usr/bin/perl -w 1.5 +# 1.6 +# This Source Code Form is subject to the terms of the Mozilla Public 1.7 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.9 + 1.10 +# This tool is used to construct the ``type inference'' file. It 1.11 +# prints the total number of bytes that are attributed to a type that 1.12 +# cannot be inferred, grouped by stack trace; e.g., 1.13 +# 1.14 +# (100) PR_Malloc 1.15 +# (50) foo 1.16 +# (50) foo2::foo2 1.17 +# (25) bar 1.18 +# (25) baz 1.19 +# (50) __builtin_new 1.20 +# (50) foo2::foo2 1.21 +# 1.22 +# 1.23 +# Which indicates that 100 bytes were allocated by uninferrable 1.24 +# classes via PR_Malloc(). Of that 100 bytes, 50 were allocated from 1.25 +# calls by foo(), 25 from calls by bar(), and 25 from calls by baz(). 1.26 +# 50 bytes were allocated by __builtin_new from foo2's ctor. 1.27 +# 1.28 +# 1.29 +# From this, we might be able to infer the type of the object that was 1.30 +# created by examining the PR_Malloc() usage in foo() and the 1.31 +# ::operator new() usage in foo2(), and could add new type inference 1.32 +# rules; e.g., 1.33 +# 1.34 +# <unclassified-string> 1.35 +# foo 1.36 +# foo2 1.37 +# 1.38 +# # Attribute ::operator new() usage in foo2's ctor to foo2 1.39 +# <foo2> 1.40 +# __builtin_new 1.41 +# foo2::foo2 1.42 + 1.43 +use 5.004; 1.44 +use strict; 1.45 +use Getopt::Long; 1.46 + 1.47 +# So we can find TraceMalloc.pm 1.48 +use FindBin; 1.49 +use lib "$FindBin::Bin"; 1.50 + 1.51 +use TraceMalloc; 1.52 + 1.53 +# Collect program options 1.54 +$::opt_help = 0; 1.55 +$::opt_depth = 10; 1.56 +$::opt_types = "${FindBin::Bin}/types.dat"; 1.57 +GetOptions("help", "depth=n", "types=s"); 1.58 + 1.59 +if ($::opt_help) { 1.60 + die "usage: uncategorized.pl [options] <dumpfile> 1.61 + --help Display this message 1.62 + --depth=<n> Display at most <n> stack frames 1.63 + --types=<file> Read type heuristics from <file>"; 1.64 +} 1.65 + 1.66 +# Initialize type inference juju from the type file specified by 1.67 +# ``--types''. 1.68 +TraceMalloc::init_type_inference($::opt_types); 1.69 + 1.70 +# Read the objects from the dump file. For each object, remember up to 1.71 +# ``--depth'' stack frames (from the top). Thread together common 1.72 +# stack prefixes, accumulating the number of bytes attributed to the 1.73 +# prefix. 1.74 + 1.75 +# This'll hold the inverted stacks 1.76 +$::Stacks = { '#bytes#' => 0 }; 1.77 + 1.78 +sub collect_stacks($) { 1.79 + my ($object) = @_; 1.80 + my $stack = $object->{'stack'}; 1.81 + 1.82 + return unless ($object->{'type'} eq 'void*') && (TraceMalloc::infer_type($stack) eq 'void*'); 1.83 + 1.84 + my $count = 0; 1.85 + my $link = \%::Stacks; 1.86 + FRAME: foreach my $frame (@$stack) { 1.87 + last FRAME unless $count++ < $::opt_depth; 1.88 + 1.89 + $link->{'#bytes#'} += $object->{'size'}; 1.90 + $link->{$frame} = { '#bytes#' => 0 } unless $link->{$frame}; 1.91 + $link = $link->{$frame}; 1.92 + } 1.93 +} 1.94 + 1.95 +TraceMalloc::read(\&collect_stacks); 1.96 + 1.97 +# Do a depth-first walk of the inverted stack tree. 1.98 + 1.99 +sub walk($$) { 1.100 + my ($links, $indent) = @_; 1.101 + 1.102 + my @keys; 1.103 + KEY: foreach my $key (keys %$links) { 1.104 + next KEY if $key eq '#bytes#'; 1.105 + $keys[$#keys + 1] = $key; 1.106 + } 1.107 + 1.108 + foreach my $key (sort { $links->{$b}->{'#bytes#'} <=> $links->{$a}->{'#bytes#'} } @keys) { 1.109 + for (my $i = 0; $i < $indent; ++$i) { 1.110 + print " "; 1.111 + } 1.112 + 1.113 + print "($links->{$key}->{'#bytes#'}) $key\n"; 1.114 + 1.115 + walk($links->{$key}, $indent + 1); 1.116 + } 1.117 +} 1.118 + 1.119 +walk(\%::Stacks, 0); 1.120 +