Coverage Report

Created: 2022-03-15 07:22

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