/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 ¶ms, 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 |