Coverage Report

Created: 2026-05-30 06:23

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
258M
    HeapEntity(Type type_) : type(type_) {}
44
258M
    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
155M
    {
70
155M
        return t & 0x10;
71
155M
    }
72
};
73
74
/** Convert the type into a string, for error messages. */
75
std::string type_str(Value::Type t)
76
3.17k
{
77
3.17k
    switch (t) {
78
19
        case Value::NULL_TYPE: return "null";
79
601
        case Value::BOOLEAN: return "boolean";
80
638
        case Value::NUMBER: return "number";
81
142
        case Value::ARRAY: return "array";
82
5
        case Value::FUNCTION: return "function";
83
510
        case Value::OBJECT: return "object";
84
1.25k
        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.17k
    }
90
3.17k
}
91
92
/** Convert the value's type into a string, for error messages. */
93
std::string type_str(const Value &v)
94
1.18k
{
95
1.18k
    return type_str(v.t);
96
1.18k
}
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.15M
    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
120M
        : HeapEntity(THUNK), filled(false), name(name), self(self), offset(offset), body(body)
141
120M
    {
142
120M
    }
143
144
    void fill(const Value &v)
145
68.4M
    {
146
68.4M
        content = v;
147
68.4M
        filled = true;
148
68.4M
        self = nullptr;
149
68.4M
        upValues.clear();
150
68.4M
    }
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
3.27M
        : HeapEntity(ARRAY), elements(elements)
160
3.27M
    {
161
3.27M
    }
