File: | out/../deps/v8/src/torque/instance-type-generator.cc |
Warning: | line 240, column 5 Value stored to 'own_type_pending' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // Copyright 2019 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #include "src/torque/implementation-visitor.h" |
6 | |
7 | namespace v8 { |
8 | namespace internal { |
9 | namespace torque { |
10 | |
11 | namespace { |
12 | |
13 | // Contains all necessary state for a single class type during the process of |
14 | // assigning instance types, and provides a convenient way to access the list of |
15 | // types that inherit from this one. |
16 | struct InstanceTypeTree { |
17 | explicit InstanceTypeTree(const ClassType* type) |
18 | : type(type), |
19 | start(INT_MAX2147483647), |
20 | end(INT_MIN(-2147483647 -1)), |
21 | value(-1), |
22 | num_values(0), |
23 | num_own_values(0) {} |
24 | const ClassType* type; |
25 | std::vector<std::unique_ptr<InstanceTypeTree>> children; |
26 | int start; // Start of range for this and subclasses, or INT_MAX. |
27 | int end; // End of range for this and subclasses, or INT_MIN. |
28 | int value; // Assigned value for this class itself, or -1 when unassigned. |
29 | int num_values; // Number of values assigned for this and subclasses. |
30 | int num_own_values; // How many values this needs (not including subclasses). |
31 | }; |
32 | |
33 | // Assembles all class types into a tree, but doesn't yet attempt to assign |
34 | // instance types for them. |
35 | std::unique_ptr<InstanceTypeTree> BuildInstanceTypeTree() { |
36 | // First, build InstanceTypeTree instances for every class but don't try to |
37 | // attach them to their subclasses yet. |
38 | std::unordered_map<const ClassType*, InstanceTypeTree*> map_by_type; |
39 | std::vector<std::unique_ptr<InstanceTypeTree>> unparented_types; |
40 | for (auto& p : GlobalContext::AllDeclarables()) { |
41 | if (const TypeAlias* alias = TypeAlias::DynamicCast(p.get())) { |
42 | const Type* type = alias->type(); |
43 | const ClassType* class_type = ClassType::DynamicCast(type); |
44 | if (class_type == nullptr) { |
45 | continue; |
46 | } |
47 | auto& map_slot = map_by_type[class_type]; |
48 | if (map_slot != nullptr) { |
49 | continue; // We already encountered this type. |
50 | } |
51 | std::unique_ptr<InstanceTypeTree> type_tree = |
52 | std::make_unique<InstanceTypeTree>(class_type); |
53 | map_slot = type_tree.get(); |
54 | unparented_types.push_back(std::move(type_tree)); |
55 | } |
56 | } |
57 | |
58 | // Second, assemble them all into a tree following the inheritance hierarchy. |
59 | std::unique_ptr<InstanceTypeTree> root; |
60 | for (auto& type_tree : unparented_types) { |
61 | const ClassType* parent = type_tree->type->GetSuperClass(); |
62 | if (parent == nullptr) { |
63 | if (root != nullptr) |
64 | Error("Expected only one root class type. Found: ", root->type->name(), |
65 | " and ", type_tree->type->name()) |
66 | .Position(type_tree->type->GetPosition()); |
67 | root = std::move(type_tree); |
68 | } else { |
69 | map_by_type[parent]->children.push_back(std::move(type_tree)); |
70 | } |
71 | } |
72 | return root; |
73 | } |
74 | |
75 | // Propagates constraints about instance types from children to their parents. |
76 | void PropagateInstanceTypeConstraints(InstanceTypeTree* root) { |
77 | for (auto& child : root->children) { |
78 | PropagateInstanceTypeConstraints(child.get()); |
79 | if (child->start < root->start) root->start = child->start; |
80 | if (child->end > root->end) root->end = child->end; |
81 | root->num_values += child->num_values; |
82 | } |
83 | const InstanceTypeConstraints& constraints = |
84 | root->type->GetInstanceTypeConstraints(); |
85 | if (!root->type->IsAbstract() && !root->type->HasSameInstanceTypeAsParent()) { |
86 | root->num_own_values = 1; |
87 | } |
88 | root->num_values += root->num_own_values; |
89 | if (constraints.num_flags_bits != -1) { |
90 | // Children won't get any types assigned; must be done manually in C++. |
91 | root->children.clear(); |
92 | root->num_values = 1 << constraints.num_flags_bits; |
93 | root->num_own_values = root->num_values; |
94 | root->start = 0; |
95 | root->end = root->num_values - 1; |
96 | } |
97 | if (constraints.value != -1) { |
98 | if (root->num_own_values != 1) { |
99 | Error("Instance type value requested for abstract class ", |
100 | root->type->name()) |
101 | .Position(root->type->GetPosition()); |
102 | } |
103 | root->value = constraints.value; |
104 | if (constraints.value < root->start) root->start = constraints.value; |
105 | if (constraints.value > root->end) root->end = constraints.value; |
106 | } |
107 | } |
108 | |
109 | // Assigns values for the type itself, not including any children. Returns the |
110 | // next available value. |
111 | int SelectOwnValues(InstanceTypeTree* root, int start_value) { |
112 | if (root->value == -1) { |
113 | root->value = start_value; |
114 | } else if (root->value < start_value) { |
115 | Error("Failed to assign instance type ", root->value, " to ", |
116 | root->type->name()) |
117 | .Position(root->type->GetPosition()); |
118 | } |
119 | return root->value + root->num_own_values; |
120 | } |
121 | |
122 | // Sorting function for types that don't have specific values they must include. |
123 | // Prioritizes bigger type ranges (those with more subtypes) first, and |
124 | // then sorts alphabetically within each size category. |
125 | struct CompareUnconstrainedTypes { |
126 | constexpr bool operator()(const InstanceTypeTree* a, |
127 | const InstanceTypeTree* b) const { |
128 | return (a->num_values > b->num_values) |
129 | ? true |
130 | : (a->num_values < b->num_values) |
131 | ? false |
132 | : std::less<std::string>()(a->type->name(), |
133 | b->type->name()); |
134 | } |
135 | }; |
136 | |
137 | // Assigns concrete values for every instance type range, and sorts the children |
138 | // at each layer of the tree into increasing order. Appends the newly-assigned |
139 | // tree to the destination vector. Returns the first unassigned value after |
140 | // those that have been used. |
141 | int SolveInstanceTypeConstraints( |
142 | std::unique_ptr<InstanceTypeTree> root, int start_value, |
143 | std::vector<std::unique_ptr<InstanceTypeTree>>* destination) { |
144 | if (root->start < start_value) { |
145 | Error("Failed to assign instance type ", root->start, " to ", |
146 | root->type->name()) |
147 | .Position(root->type->GetPosition()); |
148 | } |
149 | |
150 | // First, separate the children into four groups: |
151 | // - The one child that must go first, if it exists; |
152 | // - Children with specific value requirements ("constrained"); |
153 | // - Children without specific value requirements ("unconstrained"); |
154 | // - The one child that must go last, if it exists. |
155 | std::unique_ptr<InstanceTypeTree> lowest_child; |
156 | std::unique_ptr<InstanceTypeTree> highest_child; |
157 | std::multimap<int, std::unique_ptr<InstanceTypeTree>> |
158 | constrained_children_by_start; |
159 | // Using std::map because you can't std::move out of a std::set until C++17. |
160 | std::map<InstanceTypeTree*, std::unique_ptr<InstanceTypeTree>, |
161 | CompareUnconstrainedTypes> |
162 | unconstrained_children_by_size; |
163 | for (auto& child : root->children) { |
164 | if (child->type->IsHighestInstanceTypeWithinParent()) { |
165 | if (highest_child) { |
166 | Error("Two classes requested to be the highest instance type: ", |
167 | highest_child->type->name(), " and ", child->type->name(), |
168 | " within range for parent class ", root->type->name()) |
169 | .Position(child->type->GetPosition()); |
170 | } |
171 | if (child->type->IsLowestInstanceTypeWithinParent()) { |
172 | Error( |
173 | "Class requested to be both highest and lowest instance type " |
174 | "within its parent range: ", |
175 | child->type->name()) |
176 | .Position(child->type->GetPosition()); |
177 | } |
178 | highest_child = std::move(child); |
179 | } else if (child->type->IsLowestInstanceTypeWithinParent()) { |
180 | if (lowest_child) { |
181 | Error("Two classes requested to be the lowest instance type: ", |
182 | lowest_child->type->name(), " and ", child->type->name(), |
183 | " within range for parent class ", root->type->name()) |
184 | .Position(child->type->GetPosition()); |
185 | } |
186 | lowest_child = std::move(child); |
187 | } else if (child->start > child->end) { |
188 | unconstrained_children_by_size.insert( |
189 | std::make_pair(child.get(), std::move(child))); |
190 | } else { |
191 | constrained_children_by_start.insert( |
192 | std::make_pair(child->start, std::move(child))); |
193 | } |
194 | } |
195 | root->children.clear(); |
196 | |
197 | bool own_type_pending = root->num_own_values > 0; |
198 | |
199 | // Second, iterate and place the children in ascending order. |
200 | if (lowest_child != nullptr) { |
201 | start_value = SolveInstanceTypeConstraints(std::move(lowest_child), |
202 | start_value, &root->children); |
203 | } |
204 | for (auto& constrained_child_pair : constrained_children_by_start) { |
205 | // Select the next constrained child type in ascending order. |
206 | std::unique_ptr<InstanceTypeTree> constrained_child = |
207 | std::move(constrained_child_pair.second); |
208 | |
209 | // Try to place the root type before the constrained child type if it fits. |
210 | if (own_type_pending) { |
211 | if ((root->value != -1 && root->value < constrained_child->start) || |
212 | (root->value == -1 && |
213 | start_value + root->num_own_values <= constrained_child->start)) { |
214 | start_value = SelectOwnValues(root.get(), start_value); |
215 | own_type_pending = false; |
216 | } |
217 | } |
218 | |
219 | // Try to find any unconstrained children that fit before the constrained |
220 | // one. This simple greedy algorithm just puts the biggest unconstrained |
221 | // children in first, which might not fill the space as efficiently as |
222 | // possible but is good enough for our needs. |
223 | for (auto it = unconstrained_children_by_size.begin(); |
224 | it != unconstrained_children_by_size.end();) { |
225 | if (it->second->num_values + start_value <= constrained_child->start) { |
226 | start_value = SolveInstanceTypeConstraints( |
227 | std::move(it->second), start_value, &root->children); |
228 | it = unconstrained_children_by_size.erase(it); |
229 | } else { |
230 | ++it; |
231 | } |
232 | } |
233 | |
234 | // Place the constrained child type. |
235 | start_value = SolveInstanceTypeConstraints(std::move(constrained_child), |
236 | start_value, &root->children); |
237 | } |
238 | if (own_type_pending) { |
239 | start_value = SelectOwnValues(root.get(), start_value); |
240 | own_type_pending = false; |
Value stored to 'own_type_pending' is never read | |
241 | } |
242 | for (auto& child_pair : unconstrained_children_by_size) { |
243 | start_value = SolveInstanceTypeConstraints(std::move(child_pair.second), |
244 | start_value, &root->children); |
245 | } |
246 | if (highest_child != nullptr) { |
247 | start_value = SolveInstanceTypeConstraints(std::move(highest_child), |
248 | start_value, &root->children); |
249 | } |
250 | |
251 | // Finally, set the range for this class to include all placed subclasses. |
252 | root->end = start_value - 1; |
253 | root->start = |
254 | root->children.empty() ? start_value : root->children.front()->start; |
255 | if (root->value != -1 && root->value < root->start) { |
256 | root->start = root->value; |
257 | } |
258 | root->num_values = root->end - root->start + 1; |
259 | root->type->InitializeInstanceTypes( |
260 | root->value == -1 ? base::Optional<int>{} : root->value, |
261 | std::make_pair(root->start, root->end)); |
262 | |
263 | if (root->num_values > 0) { |
264 | destination->push_back(std::move(root)); |
265 | } |
266 | return start_value; |
267 | } |
268 | |
269 | std::unique_ptr<InstanceTypeTree> SolveInstanceTypeConstraints( |
270 | std::unique_ptr<InstanceTypeTree> root) { |
271 | std::vector<std::unique_ptr<InstanceTypeTree>> destination; |
272 | SolveInstanceTypeConstraints(std::move(root), 0, &destination); |
273 | return destination.empty() ? nullptr : std::move(destination.front()); |
274 | } |
275 | |
276 | std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() { |
277 | std::unique_ptr<InstanceTypeTree> root = BuildInstanceTypeTree(); |
278 | if (root != nullptr) { |
279 | PropagateInstanceTypeConstraints(root.get()); |
280 | root = SolveInstanceTypeConstraints(std::move(root)); |
281 | } |
282 | return root; |
283 | } |
284 | |
285 | // Prints items in macro lists for the given type and its descendants. |
286 | // - definitions: This list is pairs of instance type name and assigned value, |
287 | // such as V(ODDBALL_TYPE, 67). It includes FIRST_* and LAST_* items for each |
288 | // type that has more than one associated InstanceType. Items within those |
289 | // ranges are indented for readability. |
290 | // - values: This list is just instance type names, like V(ODDBALL_TYPE). It |
291 | // does not include any FIRST_* and LAST_* range markers. |
292 | // - fully_defined_single_instance_types: This list is pairs of class name and |
293 | // instance type, for classes which have defined layouts and a single |
294 | // corresponding instance type. |
295 | // - fully_defined_multiple_instance_types: This list is pairs of class name and |
296 | // instance type, for classes which have defined layouts and subclasses. |
297 | // - only_declared_single_instance_types: This list is pairs of class name and |
298 | // instance type, for classes which have a single corresponding instance type |
299 | // and do not have layout definitions in Torque. |
300 | // - only_declared_multiple_instance_types: This list is pairs of class name and |
301 | // instance type, for classes which have subclasses but also have a single |
302 | // corresponding instance type, and do not have layout definitions in Torque. |
303 | // - fully_defined_range_instance_types: This list is triples of class name, |
304 | // first instance type, and last instance type, for classes which have defined |
305 | // layouts and multiple corresponding instance types. |
306 | // - only_declared_range_instance_types: This list is triples of class name, |
307 | // first instance type, and last instance type, for classes which have |
308 | // multiple corresponding instance types and do not have layout definitions in |
309 | // Torque. |
310 | void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions, |
311 | std::ostream& values, |
312 | std::ostream& fully_defined_single_instance_types, |
313 | std::ostream& fully_defined_multiple_instance_types, |
314 | std::ostream& only_declared_single_instance_types, |
315 | std::ostream& only_declared_multiple_instance_types, |
316 | std::ostream& fully_defined_range_instance_types, |
317 | std::ostream& only_declared_range_instance_types, |
318 | const std::string& indent) { |
319 | std::string type_name = |
320 | CapifyStringWithUnderscores(root->type->name()) + "_TYPE"; |
321 | std::string inner_indent = indent; |
322 | |
323 | if (root->num_values > 1) { |
324 | definitions << indent << "V(FIRST_" << type_name << ", " << root->start |
325 | << ") \\\n"; |
326 | inner_indent += " "; |
327 | } |
328 | if (root->num_own_values == 1) { |
329 | definitions << inner_indent << "V(" << type_name << ", " << root->value |
330 | << ") /* " << root->type->GetPosition() << " */\\\n"; |
331 | values << " V(" << type_name << ") /* " << root->type->GetPosition() |
332 | << " */\\\n"; |
333 | std::ostream& type_checker_list = |
334 | root->type->HasUndefinedLayout() |
335 | ? (root->num_values == 1 ? only_declared_single_instance_types |
336 | : only_declared_multiple_instance_types) |
337 | : (root->num_values == 1 ? fully_defined_single_instance_types |
338 | : fully_defined_multiple_instance_types); |
339 | type_checker_list << " V(" << root->type->name() << ", " << type_name |
340 | << ") /* " << root->type->GetPosition() << " */ \\\n"; |
341 | } |
342 | for (auto& child : root->children) { |
343 | PrintInstanceTypes(child.get(), definitions, values, |
344 | fully_defined_single_instance_types, |
345 | fully_defined_multiple_instance_types, |
346 | only_declared_single_instance_types, |
347 | only_declared_multiple_instance_types, |
348 | fully_defined_range_instance_types, |
349 | only_declared_range_instance_types, inner_indent); |
350 | } |
351 | if (root->num_values > 1) { |
352 | // We can't emit LAST_STRING_TYPE because it's not a valid flags |
353 | // combination. So if the class type has multiple own values, which only |
354 | // happens when using ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, then omit |
355 | // the end marker. |
356 | if (root->num_own_values <= 1) { |
357 | definitions << indent << "V(LAST_" << type_name << ", " << root->end |
358 | << ") \\\n"; |
359 | } |
360 | |
361 | // Only output the instance type range for things other than the root type. |
362 | if (root->type->GetSuperClass() != nullptr) { |
363 | std::ostream& range_instance_types = |
364 | root->type->HasUndefinedLayout() ? only_declared_range_instance_types |
365 | : fully_defined_range_instance_types; |
366 | range_instance_types << " V(" << root->type->name() << ", FIRST_" |
367 | << type_name << ", LAST_" << type_name << ") \\\n"; |
368 | } |
369 | } |
370 | } |
371 | |
372 | } // namespace |
373 | |
374 | void ImplementationVisitor::GenerateInstanceTypes( |
375 | const std::string& output_directory) { |
376 | std::stringstream header; |
377 | std::string file_name = "instance-types.h"; |
378 | { |
379 | IncludeGuardScope guard(header, file_name); |
380 | |
381 | header << "// Instance types for all classes except for those that use " |
382 | "InstanceType as flags.\n"; |
383 | header << "#define TORQUE_ASSIGNED_INSTANCE_TYPES(V) \\\n"; |
384 | std::unique_ptr<InstanceTypeTree> instance_types = AssignInstanceTypes(); |
385 | std::stringstream values_list; |
386 | std::stringstream fully_defined_single_instance_types; |
387 | std::stringstream fully_defined_multiple_instance_types; |
388 | std::stringstream only_declared_single_instance_types; |
389 | std::stringstream only_declared_multiple_instance_types; |
390 | std::stringstream fully_defined_range_instance_types; |
391 | std::stringstream only_declared_range_instance_types; |
392 | if (instance_types != nullptr) { |
393 | PrintInstanceTypes(instance_types.get(), header, values_list, |
394 | fully_defined_single_instance_types, |
395 | fully_defined_multiple_instance_types, |
396 | only_declared_single_instance_types, |
397 | only_declared_multiple_instance_types, |
398 | fully_defined_range_instance_types, |
399 | only_declared_range_instance_types, " "); |
400 | } |
401 | header << "\n"; |
402 | |
403 | header << "// Instance types for all classes except for those that use\n"; |
404 | header << "// InstanceType as flags.\n"; |
405 | header << "#define TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(V) \\\n"; |
406 | header << values_list.str(); |
407 | header << "\n"; |
408 | |
409 | header << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that have\n"; |
410 | header << "// full Torque definitions.\n"; |
411 | header << "#define TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(V) \\\n"; |
412 | header << fully_defined_single_instance_types.str(); |
413 | header << "\n"; |
414 | |
415 | header << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that have\n"; |
416 | header << "// full Torque definitions and subclasses.\n"; |
417 | header << "#define TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(V) \\\n"; |
418 | header << fully_defined_multiple_instance_types.str(); |
419 | header << "\n"; |
420 | |
421 | header << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that are\n"; |
422 | header << "// declared but not defined in Torque. These classes may\n"; |
423 | header << "// correspond with actual C++ classes, but they are not\n"; |
424 | header << "// guaranteed to.\n"; |
425 | header << "#define TORQUE_INSTANCE_CHECKERS_SINGLE_ONLY_DECLARED(V) \\\n"; |
426 | header << only_declared_single_instance_types.str(); |
427 | header << "\n"; |
428 | |
429 | header << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that are\n"; |
430 | header << "// declared but not defined in Torque, and have subclasses.\n"; |
431 | header << "// These classes may correspond with actual C++ classes, but\n"; |
432 | header << "// they are not guaranteed to.\n"; |
433 | header << "#define TORQUE_INSTANCE_CHECKERS_MULTIPLE_ONLY_DECLARED(V) \\\n"; |
434 | header << only_declared_multiple_instance_types.str(); |
435 | header << "\n"; |
436 | |
437 | header << "// Triples of (ClassName, FIRST_TYPE, LAST_TYPE) for classes\n"; |
438 | header << "// that have full Torque definitions.\n"; |
439 | header << "#define TORQUE_INSTANCE_CHECKERS_RANGE_FULLY_DEFINED(V) \\\n"; |
440 | header << fully_defined_range_instance_types.str(); |
441 | header << "\n"; |
442 | |
443 | header << "// Triples of (ClassName, FIRST_TYPE, LAST_TYPE) for classes\n"; |
444 | header << "// that are declared but not defined in Torque. These classes\n"; |
445 | header << "// may correspond with actual C++ classes, but they are not\n"; |
446 | header << "// guaranteed to.\n"; |
447 | header << "#define TORQUE_INSTANCE_CHECKERS_RANGE_ONLY_DECLARED(V) \\\n"; |
448 | header << only_declared_range_instance_types.str(); |
449 | header << "\n"; |
450 | |
451 | std::stringstream torque_defined_class_list; |
452 | std::stringstream torque_defined_varsize_instance_type_list; |
453 | std::stringstream torque_defined_fixed_instance_type_list; |
454 | std::stringstream torque_defined_map_csa_list; |
455 | std::stringstream torque_defined_map_root_list; |
456 | |
457 | for (const ClassType* type : TypeOracle::GetClasses()) { |
458 | std::string upper_case_name = type->name(); |
459 | std::string lower_case_name = SnakeifyString(type->name()); |
460 | std::string instance_type_name = |
461 | CapifyStringWithUnderscores(type->name()) + "_TYPE"; |
462 | |
463 | if (!type->IsExtern()) { |
464 | torque_defined_class_list << " V(" << upper_case_name << ") \\\n"; |
465 | } |
466 | |
467 | if (type->ShouldGenerateUniqueMap()) { |
468 | torque_defined_map_csa_list << " V(_, " << upper_case_name << "Map, " |
469 | << lower_case_name << "_map, " |
470 | << upper_case_name << ") \\\n"; |
471 | torque_defined_map_root_list << " V(Map, " << lower_case_name |
472 | << "_map, " << upper_case_name |
473 | << "Map) \\\n"; |
474 | std::stringstream& list = |
475 | type->HasStaticSize() ? torque_defined_fixed_instance_type_list |
476 | : torque_defined_varsize_instance_type_list; |
477 | list << " V(" << instance_type_name << ", " << upper_case_name << ", " |
478 | << lower_case_name << ") \\\n"; |
479 | } |
480 | } |
481 | |
482 | header << "// Fully Torque-defined classes (both internal and exported).\n"; |
483 | header << "#define TORQUE_DEFINED_CLASS_LIST(V) \\\n"; |
484 | header << torque_defined_class_list.str(); |
485 | header << "\n"; |
486 | header << "#define TORQUE_DEFINED_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n"; |
487 | header << torque_defined_varsize_instance_type_list.str(); |
488 | header << "\n"; |
489 | header << "#define TORQUE_DEFINED_FIXED_INSTANCE_TYPE_LIST(V) \\\n"; |
490 | header << torque_defined_fixed_instance_type_list.str(); |
491 | header << "\n"; |
492 | header << "#define TORQUE_DEFINED_INSTANCE_TYPE_LIST(V) \\\n"; |
493 | header << " TORQUE_DEFINED_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n"; |
494 | header << " TORQUE_DEFINED_FIXED_INSTANCE_TYPE_LIST(V) \\\n"; |
495 | header << "\n"; |
496 | header << "#define TORQUE_DEFINED_MAP_CSA_LIST_GENERATOR(V, _) \\\n"; |
497 | header << torque_defined_map_csa_list.str(); |
498 | header << "\n"; |
499 | header << "#define TORQUE_DEFINED_MAP_ROOT_LIST(V) \\\n"; |
500 | header << torque_defined_map_root_list.str(); |
501 | header << "\n"; |
502 | } |
503 | std::string output_header_path = output_directory + "/" + file_name; |
504 | WriteFile(output_header_path, header.str()); |
505 | |
506 | GlobalContext::SetInstanceTypesInitialized(); |
507 | } |
508 | |
509 | } // namespace torque |
510 | } // namespace internal |
511 | } // namespace v8 |