Coverage Report

Created: 2025-11-09 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsonnet/core/state.h
Line
Count
Source
1
/*
2
Copyright 2015 Google Inc. All rights reserved.
3
4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7
8
    http://www.apache.org/licenses/LICENSE-2.0
9
10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16
17
#ifndef JSONNET_STATE_H
18
#define JSONNET_STATE_H
19
20
namespace jsonnet::internal {
21
namespace {
22
23
/** Mark & sweep: advanced by 1 each GC cycle.
24
 */
25
typedef unsigned char GarbageCollectionMark;
26
27
/** Supertype of everything that is allocated on the heap.
28
 */
29
struct HeapEntity {
30
    enum Type : unsigned char {
31
        THUNK,
32
        ARRAY,
33
        CLOSURE,
34
        STRING,
35
        SIMPLE_OBJECT,
36
        COMPREHENSION_OBJECT,
37
        EXTENDED_OBJECT,
38
    };
39
    GarbageCollectionMark mark;
40
    Type type;
41
290M
    HeapEntity(Type type_) : type(type_) {}
42
290M
    virtual ~HeapEntity() {}
43
};
44
45
/** Tagged union of all values.
46
 *
47
 * Primitives (<= 8 bytes) are copied by value.  Otherwise a pointer to a HeapEntity is used.
48
 */
49
struct Value {
50
    enum Type {
51
        NULL_TYPE = 0x0,  // Unfortunately NULL is a macro in C.
52
        BOOLEAN = 0x1,
53
        NUMBER = 0x2,
54
55
        ARRAY = 0x10,
56
        FUNCTION = 0x11,
57
        OBJECT = 0x12,
58
        STRING = 0x13
59
    };
60
    Type t;
61
    union {
62
        HeapEntity *h;
63
        double d;
64
        bool b;
65
    } v;
66
    bool isHeap(void) const
67
166M
    {
68
166M
        return t & 0x10;
69
166M
    }
70
};
71
72
/** Convert the type into a string, for error messages. */
73
std::string type_str(Value::Type t)
74
3.22k
{
75
3.22k
    switch (t) {
76
29
        case Value::NULL_TYPE: return "null";
77
730
        case Value::BOOLEAN: return "boolean";
78
657
        case Value::NUMBER: return "number";
79
141
        case Value::ARRAY: return "array";
80
13
        case Value::FUNCTION: return "function";
81
432
        case Value::OBJECT: return "object";
82
1.22k
        case Value::STRING: return "string";
83
0
        default:
84
0
            std::cerr << "INTERNAL ERROR: Unknown type: " << t << std::endl;
85
0
            std::abort();
86
0
            return "";  // Quiet, compiler.
87
3.22k
    }
88
3.22k
}
89
90
/** Convert the value's type into a string, for error messages. */
91
std::string type_str(const Value &v)
92
1.08k
{
93
1.08k
    return type_str(v.t);
94
1.08k
}
95
96
struct HeapThunk;
97
98
/** Stores the values bound to variables.
99
 *
100
 * Each nested local statement, function call, and field access has its own binding frame to
101
 * give the values for the local variable, function parameters, or upValues.
102
 */
103
typedef std::map<const Identifier *, HeapThunk *> BindingFrame;
104
105
/** Supertype of all objects.  Types of Value::OBJECT will point at these.  */
106
struct HeapObject : public HeapEntity {
107
9.94M
    HeapObject(Type type) : HeapEntity(type) {}
108
};
109
110
/** Hold an unevaluated expression.  This implements lazy semantics.
111
 */