162
};
163
164
/** Supertype of all objects that are not super objects or extended objects.  */
165
struct HeapLeafObject : public HeapObject {
166
4.78M
    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.78M
        : HeapLeafObject(SIMPLE_OBJECT), upValues(up_values), fields(fields), asserts(asserts)
197
4.78M
    {
198
4.78M
    }
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.36M
        : HeapObject(EXTENDED_OBJECT), left(left), right(right)
211
3.36M
    {
212
3.36M
    }
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
46.8M
        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
28.6M
        : HeapEntity(CLOSURE),
284
28.6M
          upValues(up_values),
285
28.6M
          self(self),
286
28.6M
          offset(offset),
287
28.6M
          params(params),
288
28.6M
          body(body),
289
28.6M
          builtinName(builtin_name)
290
28.6M
    {
291
28.6M
    }
292
293
82.6M
    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
98.4M
    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
235M
    {
341
235M
        vec.push_back(v);
342
235M
    }
343
344
   public:
345
    Heap(unsigned gc_tune_min_objects, double gc_tune_growth_trigger)
346
9.76k
        : gcTuneMinObjects(gc_tune_min_objects),
347
9.76k
          gcTuneGrowthTrigger(gc_tune_growth_trigger),
348
9.76k
          lastMark(0),
349
9.76k
          lastNumEntities(0),
350
9.76k
          numEntities(0)
351
9.76k
    {
352
9.76k
    }
353
354
    ~Heap(void)
355
9.76k
    {
356
        // Nothing is marked, everything will be collected.
357
9.76k
        sweep();
358
9.76k
    }
359
360
    /** Garbage collection: Mark v, and entities reachable from v. */
361
    void markFrom(Value v)
362
124M
    {
363
124M
        if (v.isHeap())
364
33.0M
            markFrom(v.v.h);
365
124M
    }
366
367
    /** Garbage collection: Mark heap entities reachable from the given heap entity. */
368
    void markFrom(HeapEntity *from)
369
238M
    {
370
238M
        assert(from != nullptr);
371
238M
        const GarbageCollectionMark thisMark = lastMark + 1;
372
238M
        struct State {
373
238M
            HeapEntity *ent;
374
238M
            std::vector<HeapEntity *> children;
375
474M
            State(HeapEntity *ent) : ent(ent) {}
376
238M
        };
377
378
238M
        std::vector<State> stack;
379
238M
        stack.emplace_back(from);
380
381
948M
        while (stack.size() > 0) {
382
710M
            size_t curr_index = stack.size() - 1;
383
710M
            State &s = stack[curr_index];
384
710M
            HeapEntity *curr = s.ent;
385
710M
            if (curr->mark != thisMark) {
386
178M
                curr->mark = thisMark;
387
388
178M
                switch(curr->type) {
389
25.5M
                    case HeapEntity::SIMPLE_OBJECT: {
390
25.5M
                        assert(dynamic_cast<HeapSimpleObject *>(curr));
391
25.5M
                        auto *obj = static_cast<HeapSimpleObject *>(curr);
392
25.5M
                        for (auto upv : obj->upValues)
393
22.7M
                            addIfHeapEntity(upv.second, s.children);
394
25.5M
                        break;
395
25.5M
                    }
396
16.0M
                    case HeapEntity::EXTENDED_OBJECT: {
397
16.0M
                        assert(dynamic_cast<HeapExtendedObject *>(curr));
398
16.0M
                        auto *obj = static_cast<HeapExtendedObject *>(curr);
399
16.0M
                        addIfHeapEntity(obj->left, s.children);
400
16.0M
                        addIfHeapEntity(obj->right, s.children);
401
16.0M
                        break;
402
16.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.08M
                    case HeapEntity::ARRAY: {
419
4.08M
                        assert(dynamic_cast<HeapArray *>(curr));
420
4.08M
                        auto *arr = static_cast<HeapArray *>(curr);
421
4.08M
                        for (auto el : arr->elements)
422
35.5M
                            addIfHeapEntity(el, s.children);
423
4.08M
                        break;
424
4.08M
                    }
425
4.82M
                    case HeapEntity::CLOSURE: {
426
4.82M
                        assert(dynamic_cast<HeapClosure *>(curr));
427
4.82M
                        auto *func = static_cast<HeapClosure *>(curr);
428
4.82M
                        for (auto upv : func->upValues)
429
11.1M
                            addIfHeapEntity(upv.second, s.children);
430
4.82M
                        if (func->self)
431
4.14M
                            addIfHeapEntity(func->self, s.children);
432
4.82M
                        break;
433
4.82M
                    }
434
122M
                    case HeapEntity::THUNK: {
435
122M
                        assert(dynamic_cast<HeapThunk *>(curr));
436
122M
                        auto *thunk = static_cast<HeapThunk *>(curr);
437
122M
                        if (thunk->filled) {
438
29.8M
                            if (thunk->content.isHeap())
439
20.4M
                                addIfHeapEntity(thunk->content.v.h, s.children);
440
92.4M
                        } else {
441
92.4M
                            for (auto upv : thunk->upValues)
442
21.1M
                                addIfHeapEntity(upv.second, s.children);
443
92.4M
                            if (thunk->self)
444
88.5M
                                addIfHeapEntity(thunk->self, s.children);
445
92.4M
                        }
446
122M
                        break;
447
122M
                    }
448
5.90M
                    case HeapEntity::STRING:
449
5.90M
                        assert(dynamic_cast<HeapString *>(curr));
450
5.90M
                        break;
451
5.90M
                    default:
452
0
                        assert(false);
453
0
                        break;
454
178M
                }
455
178M
            }
456
457
710M
            if (s.children.size() > 0) {
458
235M
                HeapEntity *next = s.children[s.children.size() - 1];
459
235M
                s.children.pop_back();
460
235M
                stack.emplace_back(next);  // CAUTION: s invalidated here
461
474M
            } else {
462
474M
                stack.pop_back();  // CAUTION: s invalidated here
463
474M
            }
464
710M
        }
465
238M
    }
466
467
    /** Delete everything that was not marked since the last collection. */
468
    void sweep(void)
469
309k
    {
470
309k
        lastMark++;
471
        // Heap shrinks during this loop.  Do not cache entities.size().
472
437M
        for (unsigned long i = 0; i < entities.size(); ++i) {
473
437M
            HeapEntity *x = entities[i];
474
437M
            if (x->mark != lastMark) {
475
258M
                delete x;
476
258M
                if (i != entities.size() - 1) {
477
                    // Swap it with the back.
478
258M
                    entities[i] = entities[entities.size() - 1];
479
258M
                }
480
258M
                entities.pop_back();
481
258M
                --i;
482
258M
            }
483
437M
        }
484
309k
        lastNumEntities = numEntities = entities.size();
485
309k
    }
486
487
    /** Is it time to initiate a GC cycle? */
488
    bool checkHeap(void)
489
258M
    {
490
258M
        return numEntities > gcTuneMinObjects &&
491
92.0M
               numEntities > gcTuneGrowthTrigger * lastNumEntities;
492
258M
    }
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
258M
    {
502
258M
        T *r = new T(std::forward<Args>(args)...);
503
258M
        entities.push_back(r);
504
258M
        r->mark = lastMark;
505
258M
        numEntities = entities.size();
506
258M
        return r;
507
258M
    }
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
3.27M
    {
502
3.27M
        T *r = new T(std::forward<Args>(args)...);
503
3.27M
        entities.push_back(r);
504
3.27M
        r->mark = lastMark;
505
3.27M
        numEntities = entities.size();
506
3.27M
        return r;
507
3.27M
    }
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
98.4M
    {
502
98.4M
        T *r = new T(std::forward<Args>(args)...);
503
98.4M
        entities.push_back(r);
504
98.4M
        r->mark = lastMark;
505
98.4M
        numEntities = entities.size();
506
98.4M
        return r;
507
98.4M
    }
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.44M
    {
502
1.44M
        T *r = new T(std::forward<Args>(args)...);
503
1.44M
        entities.push_back(r);
504
1.44M
        r->mark = lastMark;
505
1.44M
        numEntities = entities.size();
506
1.44M
        return r;
507
1.44M
    }
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
23.0M
    {
502
23.0M
        T *r = new T(std::forward<Args>(args)...);
503
23.0M
        entities.push_back(r);
504
23.0M
        r->mark = lastMark;
505
23.0M
        numEntities = entities.size();
506
23.0M
        return r;
507
23.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
9.76k
    {
502
9.76k
        T *r = new T(std::forward<Args>(args)...);
503
9.76k
        entities.push_back(r);
504
9.76k
        r->mark = lastMark;
505
9.76k
        numEntities = entities.size();
506
9.76k
        return r;
507
9.76k
    }
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.57M
    {
502
1.57M
        T *r = new T(std::forward<Args>(args)...);
503
1.57M
        entities.push_back(r);
504
1.57M
        r->mark = lastMark;
505
1.57M
        numEntities = entities.size();
506
1.57M
        return r;
507
1.57M
    }
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
63.6M
    {
502
63.6M
        T *r = new T(std::forward<Args>(args)...);
503
63.6M
        entities.push_back(r);
504
63.6M
        r->mark = lastMark;
505
63.6M
        numEntities = entities.size();
506
63.6M
        return r;
507
63.6M
    }
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
5.55M
    {
502
5.55M
        T *r = new T(std::forward<Args>(args)...);
503
5.55M
        entities.push_back(r);
504
5.55M
        r->mark = lastMark;
505
5.55M
        numEntities = entities.size();
506
5.55M
        return r;
507
5.55M
    }
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
51.0M
    {
502
51.0M
        T *r = new T(std::forward<Args>(args)...);
503
51.0M
        entities.push_back(r);
504
51.0M
        r->mark = lastMark;
505
51.0M
        numEntities = entities.size();
506
51.0M
        return r;
507
51.0M
    }
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.78M
    {
502
4.78M
        T *r = new T(std::forward<Args>(args)...);
503
4.78M
        entities.push_back(r);
504
4.78M
        r->mark = lastMark;
505
4.78M
        numEntities = entities.size();
506
4.78M
        return r;
507
4.78M
    }
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
375
    {
502
375
        T *r = new T(std::forward<Args>(args)...);
503
375
        entities.push_back(r);
504
375
        r->mark = lastMark;
505
375
        numEntities = entities.size();
506
375
        return r;
507
375
    }
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.36M
    {
502
3.36M
        T *r = new T(std::forward<Args>(args)...);
503
3.36M
        entities.push_back(r);
504
3.36M
        r->mark = lastMark;
505
3.36M
        numEntities = entities.size();
506
3.36M
        return r;
507
3.36M
    }
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.57M
    {
502
2.57M
        T *r = new T(std::forward<Args>(args)...);
503
2.57M
        entities.push_back(r);
504
2.57M
        r->mark = lastMark;
505
2.57M
        numEntities = entities.size();
506
2.57M
        return r;
507
2.57M
    }
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