summaryrefslogtreecommitdiffstats
path: root/devtools/shared/heapsnapshot/CoreDump.proto
blob: 4d0bf27f013ab5556e1a72f2e77de6591abc0b63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* -*- Mode: protobuf; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * 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
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// # Core Dumps
//
// A core dump is a serialized snapshot of the heap graph. We serialize the heap
// as a series of protobuf messages with each message prefixed by its Varint32
// byte size so we can delimit individual protobuf messages (protobuf parsers
// cannot determine where a message ends on their own).
//
// The first protobuf message is an instance of the `Metadata` message. All
// subsequent messages will be instances of the `Node` message. The first of
// these `Node` messages is the root node of the serialized heap graph. Here is
// a diagram of our core dump format:
//
//     +-----------------------------------------------------------------------+
//     | Varint32: The size of following `Metadata` message.                   |
//     +-----------------------------------------------------------------------+
//     | message: The core dump `Metadata` message.                            |
//     +-----------------------------------------------------------------------+
//     | Varint32: The size of the following `Node` message.                   |
//     +-----------------------------------------------------------------------+
//     | message: The first `Node` message. This is the root node.             |
//     +-----------------------------------------------------------------------+
//     | Varint32: The size of the following `Node` message.                   |
//     +-----------------------------------------------------------------------+
//     | message: A `Node` message.                                            |
//     +-----------------------------------------------------------------------+
//     | Varint32: The size of the following `Node` message.                   |
//     +-----------------------------------------------------------------------+
//     | message: A `Node` message.                                            |
//     +-----------------------------------------------------------------------+
//     | .                                                                     |
//     | .                                                                     |
//     | .                                                                     |
//     +-----------------------------------------------------------------------+
//
// Core dumps should always be written with a
// `google::protobuf::io::GzipOutputStream` and read from a
// `google::protobuf::io::GzipInputStream`.
//
// Note that all strings are de-duplicated. The first time the N^th unique
// string is encountered, the full string is serialized. Subsequent times that
// same string is encountered, it is referenced by N. This de-duplication
// happens across string properties, not on a per-property basis. For example,
// if the same K^th unique string is first used as an Edge::EdgeNameOrRef and
// then as a StackFrame::Data::FunctionDisplayNameOrRef, the first will be the
// actual string as the functionDisplayName oneof property, and the second will
// be a reference to the first as the edgeNameRef oneof property whose value is
// K.
//
// We would ordinarily abstract these de-duplicated strings with messages of
// their own, but unfortunately, the protobuf compiler does not have a way to
// inline a messsage within another message and the child message must be
// referenced by pointer. This leads to extra mallocs that we wish to avoid.

syntax = "proto2";

option optimize_for = LITE_RUNTIME;

package mozilla.devtools.protobuf;

// A collection of metadata about this core dump.
message Metadata {
    // Number of microseconds since midnight (00:00:00) 1 January 1970 UTC.
    optional uint64 timeStamp = 1;
}

// A serialized version of `JS::ubi::StackFrame`. Older parent frame tails are
// de-duplicated to cut down on [de]serialization and size costs.
message StackFrame {
    oneof StackFrameType {
        // This is the first time this stack frame has been serialized, and so
        // here is all of its data.
        Data   data = 1;
        // A reference to a stack frame that has already been serialized and has
        // the given number as its id.
        uint64 ref  = 2;
    }

    message Data {
        optional uint64        id           = 1;
        optional StackFrame    parent       = 2;
        optional uint32        line         = 3;
        optional uint32        column       = 4;

        // De-duplicated two-byte string.
        oneof SourceOrRef {
            bytes  source                   = 5;
            uint64 sourceRef                = 6;
        }

        // De-duplicated two-byte string.
        oneof FunctionDisplayNameOrRef {
            bytes  functionDisplayName      = 7;
            uint64 functionDisplayNameRef   = 8;
        }

        optional bool          isSystem     = 9;
        optional bool          isSelfHosted = 10;
    }
}

// A serialized version of `JS::ubi::Node` and its outgoing edges.
message Node {
    optional uint64     id                     = 1;

    // De-duplicated two-byte string.
    oneof TypeNameOrRef {
        bytes           typeName               = 2;
        uint64          typeNameRef            = 3;
    }

    optional uint64     size                   = 4;
    repeated Edge       edges                  = 5;
    optional StackFrame allocationStack        = 6;

    // De-duplicated one-byte string.
    oneof JSObjectClassNameOrRef {
        bytes           jsObjectClassName      = 7;
        uint64          jsObjectClassNameRef   = 8;
    }

    // JS::ubi::CoarseType. Defaults to Other.
    optional uint32     coarseType             = 9 [default = 0];

    // De-duplicated one-byte string.
    oneof ScriptFilenameOrRef {
        bytes           scriptFilename         = 10;
        uint64          scriptFilenameRef      = 11;
    }

    // De-duplicated one-byte string.
    oneof descriptiveTypeNameOrRef {
        bytes           descriptiveTypeName    = 12;
        uint64          descriptiveTypeNameRef = 13;
    }
}

// A serialized edge from the heap graph.
message Edge {
    optional uint64 referent    = 1;

    // De-duplicated two-byte string.
    oneof EdgeNameOrRef {
        bytes       name    = 2;
        uint64      nameRef = 3;
    }
}