112
struct HeapThunk : public HeapEntity {
113
    /** Whether or not the thunk was forced. */
114
    bool filled;
115
116
    /** The result when the thunk was forced, if filled == true. */
117
    Value content;
118
119
    /** Used in error tracebacks. */
120
    const Identifier *name;
121
122
    /** The captured environment.
123
     *
124
     * Note, this is non-const because we have to add cyclic references to it.
125
     */
126
    BindingFrame upValues;
127
128
    /** The captured self variable, or nullptr if there was none.  \see CallFrame. */
129
    HeapObject *self;
130
131
    /** The offset from the captured self variable. \see CallFrame. */
132
    unsigned offset;
133
134
    /** Evaluated to force the thunk. */
135
    const AST *body;
136
137
    HeapThunk(const Identifier *name, HeapObject *self, unsigned offset, const AST *body)
138
128M
        : HeapEntity(THUNK), filled(false), name(name), self(self), offset(offset), body(body)
139
128M
    {
140
128M
    }
141
142
    void fill(const Value &v)
143
74.0M
    {
144
74.0M
        content = v;
145
74.0M
        filled = true;
146
74.0M
        self = nullptr;
147
74.0M
        upValues.clear();
148
74.0M
    }
149
};
150
151
struct HeapArray : public HeapEntity {
152
    // It is convenient for this to not be const, so that we can add elements to it one at a
153
    // time after creation.  Thus, elements are not GCed as the array is being
154
    // created.
155
    std::vector<HeapThunk *> elements;
156
    HeapArray(const std::vector<HeapThunk *> &elements)
157
3.97M
        : HeapEntity(ARRAY), elements(elements)
158
3.97M
    {
159
3.97M
    }
160
};
161
162
/** Supertype of all objects that are not super objects or extended objects.  */
163
struct HeapLeafObject : public HeapObject {
164
5.76M
    HeapLeafObject(Type type) : HeapObject(type) {}
165
};
166
167
/** Objects created via the simple object constructor construct. */
168
struct HeapSimpleObject : public HeapLeafObject {
169
    /** The captured environment. */
170
    const BindingFrame upValues;
171
172
    struct Field {
173
        /** Will the field appear in output? */
174
        ObjectField::Hide hide;
175
        /** Expression that is evaluated when indexing this field. */
176
        AST *body;
177
    };
178
179
    /** The fields.
180
     *
181
     * These are evaluated in the captured environment and with self and super bound
182
     * dynamically.
183
     */
184
    const std::map<const Identifier *, Field> fields;
185
186
    /** The object's invariants.
187
     *
188
     * These are evaluated in the captured environment with self and super bound.
189
     */
190
    ASTs asserts;
191
192
    HeapSimpleObject(const BindingFrame &up_values,
193
                     const std::map<const Identifier *, Field> fields, ASTs asserts)
194
5.76M
        : HeapLeafObject(SIMPLE_OBJECT), upValues(up_values), fields(fields), asserts(asserts)
195
5.76M
    {
196
5.76M
    }
197
};
198
199
/** Objects created by the + construct. */
200
struct HeapExtendedObject : public HeapObject {
201
    /** The left hand side of the construct. */
202
    HeapObject *left;
203
204
    /** The right hand side of the construct. */
205
    HeapObject *right;
206
207
    HeapExtendedObject(HeapObject *left, HeapObject *right)
208
4.18M
        : HeapObject(EXTENDED_OBJECT), left(left), right(right)
209
4.18M
    {
210
4.18M
    }
211
};
212
213
/** Objects created by the ObjectComprehensionSimple construct. */
214
struct HeapComprehensionObject : public HeapLeafObject {
215
    /** The captured environment. */
216
    const BindingFrame upValues;
217
218
    /** The expression used to compute the field values.  */
219
    const AST *value;
220
221
    /** The identifier of bound variable in that construct.  */
222
    const Identifier *const id;
223
224
    /** Binding for id.
225
     *
226
     * For each field, holds the value that should be bound to id.  This is the corresponding
227
     * array element from the original array used to define this object.  This should not really
228
     * be a thunk, but it makes the implementation easier.
229
     *
230
     * It is convenient to make this non-const to allow building up the values one by one, so that
231
     * the garbage collector can see them at each intermediate point.
232
     */
233
    std::map<const Identifier *, HeapThunk *> compValues;
234
235
    HeapComprehensionObject(const BindingFrame &up_values, const AST *value, const Identifier *id,
236
                            const std::map<const Identifier *, HeapThunk *> &comp_values)
237
0
        : HeapLeafObject(COMPREHENSION_OBJECT), upValues(up_values), value(value), id(id), compValues(comp_values)
238
0
    {
239
0
    }
240
};
241
242
/** Stores the function itself and also the captured environment.
243
 *
244
 * Either body is non-null and builtinName is "", or body is null and builtin refers to a built-in
245
 * function.  In the former case, the closure represents a user function, otherwise calling it
246
 * will trigger the builtin function to execute.  Params is empty when the function is a
247
 * builtin.
248
 */
