Coverage Report

Created: 2025-08-26 06:57

/src/jsonnet/core/state.h
Line
Count
Source (jump to first uncovered line)
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
312M
    HeapEntity(Type type_) : type(type_) {}
42
312M
    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
174M
    {
68
174M
        return t & 0x10;
69
174M
    }
70
};
71
72
/** Convert the type into a string, for error messages. */
73
std::string type_str(Value::Type t)
74
3.16k
{
75
3.16k
    switch (t) {
76
20
        case Value::NULL_TYPE: return "null";
77
652
        case Value::BOOLEAN: return "boolean";
78
711
        case Value::NUMBER: return "number";
79
132
        case Value::ARRAY: return "array";
80
3
        case Value::FUNCTION: return "function";
81
473
        case Value::OBJECT: return "object";
82
1.17k
        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.16k
    }
88
3.16k
}
89
90
/** Convert the value's type into a string, for error messages. */
91
std::string type_str(const Value &v)
92
1.13k
{
93
1.13k
    return type_str(v.t);
94
1.13k
}
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
10.1M
    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
139M
        : HeapEntity(THUNK), filled(false), name(name), self(self), offset(offset), body(body)
139
139M
    {
140
139M
    }
141
142
    void fill(const Value &v)
143
83.4M
    {
144
83.4M
        content = v;
145
83.4M
        filled = true;
146
83.4M
        self = nullptr;
147
83.4M
        upValues.clear();
148
83.4M
    }
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.32M
        : HeapEntity(ARRAY), elements(elements)
158
3.32M
    {
159
3.32M
    }
