Coverage Report

Created: 2026-11-12 07:16

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