249
struct HeapClosure : public HeapEntity {
250
    /** The captured environment. */
251
    const BindingFrame upValues;
252
    /** The captured self variable, or nullptr if there was none.  \see Frame. */
253
    HeapObject *self;
254
    /** The offset from the captured self variable.  \see Frame.*/
255
    unsigned offset;
256
    struct Param {
257
        const Identifier *id;
258
        const AST *def;
259
51.0M
        Param(const Identifier *id, const AST *def) : id(id), def(def) {}
260
    };
261
    typedef std::vector<Param> Params;
262
    const Params params;
263
    const AST *body;
264
    std::string builtinName;
265
    HeapClosure(const BindingFrame &up_values, HeapObject *self, unsigned offset,
266
                const Params &params, const AST *body, const std::string &builtin_name)
267
31.2M
        : HeapEntity(CLOSURE),
268
31.2M
          upValues(up_values),
269
31.2M
          self(self),
270
31.2M
          offset(offset),
271
31.2M
          params(params),
272
31.2M
          body(body),
273
31.2M
          builtinName(builtin_name)
274
31.2M
    {
275
31.2M
    }
276
};
277
278
/** Stores a simple string on the heap. */
279
struct HeapString : public HeapEntity {
280
    const UString value;
281
116M
    HeapString(const UString &value) : HeapEntity(STRING), value(value) {}
282
};
283
284
/** The heap does memory management, i.e. garbage collection. */
285
class Heap {
286
    /** How many objects must exist in the heap before we bother doing garbage collection?
287
     */
288
    unsigned gcTuneMinObjects;
289
290
    /** How much must the heap have grown since the last cycle to trigger a collection?
291
     */
292
    double gcTuneGrowthTrigger;
293
294
    /** Value used to mark entities at the last garbage collection cycle. */
295
    GarbageCollectionMark lastMark;
296
297
    /** The heap entities (strings, arrays, objects, functions, etc).
298
     *
299
     * Not all may be reachable, all should have o->mark == this->lastMark.  Entities are
300
     * removed from the heap via O(1) swap with last element, so the ordering of entities is
301
     * arbitrary and changes every garbage collection cycle.
302
     */
303
    std::vector<HeapEntity *> entities;
304
305
    /** The number of heap entities at the last garbage collection cycle. */
306
    unsigned long lastNumEntities;
307
308
    /** The number of heap entities now. */
309
    unsigned long numEntities;
310
311
    /** Add the HeapEntity inside v to vec, if the value exists on the heap.
312
     */
313
    void addIfHeapEntity(Value v, std::vector<HeapEntity *> &vec)
314
0
    {
315
0
        if (v.isHeap())
316
0
            vec.push_back(v.v.h);
317
0
    }
318
319
    /** Add the HeapEntity inside v to vec, if the value exists on the heap.
320
     */
321
    void addIfHeapEntity(HeapEntity *v, std::vector<HeapEntity *> &vec)
322
252M
    {
323
252M
        vec.push_back(v);
324
252M
    }
325
326
   public:
327
    Heap(unsigned gc_tune_min_objects, double gc_tune_growth_trigger)
328
10.2k
        : gcTuneMinObjects(gc_tune_min_objects),
329
10.2k
          gcTuneGrowthTrigger(gc_tune_growth_trigger),
330
10.2k
          lastMark(0),
331
10.2k
          lastNumEntities(0),
332
10.2k
          numEntities(0)
333
10.2k
    {
334
10.2k
    }
335
336
    ~Heap(void)
337
10.2k
    {
338
        // Nothing is marked, everything will be collected.
339
10.2k
        sweep();
340
10.2k
    }
341
342
    /** Garbage collection: Mark v, and entities reachable from v. */
343
    void markFrom(Value v)
344
138M
    {
345
138M
        if (v.isHeap())
346
35.8M
            markFrom(v.v.h);
347
138M
    }
348
349
    /** Garbage collection: Mark heap entities reachable from the given heap entity. */
350
    void markFrom(HeapEntity *from)
351
255M
    {
352
255M
        assert(from != nullptr);
353
255M
        const GarbageCollectionMark thisMark = lastMark + 1;
354
255M
        struct State {
355
255M
            HeapEntity *ent;
356
255M
            std::vector<HeapEntity *> children;
357
508M
            State(HeapEntity *ent) : ent(ent) {}
358
255M
        };
359
360
255M
        std::vector<State> stack;
361
255M
        stack.emplace_back(from);
362
363
1.01G
        while (stack.size() > 0) {
364
760M
            size_t curr_index = stack.size() - 1;
365
760M
            State &s = stack[curr_index];
366
760M
            HeapEntity *curr = s.ent;
367
760M
            if (curr->mark != thisMark) {
368
191M
                curr->mark = thisMark;
369
370
191M
                switch(curr->type) {
371
29.7M
                    case HeapEntity::SIMPLE_OBJECT: {
372
29.7M
                        assert(dynamic_cast<HeapSimpleObject *>(curr));
373
29.7M
                        auto *obj = static_cast<HeapSimpleObject *>(curr);
374
29.7M
                        for (auto upv : obj->upValues)
375
24.2M
                            addIfHeapEntity(upv.second, s.children);
376
29.7M
                        break;
377
29.7M
                    }
378
20.9M
                    case HeapEntity::EXTENDED_OBJECT: {
379
20.9M
                        assert(dynamic_cast<HeapExtendedObject *>(curr));
380
20.9M
                        auto *obj = static_cast<HeapExtendedObject *>(curr);
381
20.9M
                        addIfHeapEntity(obj->left, s.children);
382
20.9M
                        addIfHeapEntity(obj->right, s.children);
383
20.9M
                        break;
384
20.9M
                    }
385
0
                    case HeapEntity::COMPREHENSION_OBJECT: {
386
0
                        assert(dynamic_cast<HeapComprehensionObject *>(curr));
387
0
                        auto *obj = static_cast<HeapComprehensionObject *>(curr);
388
0
                        for (auto upv : obj->upValues)
389
0
                            addIfHeapEntity(upv.second, s.children);
390
0
                        for (auto upv : obj->compValues)
391
0
                            addIfHeapEntity(upv.second, s.children);
392
0
                        break;
393
0
                    }
394
3.20M
                    case HeapEntity::ARRAY: {
395
3.20M
                        assert(dynamic_cast<HeapArray *>(curr));
396
3.20M
                        auto *arr = static_cast<HeapArray *>(curr);
397
3.20M
                        for (auto el : arr->elements)
398
35.6M
                            addIfHeapEntity(el, s.children);
399
3.20M
                        break;
400
3.20M
                    }
401
4.64M
                    case HeapEntity::CLOSURE: {
402
4.64M
                        assert(dynamic_cast<HeapClosure *>(curr));
403
4.64M
                        auto *func = static_cast<HeapClosure *>(curr);
404
4.64M
                        for (auto upv : func->upValues)
405
10.5M
                            addIfHeapEntity(upv.second, s.children);
406
4.64M
                        if (func->self)
407
3.91M
                            addIfHeapEntity(func->self, s.children);
408
4.64M
                        break;
409
4.64M
                    }
410
128M
                    case HeapEntity::THUNK: {
411
128M
                        assert(dynamic_cast<HeapThunk *>(curr));
412
128M
                        auto *thunk = static_cast<HeapThunk *>(curr);
413
128M
                        if (thunk->filled) {
414
26.6M
                            if (thunk->content.isHeap())
415
17.9M
                                addIfHeapEntity(thunk->content.v.h, s.children);
416
101M
                        } else {
417
101M
                            for (auto upv : thunk->upValues)
418
20.5M
                                addIfHeapEntity(upv.second, s.children);
419
101M
                            if (thunk->self)
420
97.3M
                                addIfHeapEntity(thunk->self, s.children);
421
101M
                        }
422
128M
                        break;
423
128M
                    }
424
4.99M
                    case HeapEntity::STRING:
425
4.99M
                        assert(dynamic_cast<HeapString *>(curr));
426
4.99M
                        break;
427
4.99M
                    default:
428
0
                        assert(false);
429
0
                        break;
430
191M
                }
431
191M
            }
432
433
760M
            if (s.children.size() > 0) {
434
252M
                HeapEntity *next = s.children[s.children.size() - 1];
435
252M
                s.children.pop_back();
436
252M
                stack.emplace_back(next);  // CAUTION: s invalidated here
437
508M
            } else {
438
508M
                stack.pop_back();  // CAUTION: s invalidated here
439
508M
            }
440
760M
        }
441
255M
    }
442
443
    /** Delete everything that was not marked since the last collection. */
444
    void sweep(void)
445
348k
    {
446
348k
        lastMark++;
447
        // Heap shrinks during this loop.  Do not cache entities.size().
448
482M
        for (unsigned long i = 0; i < entities.size(); ++i) {
449
482M
            HeapEntity *x = entities[i];
450
482M
            if (x->mark != lastMark) {
451
290M
                delete x;
452
290M
                if (i != entities.size() - 1) {
453
                    // Swap it with the back.
454
289M
                    entities[i] = entities[entities.size() - 1];
455
289M
                }
456
290M
                entities.pop_back();
457
290M
                --i;
458
290M
            }
459
482M
        }
460
348k
        lastNumEntities = numEntities = entities.size();
461
348k
    }
462
463
    /** Is it time to initiate a GC cycle? */
464
    bool checkHeap(void)
465
290M
    {
466
290M
        return numEntities > gcTuneMinObjects &&
467
96.3M
               numEntities > gcTuneGrowthTrigger * lastNumEntities;
468
290M
    }
469
470
    /** Allocate a heap entity.
471
     *
472
     * If the heap is large enough (\see gcTuneMinObjects) and has grown by enough since the
473
     * last collection cycle (\see gcTuneGrowthTrigger), a collection cycle should be performed.
474
     */
475
    template <class T, class... Args>
476
    T *makeEntity(Args &&... args)
477
290M
    {
478
290M
        T *r = new T(std::forward<Args>(args)...);
479
290M
        entities.push_back(r);
480
290M
        r->mark = lastMark;
481
290M
        numEntities = entities.size();
482
290M
        return r;
483
290M
    }
Unexecuted instantiation: vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject* const&, unsigned int const&, jsonnet::internal::AST const* const&>(jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject* const&, unsigned int const&, jsonnet::internal::AST const* const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const* const&, decltype(nullptr), int, decltype(nullptr)>(jsonnet::internal::Identifier const* const&, decltype(nullptr)&&, int&&, decltype(nullptr)&&)
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapArray* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapArray, std::__1::vector<jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::allocator<jsonnet::internal::(anonymous namespace)::HeapThunk*> > const&>(std::__1::vector<jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::allocator<jsonnet::internal::(anonymous namespace)::HeapThunk*> > const&)
Line
Count
Source
477
3.97M
    {
478
3.97M
        T *r = new T(std::forward<Args>(args)...);
479
3.97M
        entities.push_back(r);
480
3.97M
        r->mark = lastMark;
481
3.97M
        numEntities = entities.size();
482
3.97M
        return r;
483
3.97M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapString* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapString, std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, std::__1::allocator<char32_t> > const&>(std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, std::__1::allocator<char32_t> > const&)
Line
Count
Source
477
116M
    {
478
116M
        T *r = new T(std::forward<Args>(args)...);
479
116M
        entities.push_back(r);
480
116M
        r->mark = lastMark;
481
116M
        numEntities = entities.size();
482
116M
        return r;
483
116M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const*&, decltype(nullptr), int, decltype(nullptr)>(jsonnet::internal::Identifier const*&, decltype(nullptr)&&, int&&, decltype(nullptr)&&)
Line
Count
Source
477
1.38M
    {
478
1.38M
        T *r = new T(std::forward<Args>(args)...);
479
1.38M
        entities.push_back(r);
480
1.38M
        r->mark = lastMark;
481
1.38M
        numEntities = entities.size();
482
1.38M
        return r;
483
1.38M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapClosure* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapClosure, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >, decltype(nullptr), int, std::__1::vector<jsonnet::internal::(anonymous namespace)::HeapClosure::Param, std::__1::allocator<jsonnet::internal::(anonymous namespace)::HeapClosure::Param> > const&, jsonnet::internal::AST*&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&&, decltype(nullptr)&&, int&&, std::__1::vector<jsonnet::internal::(anonymous namespace)::HeapClosure::Param, std::__1::allocator<jsonnet::internal::(anonymous namespace)::HeapClosure::Param> > const&, jsonnet::internal::AST*&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
477
25.2M
    {
478
25.2M
        T *r = new T(std::forward<Args>(args)...);
479
25.2M
        entities.push_back(r);
480
25.2M
        r->mark = lastMark;
481
25.2M
        numEntities = entities.size();
482
25.2M
        return r;
483
25.2M
    }
Unexecuted instantiation: vm.cpp:jsonnet::internal::(anonymous namespace)::HeapComprehensionObject* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapComprehensionObject, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&, jsonnet::internal::AST const*&, jsonnet::internal::Identifier const*&, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&>(std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&, jsonnet::internal::AST const*&, jsonnet::internal::Identifier const*&, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&)
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, decltype(nullptr), decltype(nullptr), int, jsonnet::internal::AST const*>(decltype(nullptr)&&, decltype(nullptr)&&, int&&, jsonnet::internal::AST const*&&)
Line
Count
Source
477
10.2k
    {
478
10.2k
        T *r = new T(std::forward<Args>(args)...);
479
10.2k
        entities.push_back(r);
480
10.2k
        r->mark = lastMark;
481
10.2k
        numEntities = entities.size();
482
10.2k
        return r;
483
10.2k
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier*, jsonnet::internal::(anonymous namespace)::HeapObject*&, int, jsonnet::internal::AST* const&>(jsonnet::internal::Identifier*&&, jsonnet::internal::(anonymous namespace)::HeapObject*&, int&&, jsonnet::internal::AST* const&)
Line
Count
Source
477
1.63M
    {
478
1.63M
        T *r = new T(std::forward<Args>(args)...);
479
1.63M
        entities.push_back(r);
480
1.63M
        r->mark = lastMark;
481
1.63M
        numEntities = entities.size();
482
1.63M
        return r;
483
1.63M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST* const&>(jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST* const&)
Line
Count
Source
477
67.0M
    {
478
67.0M
        T *r = new T(std::forward<Args>(args)...);
479
67.0M
        entities.push_back(r);
480
67.0M
        r->mark = lastMark;
481
67.0M
        numEntities = entities.size();
482
67.0M
        return r;
483
67.0M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapClosure* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapClosure, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > > const&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, std::__1::vector<jsonnet::internal::(anonymous namespace)::HeapClosure::Param, std::__1::allocator<jsonnet::internal::(anonymous namespace)::HeapClosure::Param> > const&, jsonnet::internal::AST*&, char const (&) [1]>(std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > > const&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, std::__1::vector<jsonnet::internal::(anonymous namespace)::HeapClosure::Param, std::__1::allocator<jsonnet::internal::(anonymous namespace)::HeapClosure::Param> > const&, jsonnet::internal::AST*&, char const (&) [1])
Line
Count
Source
477
5.95M
    {
478
5.95M
        T *r = new T(std::forward<Args>(args)...);
479
5.95M
        entities.push_back(r);
480
5.95M
        r->mark = lastMark;
481
5.95M
        numEntities = entities.size();
482
5.95M
        return r;
483
5.95M
    }
Unexecuted instantiation: vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const*&, decltype(nullptr), int, jsonnet::internal::AST*&>(jsonnet::internal::Identifier const*&, decltype(nullptr)&&, int&&, jsonnet::internal::AST*&)
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const* const&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST* const&>(jsonnet::internal::Identifier const* const&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST* const&)
Line
Count
Source
477
54.6M
    {
478
54.6M
        T *r = new T(std::forward<Args>(args)...);
479
54.6M
        entities.push_back(r);
480
54.6M
        r->mark = lastMark;
481
54.6M
        numEntities = entities.size();
482
54.6M
        return r;
483
54.6M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapSimpleObject* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapSimpleObject, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapSimpleObject::Field, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapSimpleObject::Field> > >&, std::__1::list<jsonnet::internal::AST*, std::__1::allocator<jsonnet::internal::AST*> >&>(std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapSimpleObject::Field, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapSimpleObject::Field> > >&, std::__1::list<jsonnet::internal::AST*, std::__1::allocator<jsonnet::internal::AST*> >&)
Line
Count
Source
477
5.76M
    {
478
5.76M
        T *r = new T(std::forward<Args>(args)...);
479
5.76M
        entities.push_back(r);
480
5.76M
        r->mark = lastMark;
481
5.76M
        numEntities = entities.size();
482
5.76M
        return r;
483
5.76M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST const* const&>(jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST const* const&)
Line
Count
Source
477
325
    {
478
325
        T *r = new T(std::forward<Args>(args)...);
479
325
        entities.push_back(r);
480
325
        r->mark = lastMark;
481
325
        numEntities = entities.size();
482
325
        return r;
483
325
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapExtendedObject* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapExtendedObject, jsonnet::internal::(anonymous namespace)::HeapObject*&, jsonnet::internal::(anonymous namespace)::HeapObject*&>(jsonnet::internal::(anonymous namespace)::HeapObject*&, jsonnet::internal::(anonymous namespace)::HeapObject*&)
Line
Count
Source
477
4.18M
    {
478
4.18M
        T *r = new T(std::forward<Args>(args)...);
479
4.18M
        entities.push_back(r);
480
4.18M
        r->mark = lastMark;
481
4.18M
        numEntities = entities.size();
482
4.18M
        return r;
483
4.18M
    }
vm.cpp:jsonnet::internal::(anonymous namespace)::HeapThunk* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapThunk, jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST*&>(jsonnet::internal::Identifier const*&, jsonnet::internal::(anonymous namespace)::HeapObject*&, unsigned int&, jsonnet::internal::AST*&)
Line
Count
Source
477
3.60M
    {
478
3.60M
        T *r = new T(std::forward<Args>(args)...);
479
3.60M
        entities.push_back(r);
480
3.60M
        r->mark = lastMark;
481
3.60M
        numEntities = entities.size();
482
3.60M
        return r;
483
3.60M
    }
Unexecuted instantiation: vm.cpp:jsonnet::internal::(anonymous namespace)::HeapComprehensionObject* jsonnet::internal::(anonymous namespace)::Heap::makeEntity<jsonnet::internal::(anonymous namespace)::HeapComprehensionObject, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&, jsonnet::internal::AST*&, jsonnet::internal::Identifier const*&, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&>(std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&, jsonnet::internal::AST*&, jsonnet::internal::Identifier const*&, std::__1::map<jsonnet::internal::Identifier const*, jsonnet::internal::(anonymous namespace)::HeapThunk*, std::__1::less<jsonnet::internal::Identifier const*>, std::__1::allocator<std::__1::pair<jsonnet::internal::Identifier const* const, jsonnet::internal::(anonymous namespace)::HeapThunk*> > >&)
484
};
485
486
}  // namespace
487
}  // namespace jsonnet::internal
488
489
#endif  // JSONNET_STATE_H