160
};
161
162
/** Supertype of all objects that are not super objects or extended objects.  */
163
struct HeapLeafObject : public HeapObject {
164
5.88M
    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.88M
        : HeapLeafObject(SIMPLE_OBJECT), upValues(up_values), fields(fields), asserts(asserts)
195
5.88M
    {
196
5.88M
    }
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.25M
        : HeapObject(EXTENDED_OBJECT), left(left), right(right)
209
4.25M
    {
210
4.25M
    }
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
57.1M
        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
34.8M
        : HeapEntity(CLOSURE),
268
34.8M
          upValues(up_values),
269
34.8M
          self(self),
270
34.8M
          offset(offset),
271
34.8M
          params(params),
272
34.8M
          body(body),
273
34.8M
          builtinName(builtin_name)
274
34.8M
    {
275
34.8M
    }
276
};
277
278
/** Stores a simple string on the heap. */
279
struct HeapString : public HeapEntity {
280
    const UString value;
281
124M
    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
273M
    {
323
273M
        vec.push_back(v);
324
273M
    }
325
326
   public:
327
    Heap(unsigned gc_tune_min_objects, double gc_tune_growth_trigger)
328
9.81k
        : gcTuneMinObjects(gc_tune_min_objects),
329
9.81k
          gcTuneGrowthTrigger(gc_tune_growth_trigger),
330
9.81k
          lastMark(0),
331
9.81k
          lastNumEntities(0),
332
9.81k
          numEntities(0)
333
9.81k
    {
334
9.81k
    }
335
336
    ~Heap(void)
337
9.81k
    {
338
        // Nothing is marked, everything will be collected.
339
9.81k
        sweep();
340
9.81k
    }
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.7M
            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
263M
    {
352
263M
        assert(from != nullptr);
353
263M
        const GarbageCollectionMark thisMark = lastMark + 1;
354
263M
        struct State {
355
263M
            HeapEntity *ent;
356
263M
            std::vector<HeapEntity *> children;
357
537M
            State(HeapEntity *ent) : ent(ent) {}
358
263M
        };
359
360
263M
        std::vector<State> stack;
361
263M
        stack.emplace_back(from);
362
363
1.07G
        while (stack.size() > 0) {
364
811M
            size_t curr_index = stack.size() - 1;
365
811M
            State &s = stack[curr_index];
366
811M
            HeapEntity *curr = s.ent;
367
811M
            if (curr->mark != thisMark) {
368
208M
                curr->mark = thisMark;
369
370
208M
                switch(curr->type) {
371
30.0M
                    case HeapEntity::SIMPLE_OBJECT: {
372
30.0M
                        assert(dynamic_cast<HeapSimpleObject *>(curr));
373
30.0M
                        auto *obj = static_cast<HeapSimpleObject *>(curr);
374
30.0M
                        for (auto upv : obj->upValues)
375
24.5M
                            addIfHeapEntity(upv.second, s.children);
376
30.0M
                        break;
377
30.0M
                    }
378
20.6M
                    case HeapEntity::EXTENDED_OBJECT: {
379
20.6M
                        assert(dynamic_cast<HeapExtendedObject *>(curr));
380
20.6M
                        auto *obj = static_cast<HeapExtendedObject *>(curr);
381
20.6M
                        addIfHeapEntity(obj->left, s.children);
382
20.6M
                        addIfHeapEntity(obj->right, s.children);
383
20.6M
                        break;
384
20.6M
                    }
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.65M
                    case HeapEntity::ARRAY: {
395
3.65M
                        assert(dynamic_cast<HeapArray *>(curr));
396
3.65M
                        auto *arr = static_cast<HeapArray *>(curr);
397
3.65M
                        for (auto el : arr->elements)
398
39.5M
                            addIfHeapEntity(el, s.children);
399
3.65M
                        break;
400
3.65M
                    }
401
5.66M
                    case HeapEntity::CLOSURE: {
402
5.66M
                        assert(dynamic_cast<HeapClosure *>(curr));
403
5.66M
                        auto *func = static_cast<HeapClosure *>(curr);
404
5.66M
                        for (auto upv : func->upValues)
405
13.2M
                            addIfHeapEntity(upv.second, s.children);
406
5.66M
                        if (func->self)
407
4.91M
                            addIfHeapEntity(func->self, s.children);
408
5.66M
                        break;
409
5.66M
                    }
410
140M
                    case HeapEntity::THUNK: {
411
140M
                        assert(dynamic_cast<HeapThunk *>(curr));
412
140M
                        auto *thunk = static_cast<HeapThunk *>(curr);
413
140M
                        if (thunk->filled) {
414
34.2M
                            if (thunk->content.isHeap())
415
24.1M
                                addIfHeapEntity(thunk->content.v.h, s.children);
416
105M
                        } else {
417
105M
                            for (auto upv : thunk->upValues)
418
24.5M
                                addIfHeapEntity(upv.second, s.children);
419
105M
                            if (thunk->self)
420
101M
                                addIfHeapEntity(thunk->self, s.children);
421
105M
                        }
422
140M
                        break;
423
140M
                    }
424
8.19M
                    case HeapEntity::STRING:
425
8.19M
                        assert(dynamic_cast<HeapString *>(curr));
426
8.19M
                        break;
427
8.19M
                    default:
428
0
                        assert(false);
429
0
                        break;
430
208M
                }
431
208M
            }
432
433
811M
            if (s.children.size() > 0) {
434
273M
                HeapEntity *next = s.children[s.children.size() - 1];
435
273M
                s.children.pop_back();
436
273M
                stack.emplace_back(next);  // CAUTION: s invalidated here
437
537M
            } else {
438
537M
                stack.pop_back();  // CAUTION: s invalidated here
439
537M
            }
440
811M
        }
441
263M
    }
442
443
    /** Delete everything that was not marked since the last collection. */
444
    void sweep(void)
445
373k
    {
446
373k
        lastMark++;
447
        // Heap shrinks during this loop.  Do not cache entities.size().
448
521M
        for (unsigned long i = 0; i < entities.size(); ++i) {
449
521M
            HeapEntity *x = entities[i];
450
521M
            if (x->mark != lastMark) {
451
312M
                delete x;
452
312M
                if (i != entities.size() - 1) {
453
                    // Swap it with the back.
454
312M
                    entities[i] = entities[entities.size() - 1];
455
312M
                }
456
312M
                entities.pop_back();
457
312M
                --i;
458
312M
            }
459
521M
        }
460
373k
        lastNumEntities = numEntities = entities.size();
461
373k
    }
462
463
    /** Is it time to initiate a GC cycle? */
464
    bool checkHeap(void)
465
312M
    {
466
312M
        return numEntities > gcTuneMinObjects &&
467
312M
               numEntities > gcTuneGrowthTrigger * lastNumEntities;
468
312M
    }
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
312M
    {
478
312M
        T *r = new T(std::forward<Args>(args)...);
479
312M
        entities.push_back(r);
480
312M
        r->mark = lastMark;
481
312M
        numEntities = entities.size();
482
312M
        return r;
483
312M
    }
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.32M
    {
478
3.32M
        T *r = new T(std::forward<Args>(args)...);
479
3.32M
        entities.push_back(r);
480
3.32M
        r->mark = lastMark;
481
3.32M
        numEntities = entities.size();
482
3.32M
        return r;
483
3.32M
    }
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
124M
    {
478
124M
        T *r = new T(std::forward<Args>(args)...);
479
124M
        entities.push_back(r);
480
124M
        r->mark = lastMark;
481
124M
        numEntities = entities.size();
482
124M
        return r;
483
124M
    }
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.37M
    {
478
1.37M
        T *r = new T(std::forward<Args>(args)...);
479
1.37M
        entities.push_back(r);
480
1.37M
        r->mark = lastMark;
481
1.37M
        numEntities = entities.size();
482
1.37M
        return r;
483
1.37M
    }
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
28.3M
    {
478
28.3M
        T *r = new T(std::forward<Args>(args)...);
479
28.3M
        entities.push_back(r);
480
28.3M
        r->mark = lastMark;
481
28.3M
        numEntities = entities.size();
482
28.3M
        return r;
483
28.3M
    }
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
9.81k
    {
478
9.81k
        T *r = new T(std::forward<Args>(args)...);
479
9.81k
        entities.push_back(r);
480
9.81k
        r->mark = lastMark;
481
9.81k
        numEntities = entities.size();
482
9.81k
        return r;
483
9.81k
    }
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.56M
    {
478
1.56M
        T *r = new T(std::forward<Args>(args)...);
479
1.56M
        entities.push_back(r);
480
1.56M
        r->mark = lastMark;
481
1.56M
        numEntities = entities.size();
482
1.56M
        return r;
483
1.56M
    }
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
74.8M
    {
478
74.8M
        T *r = new T(std::forward<Args>(args)...);
479
74.8M
        entities.push_back(r);
480
74.8M
        r->mark = lastMark;
481
74.8M
        numEntities = entities.size();
482
74.8M
        return r;
483
74.8M
    }
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
6.55M
    {
478
6.55M
        T *r = new T(std::forward<Args>(args)...);
479
6.55M
        entities.push_back(r);
480
6.55M
        r->mark = lastMark;
481
6.55M
        numEntities = entities.size();
482
6.55M
        return r;
483
6.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
477
60.6M
    {
478
60.6M
        T *r = new T(std::forward<Args>(args)...);
479
60.6M
        entities.push_back(r);
480
60.6M
        r->mark = lastMark;
481
60.6M
        numEntities = entities.size();
482
60.6M
        return r;
483
60.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.88M
    {
478
5.88M
        T *r = new T(std::forward<Args>(args)...);
479
5.88M
        entities.push_back(r);
480
5.88M
        r->mark = lastMark;
481
5.88M
        numEntities = entities.size();
482
5.88M
        return r;
483
5.88M
    }
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
250
    {
478
250
        T *r = new T(std::forward<Args>(args)...);
479
250
        entities.push_back(r);
480
250
        r->mark = lastMark;
481
250
        numEntities = entities.size();
482
250
        return r;
483
250
    }
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.25M
    {
478
4.25M
        T *r = new T(std::forward<Args>(args)...);
479
4.25M
        entities.push_back(r);
480
4.25M
        r->mark = lastMark;
481
4.25M
        numEntities = entities.size();
482
4.25M
        return r;
483
4.25M
    }
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
1.13M
    {
478
1.13M
        T *r = new T(std::forward<Args>(args)...);
479
1.13M
        entities.push_back(r);
480
1.13M
        r->mark = lastMark;
481
1.13M
        numEntities = entities.size();
482
1.13M
        return r;
483
1.13M
    }
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