v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
types.cc
Go to the documentation of this file.
1// Copyright 2017 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/types.h"
6
7#include <cmath>
8#include <iostream>
9#include <optional>
10
11#include "src/base/bits.h"
12#include "src/torque/ast.h"
18
19namespace v8::internal::torque {
20
21// This custom copy constructor doesn't copy aliases_ and id_ because they
22// should be distinct for each type.
24 : TypeBase(other),
25 parent_(other.parent_),
26 aliases_(),
28 constexpr_version_(other.constexpr_version_) {}
30 MaybeSpecializationKey specialized_from)
31 : TypeBase(kind),
32 parent_(parent),
33 id_(TypeOracle::FreshTypeId()),
34 specialized_from_(specialized_from),
35 constexpr_version_(nullptr) {}
36
37std::string Type::ToString() const {
38 if (aliases_.empty())
40 if (aliases_.size() == 1) return *aliases_.begin();
41 std::stringstream result;
42 int i = 0;
43 for (const std::string& alias : aliases_) {
44 if (i == 0) {
45 result << alias << " (aka. ";
46 } else if (i == 1) {
47 result << alias;
48 } else {
49 result << ", " << alias;
50 }
51 ++i;
52 }
53 result << ")";
54 return result.str();
55}
56
57std::string Type::SimpleName() const {
58 if (aliases_.empty()) {
59 std::stringstream result;
61 if (GetSpecializedFrom()) {
62 for (const Type* t : GetSpecializedFrom()->specialized_types) {
63 result << "_" << t->SimpleName();
64 }
65 }
66 return result.str();
67 }
68 return *aliases_.begin();
69}
70
72 const std::string& type_name) const {
73 switch (kind) {
75 return "Handle<" + type_name + ">";
77 return "DirectHandle<" + type_name + ">";
78 }
79}
80
81// TODO(danno): HandlifiedCppTypeName should be used universally in Torque
82// where the C++ type of a Torque object is required.
91
92std::string Type::TagglifiedCppTypeName() const {
93 if (IsSubtypeOf(TypeOracle::GetSmiType())) return "int";
95 return "Tagged<" + GetConstexprGeneratedTypeName() + ">";
96 } else {
98 }
99}
100
101bool Type::IsSubtypeOf(const Type* supertype) const {
102 if (supertype->IsTopType()) return true;
103 if (IsNever()) return true;
104 if (const UnionType* union_type = UnionType::DynamicCast(supertype)) {
105 return union_type->IsSupertypeOf(this);
106 }
107 const Type* subtype = this;
108 while (subtype != nullptr) {
109 if (subtype == supertype) return true;
110 subtype = subtype->parent();
111 }
112 return false;
113}
114
116 const Type* constexpr_version = ConstexprVersion();
117 if (constexpr_version == nullptr) {
118 Error("Type '", ToString(), "' requires a constexpr representation");
119 return "";
120 }
121 return constexpr_version->GetGeneratedTypeName();
122}
123
124std::optional<const ClassType*> Type::ClassSupertype() const {
125 for (const Type* t = this; t != nullptr; t = t->parent()) {
126 if (auto* class_type = ClassType::DynamicCast(t)) {
127 return class_type;
128 }
129 }
130 return std::nullopt;
131}
132
133std::optional<const StructType*> Type::StructSupertype() const {
134 for (const Type* t = this; t != nullptr; t = t->parent()) {
135 if (auto* struct_type = StructType::DynamicCast(t)) {
136 return struct_type;
137 }
138 }
139 return std::nullopt;
140}
141
142std::optional<const AggregateType*> Type::AggregateSupertype() const {
143 for (const Type* t = this; t != nullptr; t = t->parent()) {
144 if (auto* aggregate_type = AggregateType::DynamicCast(t)) {
145 return aggregate_type;
146 }
147 }
148 return std::nullopt;
149}
150
151// static
152const Type* Type::CommonSupertype(const Type* a, const Type* b) {
153 int diff = a->Depth() - b->Depth();
154 const Type* a_supertype = a;
155 const Type* b_supertype = b;
156 for (; diff > 0; --diff) a_supertype = a_supertype->parent();
157 for (; diff < 0; ++diff) b_supertype = b_supertype->parent();
158 while (a_supertype && b_supertype) {
159 if (a_supertype == b_supertype) return a_supertype;
160 a_supertype = a_supertype->parent();
161 b_supertype = b_supertype->parent();
162 }
163 ReportError("types " + a->ToString() + " and " + b->ToString() +
164 " have no common supertype");
165}
166
167int Type::Depth() const {
168 int result = 0;
169 for (const Type* current = parent_; current; current = current->parent_) {
170 ++result;
171 }
172 return result;
173}
174
175bool Type::IsAbstractName(const std::string& name) const {
176 if (!IsAbstractType()) return false;
177 return AbstractType::cast(this)->name() == name;
178}
179
180std::string Type::GetGeneratedTypeName() const {
181 std::string result = GetGeneratedTypeNameImpl();
182 if (result.empty() || result == "TNode<>") {
183 ReportError("Generated type is required for type '", ToString(),
184 "'. Use 'generates' clause in definition.");
185 }
186 return result;
187}
188
191 if (result.empty() || IsConstexpr()) {
192 ReportError("Generated TNode type is required for type '", ToString(),
193 "'. Use 'generates' clause in definition.");
194 }
195 return result;
196}
197
199 // A special case that is not very well represented by the "generates"
200 // syntax in the .tq files: Lazy<T> represents a std::function that
201 // produces a TNode of the wrapped type.
202 if (std::optional<const Type*> type_wrapped_in_lazy =
205 return "std::function<" + (*type_wrapped_in_lazy)->GetGeneratedTypeName() +
206 "()>";
207 }
208
209 if (generated_type_.empty()) {
210 return parent()->GetGeneratedTypeName();
211 }
212 return IsConstexpr() ? generated_type_ : "TNode<" + generated_type_ + ">";
213}
214
216 if (generated_type_.empty()) return parent()->GetGeneratedTNodeTypeName();
217 return generated_type_;
218}
219
220std::vector<TypeChecker> AbstractType::GetTypeCheckers() const {
221 if (UseParentTypeChecker()) return parent()->GetTypeCheckers();
222 std::string type_name = name();
223 if (auto strong_type =
225 auto strong_runtime_types = (*strong_type)->GetTypeCheckers();
226 std::vector<TypeChecker> result;
227 for (const TypeChecker& type : strong_runtime_types) {
228 // Generic parameter in Weak<T> should have already been checked to
229 // extend HeapObject, so it couldn't itself be another weak type.
230 DCHECK(type.weak_ref_to.empty());
231 result.push_back({type_name, type.type});
232 }
233 return result;
234 }
235 return {{type_name, ""}};
236}
237
239 std::stringstream result;
240 result << "builtin (";
242 result << ") => " << *return_type_;
243 return result.str();
244}
245
247 std::stringstream result;
248 result << "BuiltinPointer";
249 for (const Type* t : parameter_types_) {
250 result << "_" << t->SimpleName();
251 }
252 result << "_" << return_type_->SimpleName();
253 return result.str();
254}
255
256std::string UnionType::ToExplicitString() const {
257 std::stringstream result;
258 result << "(";
259 bool first = true;
260 for (const Type* t : types_) {
261 if (!first) {
262 result << " | ";
263 }
264 first = false;
265 result << *t;
266 }
267 result << ")";
268 return result.str();
269}
270
271std::string UnionType::SimpleNameImpl() const {
272 std::stringstream result;
273 bool first = true;
274 for (const Type* t : types_) {
275 if (!first) {
276 result << "_OR_";
277 }
278 first = false;
279 result << t->SimpleName();
280 }
281 return result.str();
282}
283
284// static
285void UnionType::InsertGeneratedTNodeTypeName(std::set<std::string>& names,
286 const Type* t) {
287 if (t->IsUnionType()) {
288 for (const Type* u : ((const UnionType*)t)->types_) {
289 names.insert(u->GetGeneratedTNodeTypeName());
290 }
291 } else {
292 names.insert(t->GetGeneratedTNodeTypeName());
293 }
294}
295
297 // For non-tagged unions, use the parent GetGeneratedTNodeTypeName.
298 for (const Type* t : types_) {
299 if (!t->IsSubtypeOf(TypeOracle::GetTaggedType())) {
300 return parent()->GetGeneratedTNodeTypeName();
301 }
302 }
303
304 std::string simple_name = SimpleName();
305 if (simple_name == "Object") return simple_name;
306 if (simple_name == "Number") return simple_name;
307 if (simple_name == "Numeric") return simple_name;
308 if (simple_name == "JSAny") return simple_name;
309 if (simple_name == "JSPrimitive") return simple_name;
310
311 std::set<std::string> names;
312 for (const Type* t : types_) {
314 }
315 std::stringstream result;
316 result << "Union<";
317 bool first = true;
318 for (std::string name : names) {
319 if (!first) {
320 result << ", ";
321 }
322 first = false;
323 result << name;
324 }
325 result << ">";
326 return result.str();
327}
328
329std::string UnionType::GetRuntimeType() const {
330 for (const Type* t : types_) {
331 if (!t->IsSubtypeOf(TypeOracle::GetTaggedType())) {
332 return parent()->GetRuntimeType();
333 }
334 }
335 return "Tagged<" + GetConstexprGeneratedTypeName() + ">";
336}
337
338// static
339void UnionType::InsertConstexprGeneratedTypeName(std::set<std::string>& names,
340 const Type* t) {
341 if (t->IsUnionType()) {
342 for (const Type* u : ((const UnionType*)t)->types_) {
343 names.insert(u->GetConstexprGeneratedTypeName());
344 }
345 } else {
346 names.insert(t->GetConstexprGeneratedTypeName());
347 }
348}
349
351 // For non-tagged unions, use the superclass GetConstexprGeneratedTypeName.
352 for (const Type* t : types_) {
353 if (!t->IsSubtypeOf(TypeOracle::GetTaggedType())) {
355 }
356 }
357
358 // Allow some aliased simple names to be used as-is.
359 std::string simple_name = SimpleName();
360 if (simple_name == "Object") return simple_name;
361 if (simple_name == "Number") return simple_name;
362 if (simple_name == "Numeric") return simple_name;
363 if (simple_name == "JSAny") return simple_name;
364 if (simple_name == "JSPrimitive") return simple_name;
365
366 // Deduplicate generated typenames and flatten unions.
367 std::set<std::string> names;
368 for (const Type* t : types_) {
370 }
371 std::stringstream result;
372 result << "Union<";
373 bool first = true;
374 for (std::string name : names) {
375 if (!first) {
376 result << ", ";
377 }
378 first = false;
379 result << name;
380 }
381 result << ">";
382 return result.str();
383}
384
385std::string UnionType::GetDebugType() const { return parent()->GetDebugType(); }
386
388 const Type* parent = nullptr;
389 for (const Type* t : types_) {
390 if (parent == nullptr) {
391 parent = t;
392 } else {
394 }
395 }
397}
398
399void UnionType::Subtract(const Type* t) {
400 for (auto it = types_.begin(); it != types_.end();) {
401 if ((*it)->IsSubtypeOf(t)) {
402 it = types_.erase(it);
403 } else {
404 ++it;
405 }
406 }
407 if (types_.empty()) types_.insert(TypeOracle::GetNeverType());
409}
410
411const Type* SubtractType(const Type* a, const Type* b) {
413 result.Subtract(b);
415}
416
418 return "bitfield struct " + name();
419}
420
421const BitField& BitFieldStructType::LookupField(const std::string& name) const {
422 for (const BitField& field : fields_) {
423 if (field.name_and_type.name == name) {
424 return field;
425 }
426 }
427 ReportError("Couldn't find bitfield ", name);
428}
429
431 // Check the aggregate hierarchy and currently defined class for duplicate
432 // field declarations.
433 auto hierarchy = GetHierarchy();
434 std::map<std::string, const AggregateType*> field_names;
435 for (const AggregateType* aggregate_type : hierarchy) {
436 for (const Field& field : aggregate_type->fields()) {
437 const std::string& field_name = field.name_and_type.name;
438 auto i = field_names.find(field_name);
439 if (i != field_names.end()) {
440 CurrentSourcePosition::Scope current_source_position(field.pos);
441 std::string aggregate_type_name =
442 aggregate_type->IsClassType() ? "class" : "struct";
443 if (i->second == this) {
444 ReportError(aggregate_type_name, " '", name(),
445 "' declares a field with the name '", field_name,
446 "' more than once");
447 } else {
448 ReportError(aggregate_type_name, " '", name(),
449 "' declares a field with the name '", field_name,
450 "' that masks an inherited field from class '",
451 i->second->name(), "'");
452 }
453 }
454 field_names[field_name] = aggregate_type;
455 }
456 }
457}
458
459std::vector<const AggregateType*> AggregateType::GetHierarchy() const {
460 if (!is_finalized_) Finalize();
461 std::vector<const AggregateType*> hierarchy;
462 const AggregateType* current_container_type = this;
463 while (current_container_type != nullptr) {
464 hierarchy.push_back(current_container_type);
465 current_container_type =
466 current_container_type->IsClassType()
467 ? ClassType::cast(current_container_type)->GetSuperClass()
468 : nullptr;
469 }
470 std::reverse(hierarchy.begin(), hierarchy.end());
471 return hierarchy;
472}
473
474bool AggregateType::HasField(const std::string& name) const {
475 if (!is_finalized_) Finalize();
476 for (auto& field : fields_) {
477 if (field.name_and_type.name == name) return true;
478 }
479 if (parent() != nullptr) {
480 if (auto parent_class = ClassType::DynamicCast(parent())) {
481 return parent_class->HasField(name);
482 }
483 }
484 return false;
485}
486
487const Field& AggregateType::LookupFieldInternal(const std::string& name) const {
488 for (auto& field : fields_) {
489 if (field.name_and_type.name == name) return field;
490 }
491 if (parent() != nullptr) {
492 if (auto parent_class = ClassType::DynamicCast(parent())) {
493 return parent_class->LookupField(name);
494 }
495 }
496 ReportError("no field ", name, " found in ", this->ToString());
497}
498
499const Field& AggregateType::LookupField(const std::string& name) const {
500 if (!is_finalized_) Finalize();
501 return LookupFieldInternal(name);
502}
503
505 MaybeSpecializationKey specialized_from)
506 : AggregateType(Kind::kStructType, nullptr, nspace, decl->name->value,
507 specialized_from),
508 decl_(decl) {
509 if (decl->flags & StructFlag::kExport) {
510 generated_type_name_ = "TorqueStruct" + name();
511 } else {
512 generated_type_name_ =
513 GlobalContext::MakeUniqueName("TorqueStruct" + SimpleName());
514 }
515}
516
519}
520
522 size_t result = 0;
523 for (const Field& field : fields()) {
524 result += std::get<0>(field.GetFieldSizeInformation());
525 }
526 return result;
527}
528
531 for (const Field& struct_field : fields()) {
532 const Type* field_type = struct_field.name_and_type.type;
533 if (field_type->IsSubtypeOf(TypeOracle::GetStrongTaggedType())) {
535 } else if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
537 } else if (auto field_as_struct = field_type->StructSupertype()) {
538 result |= (*field_as_struct)->ClassifyContents();
539 } else {
541 }
542 }
543 return result;
544}
545
546// static
547std::string Type::ComputeName(const std::string& basename,
548 MaybeSpecializationKey specialized_from) {
549 if (!specialized_from) return basename;
550 if (specialized_from->generic == TypeOracle::GetConstReferenceGeneric()) {
551 return torque::ToString("const &", *specialized_from->specialized_types[0]);
552 }
553 if (specialized_from->generic == TypeOracle::GetMutableReferenceGeneric()) {
554 return torque::ToString("&", *specialized_from->specialized_types[0]);
555 }
556 std::stringstream s;
557 s << basename << "<";
558 bool first = true;
559 for (auto t : specialized_from->specialized_types) {
560 if (!first) {
561 s << ", ";
562 }
563 s << t->ToString();
564 first = false;
565 }
566 s << ">";
567 return s.str();
568}
569
570std::string StructType::SimpleNameImpl() const { return decl_->name->value; }
571
572// static
573std::optional<const Type*> Type::MatchUnaryGeneric(const Type* type,
574 GenericType* generic) {
575 DCHECK_EQ(generic->generic_parameters().size(), 1);
576 if (!type->GetSpecializedFrom()) {
577 return std::nullopt;
578 }
579 auto& key = type->GetSpecializedFrom().value();
580 if (key.generic != generic || key.specialized_types.size() != 1) {
581 return std::nullopt;
582 }
583 return {key.specialized_types[0]};
584}
585
586std::vector<Method*> AggregateType::Methods(const std::string& name) const {
587 if (!is_finalized_) Finalize();
588 std::vector<Method*> result;
589 std::copy_if(methods_.begin(), methods_.end(), std::back_inserter(result),
590 [name](Macro* macro) { return macro->ReadableName() == name; });
591 if (result.empty() && parent() != nullptr) {
592 if (auto aggregate_parent = parent()->AggregateSupertype()) {
593 return (*aggregate_parent)->Methods(name);
594 }
595 }
596 return result;
597}
598
599std::string StructType::ToExplicitString() const { return "struct " + name(); }
600
602 if (is_finalized_) return;
603 {
604 CurrentScope::Scope scope_activator(nspace());
605 CurrentSourcePosition::Scope position_activator(decl_->pos);
607 }
608 is_finalized_ = true;
610}
611
612ClassType::ClassType(const Type* parent, Namespace* nspace,
613 const std::string& name, ClassFlags flags,
614 const std::string& generates, const ClassDeclaration* decl,
615 const TypeAlias* alias)
616 : AggregateType(Kind::kClassType, parent, nspace, name),
617 size_(ResidueClass::Unknown()),
618 flags_(flags),
619 generates_(generates),
620 decl_(decl),
621 alias_(alias) {}
622
624 return generates_;
625}
626
629 : "TNode<" + GetGeneratedTNodeTypeName() + ">";
630}
631
632std::string ClassType::ToExplicitString() const { return "class " + name(); }
633
635 return (!IsExtern() || nspace()->IsDefaultNamespace()) && !IsAbstract();
636}
637
639 if (is_finalized_) return;
640 CurrentScope::Scope scope_activator(alias_->ParentScope());
641 CurrentSourcePosition::Scope position_activator(decl_->pos);
643 this->decl_);
644 is_finalized_ = true;
646}
647
648std::vector<Field> ClassType::ComputeAllFields() const {
649 std::vector<Field> all_fields;
650 const ClassType* super_class = this->GetSuperClass();
651 if (super_class) {
652 all_fields = super_class->ComputeAllFields();
653 }
654 const std::vector<Field>& fields = this->fields();
655 all_fields.insert(all_fields.end(), fields.begin(), fields.end());
656 return all_fields;
657}
658
659std::vector<Field> ClassType::ComputeHeaderFields() const {
660 std::vector<Field> result;
661 for (Field& field : ComputeAllFields()) {
662 if (field.index) break;
663 // The header is allowed to end with an optional padding field of size 0.
664 DCHECK(std::get<0>(field.GetFieldSizeInformation()) == 0 ||
665 *field.offset < header_size());
666 result.push_back(std::move(field));
667 }
668 return result;
669}
670
671std::vector<Field> ClassType::ComputeArrayFields() const {
672 std::vector<Field> result;
673 for (Field& field : ComputeAllFields()) {
674 if (!field.index) {
675 // The header is allowed to end with an optional padding field of size 0.
676 DCHECK(std::get<0>(field.GetFieldSizeInformation()) == 0 ||
677 *field.offset < header_size());
678 continue;
679 }
680 result.push_back(std::move(field));
681 }
682 return result;
683}
684
686 std::optional<int> own, std::optional<std::pair<int, int>> range) const {
687 DCHECK(!own_instance_type_.has_value());
688 DCHECK(!instance_type_range_.has_value());
689 own_instance_type_ = own;
690 instance_type_range_ = range;
691}
692
697
698std::optional<std::pair<int, int>> ClassType::InstanceTypeRange() const {
701}
702
703namespace {
704void ComputeSlotKindsHelper(std::vector<ObjectSlotKind>* slots,
705 size_t start_offset,
706 const std::vector<Field>& fields) {
707 size_t offset = start_offset;
708 for (const Field& field : fields) {
709 size_t field_size = std::get<0>(field.GetFieldSizeInformation());
710 // Support optional padding fields.
711 if (field_size == 0) continue;
712 size_t slot_index = offset / TargetArchitecture::TaggedSize();
713 // Rounding-up division to find the number of slots occupied by all the
714 // fields up to and including the current one.
715 size_t used_slots =
716 (offset + field_size + TargetArchitecture::TaggedSize() - 1) /
718 while (used_slots > slots->size()) {
719 slots->push_back(ObjectSlotKind::kNoPointer);
720 }
721 const Type* type = field.name_and_type.type;
722 if (auto struct_type = type->StructSupertype()) {
723 ComputeSlotKindsHelper(slots, offset, (*struct_type)->fields());
724 } else {
726 if (type->IsSubtypeOf(TypeOracle::GetObjectType())) {
727 if (field.custom_weak_marking) {
729 } else {
731 }
732 } else if (type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
733 DCHECK(!field.custom_weak_marking);
735 } else {
737 }
738 DCHECK(slots->at(slot_index) == ObjectSlotKind::kNoPointer);
739 slots->at(slot_index) = kind;
740 }
741
742 offset += field_size;
743 }
744}
745} // namespace
746
747std::vector<ObjectSlotKind> ClassType::ComputeHeaderSlotKinds() const {
748 std::vector<ObjectSlotKind> result;
749 std::vector<Field> header_fields = ComputeHeaderFields();
750 ComputeSlotKindsHelper(&result, 0, header_fields);
751 DCHECK_EQ(std::ceil(static_cast<double>(header_size()) /
753 result.size());
754 return result;
755}
756
757std::optional<ObjectSlotKind> ClassType::ComputeArraySlotKind() const {
758 std::vector<ObjectSlotKind> kinds;
759 ComputeSlotKindsHelper(&kinds, 0, ComputeArrayFields());
760 if (kinds.empty()) return std::nullopt;
761 std::sort(kinds.begin(), kinds.end());
762 if (kinds.front() == kinds.back()) return {kinds.front()};
763 if (kinds.front() == ObjectSlotKind::kStrongPointer &&
764 kinds.back() == ObjectSlotKind::kMaybeObjectPointer) {
766 }
767 Error("Array fields mix types with different GC visitation requirements.")
768 .Throw();
769}
770
772 const auto header_slot_kinds = ComputeHeaderSlotKinds();
773 DCHECK_GE(header_slot_kinds.size(), 1);
776 for (size_t i = 1; i < header_slot_kinds.size(); ++i) {
777 if (header_slot_kinds[i] != ObjectSlotKind::kNoPointer) return false;
778 }
779 if (auto slot = ComputeArraySlotKind()) {
780 if (*slot != ObjectSlotKind::kNoPointer) return false;
781 }
782 return true;
783}
784
786 for (const auto& field : fields_) {
787 if (field.index.has_value()) return true;
788 }
789 if (const ClassType* parent = GetSuperClass()) {
790 return parent->HasIndexedFieldsIncludingInParents();
791 }
792 return false;
793}
794
795const Field* ClassType::GetFieldPreceding(size_t field_index) const {
796 if (field_index > 0) {
797 return &fields_[field_index - 1];
798 }
799 if (const ClassType* parent = GetSuperClass()) {
800 return parent->GetFieldPreceding(parent->fields_.size());
801 }
802 return nullptr;
803}
804
806 for (const Field& field : fields_) {
807 if (f.name_and_type.name == field.name_and_type.name) return this;
808 }
809 return GetSuperClass()->GetClassDeclaringField(f);
810}
811
812std::string ClassType::GetSliceMacroName(const Field& field) const {
813 const ClassType* declarer = GetClassDeclaringField(field);
814 return "FieldSlice" + declarer->name() +
816}
817
819 bool at_or_after_indexed_field = false;
820 if (const ClassType* parent = GetSuperClass()) {
821 at_or_after_indexed_field = parent->HasIndexedFieldsIncludingInParents();
822 }
823 // For each field, construct AST snippets that implement a CSA accessor
824 // function. The implementation iterator will turn the snippets into code.
825 for (size_t field_index = 0; field_index < fields_.size(); ++field_index) {
826 Field& field = fields_[field_index];
828 continue;
829 }
830 at_or_after_indexed_field =
831 at_or_after_indexed_field || field.index.has_value();
832 CurrentSourcePosition::Scope position_activator(field.pos);
833
836
837 std::string camel_field_name = CamelifyString(field.name_and_type.name);
838
839 if (at_or_after_indexed_field) {
840 if (!field.index.has_value()) {
841 // There's no fundamental reason we couldn't generate functions to get
842 // references instead of slices, but it's not yet implemented.
844 "Torque doesn't yet support non-indexed fields after indexed "
845 "fields");
846 }
847
848 GenerateSliceAccessor(field_index);
849 }
850
851 // For now, only generate indexed accessors for simple types
852 if (field.index.has_value() && field.name_and_type.type->IsStructType()) {
853 continue;
854 }
855
856 // An explicit index is only used for indexed fields not marked as optional.
857 // Optional fields implicitly load or store item zero.
858 bool use_index = field.index && !field.index->optional;
859
860 // Load accessor
861 std::string load_macro_name = "Load" + this->name() + camel_field_name;
862 Signature load_signature;
863 load_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
864 load_signature.parameter_types.types.push_back(this);
865 if (use_index) {
866 load_signature.parameter_names.push_back(MakeNode<Identifier>("i"));
867 load_signature.parameter_types.types.push_back(
869 }
870 load_signature.parameter_types.var_args = false;
871 load_signature.return_type = field.name_and_type.type;
872
873 Expression* load_expression =
875 if (use_index) {
876 load_expression =
877 MakeNode<ElementAccessExpression>(load_expression, index);
878 }
879 Statement* load_body = MakeNode<ReturnStatement>(load_expression);
880 Declarations::DeclareMacro(load_macro_name, true, std::nullopt,
881 load_signature, load_body, std::nullopt);
882
883 // Store accessor
884 if (!field.const_qualified) {
886 std::string store_macro_name = "Store" + this->name() + camel_field_name;
887 Signature store_signature;
888 store_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
889 store_signature.parameter_types.types.push_back(this);
890 if (use_index) {
891 store_signature.parameter_names.push_back(MakeNode<Identifier>("i"));
892 store_signature.parameter_types.types.push_back(
894 }
895 store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
896 store_signature.parameter_types.types.push_back(field.name_and_type.type);
897 store_signature.parameter_types.var_args = false;
898 // TODO(danno): Store macros probably should return their value argument
899 store_signature.return_type = TypeOracle::GetVoidType();
900 Expression* store_expression =
902 if (use_index) {
903 store_expression =
904 MakeNode<ElementAccessExpression>(store_expression, index);
905 }
907 MakeNode<AssignmentExpression>(store_expression, value));
908 Declarations::DeclareMacro(store_macro_name, true, std::nullopt,
909 store_signature, store_body, std::nullopt,
910 false);
911 }
912 }
913}
914
915void ClassType::GenerateSliceAccessor(size_t field_index) {
916 // Generate a Torque macro for getting a Slice to this field. This macro can
917 // be called by the dot operator for this field. In Torque, this function for
918 // class "ClassName" and field "field_name" and field type "FieldType" would
919 // be written as one of the following:
920 //
921 // If the field has a known offset (in this example, 16):
922 // FieldSliceClassNameFieldName(o: ClassName) {
923 // return torque_internal::unsafe::New{Const,Mutable}Slice<FieldType>(
924 // /*object:*/ o,
925 // /*offset:*/ 16,
926 // /*length:*/ torque_internal::%IndexedFieldLength<ClassName>(
927 // o, "field_name")
928 // );
929 // }
930 //
931 // If the field has an unknown offset, and the previous field is named p, is
932 // not const, and is of type PType with size 4:
933 // FieldSliceClassNameFieldName(o: ClassName) {
934 // const previous = %FieldSlice<ClassName, MutableSlice<PType>>(o, "p");
935 // return torque_internal::unsafe::New{Const,Mutable}Slice<FieldType>(
936 // /*object:*/ o,
937 // /*offset:*/ previous.offset + 4 * previous.length,
938 // /*length:*/ torque_internal::%IndexedFieldLength<ClassName>(
939 // o, "field_name")
940 // );
941 // }
942 const Field& field = fields_[field_index];
943 std::string macro_name = GetSliceMacroName(field);
944 Signature signature;
945 Identifier* parameter_identifier = MakeNode<Identifier>("o");
946 signature.parameter_names.push_back(parameter_identifier);
947 signature.parameter_types.types.push_back(this);
948 signature.parameter_types.var_args = false;
949 signature.return_type =
950 field.const_qualified
953
954 std::vector<Statement*> statements;
955 Expression* offset_expression = nullptr;
956 IdentifierExpression* parameter =
957 MakeNode<IdentifierExpression>(parameter_identifier);
958
959 if (field.offset.has_value()) {
960 offset_expression =
962 } else {
963 const Field* previous = GetFieldPreceding(field_index);
965
966 const Type* previous_slice_type =
967 previous->const_qualified
968 ? TypeOracle::GetConstSliceType(previous->name_and_type.type)
969 : TypeOracle::GetMutableSliceType(previous->name_and_type.type);
970
971 // %FieldSlice<ClassName, MutableSlice<PType>>(o, "p")
972 Expression* previous_expression = MakeCallExpression(
974 {"torque_internal"}, "%FieldSlice",
976 MakeNode<PrecomputedTypeExpression>(previous_slice_type)}),
978 StringLiteralQuote(previous->name_and_type.name))});
979
980 // const previous = %FieldSlice<ClassName, MutableSlice<PType>>(o, "p");
981 Statement* define_previous =
982 MakeConstDeclarationStatement("previous", previous_expression);
983 statements.push_back(define_previous);
984
985 // 4
986 size_t previous_element_size;
987 std::tie(previous_element_size, std::ignore) =
988 *SizeOf(previous->name_and_type.type);
989 Expression* previous_element_size_expression =
991 IntegerLiteral(previous_element_size));
992
993 // previous.length
994 Expression* previous_length_expression = MakeFieldAccessExpression(
995 MakeIdentifierExpression("previous"), "length");
996
997 // previous.offset
998 Expression* previous_offset_expression = MakeFieldAccessExpression(
999 MakeIdentifierExpression("previous"), "offset");
1000
1001 // 4 * previous.length
1002 // In contrast to the code used for allocation, we don't need overflow
1003 // checks here because we already know all the offsets fit into memory.
1004 offset_expression = MakeCallExpression(
1005 "*", {previous_element_size_expression, previous_length_expression});
1006
1007 // previous.offset + 4 * previous.length
1008 offset_expression = MakeCallExpression(
1009 "+", {previous_offset_expression, offset_expression});
1010 }
1011
1012 // torque_internal::%IndexedFieldLength<ClassName>(o, "field_name")
1013 Expression* length_expression = MakeCallExpression(
1014 MakeIdentifierExpression({"torque_internal"}, "%IndexedFieldLength",
1018
1019 // torque_internal::unsafe::New{Const,Mutable}Slice<FieldType>(
1020 // /*object:*/ o,
1021 // /*offset:*/ <<offset_expression>>,
1022 // /*length:*/ torque_internal::%IndexedFieldLength<ClassName>(
1023 // o, "field_name")
1024 // )
1026 {"torque_internal", "unsafe"},
1027 field.const_qualified ? "NewConstSlice" : "NewMutableSlice",
1029 Expression* slice_expression = MakeCallExpression(
1030 new_struct, {parameter, offset_expression, length_expression});
1031
1032 statements.push_back(MakeNode<ReturnStatement>(slice_expression));
1033 Statement* block =
1034 MakeNode<BlockStatement>(/*deferred=*/false, std::move(statements));
1035
1036 Macro* macro = Declarations::DeclareMacro(macro_name, true, std::nullopt,
1037 signature, block, std::nullopt);
1039 GlobalContext::EnsureInCCDebugOutputList(TorqueMacro::cast(macro),
1040 macro->Position().source);
1041 } else {
1042 GlobalContext::EnsureInCCOutputList(TorqueMacro::cast(macro),
1043 macro->Position().source);
1044 }
1045}
1046
1048 if (IsSubtypeOf(TypeOracle::GetJSObjectType()) && !IsShape()) return false;
1049 return size().SingleValue().has_value();
1050}
1051
1053 bool in_test_directory = StringStartsWith(
1054 SourceFileMap::PathFromV8Root(GetPosition().source).substr(), "test/");
1055 if (!in_test_directory && (IsExtern() || ShouldExport())) {
1056 return GetPosition().source;
1057 }
1058 return SourceFileMap::GetSourceId("src/objects/torque-defined-classes.tq");
1059}
1060
1061void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
1062 os << "(";
1063 for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {
1064 if (i == 0 && sig.implicit_count != 0) os << "implicit ";
1065 if (sig.implicit_count > 0 && sig.implicit_count == i) {
1066 os << ")(";
1067 } else {
1068 if (i > 0) os << ", ";
1069 }
1070 if (with_names && !sig.parameter_names.empty()) {
1071 if (i < sig.parameter_names.size()) {
1072 os << sig.parameter_names[i] << ": ";
1073 }
1074 }
1075 os << *sig.parameter_types.types[i];
1076 }
1077 if (sig.parameter_types.var_args) {
1078 if (!sig.parameter_names.empty()) os << ", ";
1079 os << "...";
1080 }
1081 os << ")";
1082 os << ": " << *sig.return_type;
1083
1084 if (sig.labels.empty()) return;
1085
1086 os << " labels ";
1087 for (size_t i = 0; i < sig.labels.size(); ++i) {
1088 if (i > 0) os << ", ";
1089 os << sig.labels[i].name;
1090 if (!sig.labels[i].types.empty()) os << "(" << sig.labels[i].types << ")";
1091 }
1092}
1093
1094std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type) {
1095 os << name_and_type.name;
1096 os << ": ";
1097 os << *name_and_type.type;
1098 return os;
1099}
1100
1101std::ostream& operator<<(std::ostream& os, const Field& field) {
1102 os << field.name_and_type;
1103 if (field.custom_weak_marking) {
1104 os << " (custom weak)";
1105 }
1106 return os;
1107}
1108
1109std::ostream& operator<<(std::ostream& os, const Signature& sig) {
1110 PrintSignature(os, sig, true);
1111 return os;
1112}
1113
1114std::ostream& operator<<(std::ostream& os, const TypeVector& types) {
1115 PrintCommaSeparatedList(os, types);
1116 return os;
1117}
1118
1119std::ostream& operator<<(std::ostream& os, const ParameterTypes& p) {
1121 if (p.var_args) {
1122 if (!p.types.empty()) os << ", ";
1123 os << "...";
1124 }
1125 return os;
1126}
1127
1129 ParameterMode mode) const {
1130 auto compare_types = types();
1131 auto other_compare_types = other.types();
1132 if (mode == ParameterMode::kIgnoreImplicit) {
1133 compare_types = GetExplicitTypes();
1134 other_compare_types = other.GetExplicitTypes();
1135 }
1136 if (!(compare_types == other_compare_types &&
1137 parameter_types.var_args == other.parameter_types.var_args &&
1138 return_type == other.return_type)) {
1139 return false;
1140 }
1141 if (labels.size() != other.labels.size()) {
1142 return false;
1143 }
1144 size_t i = 0;
1145 for (const auto& l : labels) {
1146 if (l.types != other.labels[i++].types) {
1147 return false;
1148 }
1149 }
1150 return true;
1151}
1152
1153namespace {
1154bool FirstTypeIsContext(const std::vector<const Type*>& parameter_types) {
1155 return !parameter_types.empty() &&
1156 (parameter_types[0] == TypeOracle::GetContextType() ||
1157 parameter_types[0] == TypeOracle::GetNoContextType());
1158}
1159} // namespace
1160
1162 return FirstTypeIsContext(types());
1163}
1164
1166 return FirstTypeIsContext(parameter_types());
1167}
1168
1169bool IsAssignableFrom(const Type* to, const Type* from) {
1170 if (to == from) return true;
1171 if (from->IsSubtypeOf(to)) return true;
1172 return TypeOracle::ImplicitlyConvertableFrom(to, from).has_value();
1173}
1174
1175bool operator<(const Type& a, const Type& b) { return a.id() < b.id(); }
1176
1178 const std::string& fieldname) {
1179 BottomOffset begin = structure.stack_range().begin();
1180
1181 // Check constructor this super classes for fields.
1182 const StructType* type = *structure.type()->StructSupertype();
1183 auto& fields = type->fields();
1184 for (auto& field : fields) {
1185 BottomOffset end = begin + LoweredSlotCount(field.name_and_type.type);
1186 if (field.name_and_type.name == fieldname) {
1187 return VisitResult(field.name_and_type.type, StackRange{begin, end});
1188 }
1189 begin = end;
1190 }
1191
1192 ReportError("struct '", type->name(), "' doesn't contain a field '",
1193 fieldname, "'");
1194}
1195
1196namespace {
1197void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) {
1198 if (type->IsConstexpr()) return;
1199 if (type->IsVoidOrNever()) return;
1200 if (std::optional<const StructType*> s = type->StructSupertype()) {
1201 for (const Field& field : (*s)->fields()) {
1202 AppendLoweredTypes(field.name_and_type.type, result);
1203 }
1204 } else {
1205 result->push_back(type);
1206 }
1207}
1208} // namespace
1209
1212 AppendLoweredTypes(type, &result);
1213 return result;
1214}
1215
1216size_t LoweredSlotCount(const Type* type) { return LowerType(type).size(); }
1217
1219 std::vector<const Type*> result;
1220 for (const Type* t : parameters) {
1221 AppendLoweredTypes(t, &result);
1222 }
1223 return result;
1224}
1225
1227 size_t arg_count) {
1228 std::vector<const Type*> result = LowerParameterTypes(parameter_types.types);
1229 for (size_t i = parameter_types.types.size(); i < arg_count; ++i) {
1230 DCHECK(parameter_types.var_args);
1231 AppendLoweredTypes(TypeOracle::GetObjectType(), &result);
1232 }
1233 return result;
1234}
1235
1241
1243 const Type* from_type) {
1245 result.type_ = TypeOracle::GetTopType(std::move(top_reason), from_type);
1246 return result;
1247}
1248
1249std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const {
1250 auto optional = SizeOf(this->name_and_type.type);
1251 if (optional.has_value()) {
1252 return *optional;
1253 }
1254 Error("fields of type ", *name_and_type.type, " are not (yet) supported")
1255 .Position(pos)
1256 .Throw();
1257}
1258
1259size_t Type::AlignmentLog2() const {
1260 if (parent()) return parent()->AlignmentLog2();
1262}
1263
1265 size_t alignment;
1266 if (this == TypeOracle::GetTaggedType()) {
1267 alignment = TargetArchitecture::TaggedSize();
1268 } else if (this == TypeOracle::GetRawPtrType()) {
1269 alignment = TargetArchitecture::RawPtrSize();
1270 } else if (this == TypeOracle::GetExternalPointerType()) {
1272 } else if (this == TypeOracle::GetCppHeapPointerType()) {
1274 } else if (this == TypeOracle::GetTrustedPointerType()) {
1276 } else if (this == TypeOracle::GetProtectedPointerType()) {
1278 } else if (this == TypeOracle::GetVoidType()) {
1279 alignment = 1;
1280 } else if (this == TypeOracle::GetInt8Type()) {
1281 alignment = kUInt8Size;
1282 } else if (this == TypeOracle::GetUint8Type()) {
1283 alignment = kUInt8Size;
1284 } else if (this == TypeOracle::GetInt16Type()) {
1285 alignment = kUInt16Size;
1286 } else if (this == TypeOracle::GetUint16Type()) {
1287 alignment = kUInt16Size;
1288 } else if (this == TypeOracle::GetInt32Type()) {
1289 alignment = kInt32Size;
1290 } else if (this == TypeOracle::GetUint32Type()) {
1291 alignment = kInt32Size;
1292 } else if (this == TypeOracle::GetFloat64Type()) {
1293 alignment = kDoubleSize;
1294 } else if (this == TypeOracle::GetIntPtrType()) {
1295 alignment = TargetArchitecture::RawPtrSize();
1296 } else if (this == TypeOracle::GetUIntPtrType()) {
1297 alignment = TargetArchitecture::RawPtrSize();
1298 } else {
1299 return Type::AlignmentLog2();
1300 }
1301 alignment = std::min(alignment, TargetArchitecture::TaggedSize());
1302 return base::bits::WhichPowerOfTwo(alignment);
1303}
1304
1307 return TypeOracle::GetFloat64Type()->AlignmentLog2();
1308 }
1309 size_t alignment_log_2 = 0;
1310 for (const Field& field : fields()) {
1311 alignment_log_2 =
1312 std::max(alignment_log_2, field.name_and_type.type->AlignmentLog2());
1313 }
1314 return alignment_log_2;
1315}
1316
1318 const Type* type = name_and_type.type;
1319 std::optional<const StructType*> struct_type = type->StructSupertype();
1320 if (struct_type &&
1322 for (const Field& field : (*struct_type)->fields()) {
1323 field.ValidateAlignment(at_offset);
1324 size_t field_size = std::get<0>(field.GetFieldSizeInformation());
1325 at_offset += field_size;
1326 }
1327 } else {
1328 size_t alignment_log_2 = name_and_type.type->AlignmentLog2();
1329 if (at_offset.AlignmentLog2() < alignment_log_2) {
1330 Error("field ", name_and_type.name, " at offset ", at_offset, " is not ",
1331 size_t{1} << alignment_log_2, "-byte aligned.")
1332 .Position(pos);
1333 }
1334 }
1335}
1336
1337std::optional<std::tuple<size_t, std::string>> SizeOf(const Type* type) {
1338 std::string size_string;
1339 size_t size;
1340 if (type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
1342 size_string = "kTaggedSize";
1343 } else if (type->IsSubtypeOf(TypeOracle::GetRawPtrType())) {
1345 size_string = "kSystemPointerSize";
1346 } else if (type->IsSubtypeOf(TypeOracle::GetExternalPointerType())) {
1348 size_string = "kExternalPointerSlotSize";
1349 } else if (type->IsSubtypeOf(TypeOracle::GetCppHeapPointerType())) {
1351 size_string = "kCppHeapPointerSlotSize";
1352 } else if (type->IsSubtypeOf(TypeOracle::GetTrustedPointerType())) {
1354 size_string = "kTrustedPointerSize";
1355 } else if (type->IsSubtypeOf(TypeOracle::GetProtectedPointerType())) {
1357 size_string = "kTaggedSize";
1358 } else if (type->IsSubtypeOf(TypeOracle::GetVoidType())) {
1359 size = 0;
1360 size_string = "0";
1361 } else if (type->IsSubtypeOf(TypeOracle::GetInt8Type())) {
1362 size = kUInt8Size;
1363 size_string = "kUInt8Size";
1364 } else if (type->IsSubtypeOf(TypeOracle::GetUint8Type())) {
1365 size = kUInt8Size;
1366 size_string = "kUInt8Size";
1367 } else if (type->IsSubtypeOf(TypeOracle::GetInt16Type())) {
1368 size = kUInt16Size;
1369 size_string = "kUInt16Size";
1370 } else if (type->IsSubtypeOf(TypeOracle::GetUint16Type())) {
1371 size = kUInt16Size;
1372 size_string = "kUInt16Size";
1373 } else if (type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
1374 size = kInt32Size;
1375 size_string = "kInt32Size";
1376 } else if (type->IsSubtypeOf(TypeOracle::GetUint32Type())) {
1377 size = kInt32Size;
1378 size_string = "kInt32Size";
1379 } else if (type->IsSubtypeOf(TypeOracle::GetFloat64Type())) {
1380 size = kDoubleSize;
1381 size_string = "kDoubleSize";
1382 } else if (type->IsSubtypeOf(TypeOracle::GetIntPtrType())) {
1384 size_string = "kIntptrSize";
1385 } else if (type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) {
1387 size_string = "kIntptrSize";
1388 } else if (auto struct_type = type->StructSupertype()) {
1390 size = kDoubleSize;
1391 size_string = "kDoubleSize";
1392 } else {
1393 size = (*struct_type)->PackedSize();
1394 size_string = std::to_string(size);
1395 }
1396 } else {
1397 return {};
1398 }
1399 return std::make_tuple(size, size_string);
1400}
1401
1402bool IsAnyUnsignedInteger(const Type* type) {
1403 return type == TypeOracle::GetUint32Type() ||
1404 type == TypeOracle::GetUint31Type() ||
1405 type == TypeOracle::GetUint16Type() ||
1406 type == TypeOracle::GetUint8Type() ||
1408}
1409
1410bool IsAllowedAsBitField(const Type* type) {
1411 if (type->IsBitFieldStructType()) {
1412 // No nested bitfield structs for now. We could reconsider if there's a
1413 // compelling use case.
1414 return false;
1415 }
1416 // Any integer-ish type, including bools and enums which inherit from integer
1417 // types, are allowed. Note, however, that we always zero-extend during
1418 // decoding regardless of signedness.
1419 return IsPointerSizeIntegralType(type) || Is32BitIntegralType(type);
1420}
1421
1423 return type->IsSubtypeOf(TypeOracle::GetUIntPtrType()) ||
1424 type->IsSubtypeOf(TypeOracle::GetIntPtrType());
1425}
1426
1427bool Is32BitIntegralType(const Type* type) {
1428 return type->IsSubtypeOf(TypeOracle::GetUint32Type()) ||
1429 type->IsSubtypeOf(TypeOracle::GetInt32Type()) ||
1430 type->IsSubtypeOf(TypeOracle::GetBoolType());
1431}
1432
1433std::optional<NameAndType> ExtractSimpleFieldArraySize(
1434 const ClassType& class_type, Expression* array_size) {
1436 IdentifierExpression::DynamicCast(array_size);
1437 if (!identifier || !identifier->generic_arguments.empty() ||
1438 !identifier->namespace_qualification.empty())
1439 return {};
1440 if (!class_type.HasField(identifier->name->value)) return {};
1441 return class_type.LookupField(identifier->name->value).name_and_type;
1442}
1443
1444std::string Type::GetRuntimeType() const {
1445 if (IsSubtypeOf(TypeOracle::GetSmiType())) return "Tagged<Smi>";
1447 return "Tagged<" + GetGeneratedTNodeTypeName() + ">";
1448 }
1449 if (std::optional<const StructType*> struct_type = StructSupertype()) {
1450 std::stringstream result;
1451 result << "std::tuple<";
1452 bool first = true;
1453 for (const Type* field_type : LowerType(*struct_type)) {
1454 if (!first) result << ", ";
1455 first = false;
1456 result << field_type->GetRuntimeType();
1457 }
1458 result << ">";
1459 return result.str();
1460 }
1461 return ConstexprVersion()->GetGeneratedTypeName();
1462}
1463
1464std::string Type::GetDebugType() const {
1465 if (IsSubtypeOf(TypeOracle::GetSmiType())) return "uintptr_t";
1467 return "uintptr_t";
1468 }
1469 if (std::optional<const StructType*> struct_type = StructSupertype()) {
1470 std::stringstream result;
1471 result << "std::tuple<";
1472 bool first = true;
1473 for (const Type* field_type : LowerType(*struct_type)) {
1474 if (!first) result << ", ";
1475 first = false;
1476 result << field_type->GetDebugType();
1477 }
1478 result << ">";
1479 return result.str();
1480 }
1481 return ConstexprVersion()->GetGeneratedTypeName();
1482}
1483
1484} // namespace v8::internal::torque
Builtins::Kind kind
Definition builtins.cc:40
NameAndType name_and_type
std::vector< TypeChecker > GetTypeCheckers() const override
Definition types.cc:220
const std::string & name() const
Definition types.h:270
bool IsConstexpr() const final
Definition types.h:274
std::string GetGeneratedTypeNameImpl() const override
Definition types.cc:198
size_t AlignmentLog2() const override
Definition types.cc:1264
const std::string generated_type_
Definition types.h:329
std::string GetGeneratedTNodeTypeNameImpl() const override
Definition types.cc:215
const Field & LookupFieldInternal(const std::string &name) const
Definition types.cc:487
std::vector< Field > fields_
Definition types.h:608
Namespace * nspace() const
Definition types.h:563
const Field & LookupField(const std::string &name) const
Definition types.cc:499
const std::string & name() const
Definition types.h:562
const std::vector< Field > & fields() const
Definition types.h:556
virtual void Finalize() const =0
std::vector< Method * > methods_
Definition types.h:613
std::vector< const AggregateType * > GetHierarchy() const
Definition types.cc:459
const std::vector< Method * > & Methods() const
Definition types.h:571
bool HasField(const std::string &name) const
Definition types.cc:474
const BitField & LookupField(const std::string &name) const
Definition types.cc:421
const std::string & name() const
Definition types.h:526
std::string ToExplicitString() const override
Definition types.cc:417
std::vector< BitField > fields_
Definition types.h:544
std::string ToExplicitString() const override
Definition types.cc:238
const TypeVector & parameter_types() const
Definition types.h:345
std::string SimpleNameImpl() const override
Definition types.cc:246
const ClassType * GetSuperClass() const
Definition types.h:742
bool ShouldGenerateCppObjectLayoutDefinitionAsserts() const
Definition types.h:718
SourcePosition GetPosition() const
Definition types.h:783
const ClassType * GetClassDeclaringField(const Field &f) const
Definition types.cc:805
std::optional< ObjectSlotKind > ComputeArraySlotKind() const
Definition types.cc:757
std::optional< std::pair< int, int > > InstanceTypeRange() const
Definition types.cc:698
void Finalize() const override
Definition types.cc:638
size_t header_size() const
Definition types.h:734
std::optional< int > own_instance_type_
Definition types.h:809
ClassType(const Type *parent, Namespace *nspace, const std::string &name, ClassFlags flags, const std::string &generates, const ClassDeclaration *decl, const TypeAlias *alias)
Definition types.cc:612
std::string GetGeneratedTNodeTypeNameImpl() const override
Definition types.cc:623
std::optional< int > OwnInstanceType() const
Definition types.cc:693
bool HasNoPointerSlotsExceptMap() const
Definition types.cc:771
const Field * GetFieldPreceding(size_t field_index) const
Definition types.cc:795
ResidueClass size() const
Definition types.h:738
void InitializeInstanceTypes(std::optional< int > own, std::optional< std::pair< int, int > > range) const
Definition types.cc:685
std::string GetGeneratedTypeNameImpl() const override
Definition types.cc:627
std::string GetSliceMacroName(const Field &field) const
Definition types.cc:812
void GenerateSliceAccessor(size_t field_index)
Definition types.cc:915
std::string ToExplicitString() const override
Definition types.cc:632
const ClassDeclaration * decl_
Definition types.h:807
const TypeAlias * alias_
Definition types.h:808
bool AllowInstantiation() const
Definition types.cc:634
std::vector< Field > ComputeHeaderFields() const
Definition types.cc:659
std::vector< Field > ComputeAllFields() const
Definition types.cc:648
SourceId AttributedToFile() const
Definition types.cc:1052
bool HasIndexedFieldsIncludingInParents() const
Definition types.cc:785
const std::string generates_
Definition types.h:806
std::vector< Field > ComputeArrayFields() const
Definition types.cc:671
std::vector< ObjectSlotKind > ComputeHeaderSlotKinds() const
Definition types.cc:747
std::optional< std::pair< int, int > > instance_type_range_
Definition types.h:810
static Macro * DeclareMacro(const std::string &name, bool accessible_from_csa, std::optional< std::string > external_assembler_name, const Signature &signature, std::optional< Statement * > body, std::optional< std::string > op={}, bool is_user_defined=true)
static void EnsureInCCDebugOutputList(TorqueMacro *macro, SourceId source)
static void EnsureInCCOutputList(TorqueMacro *macro, SourceId source)
MessageBuilder & Position(SourcePosition position)
Definition utils.h:52
std::optional< size_t > SingleValue() const
Definition utils.h:440
static const std::string & PathFromV8Root(SourceId file)
static SourceId GetSourceId(const std::string &path)
std::string GetGeneratedTypeNameImpl() const override
Definition types.cc:517
size_t AlignmentLog2() const override
Definition types.cc:1305
const StructDeclaration * decl_
Definition types.h:649
std::string SimpleNameImpl() const override
Definition types.cc:570
void Finalize() const override
Definition types.cc:601
Classification ClassifyContents() const
Definition types.cc:529
std::string ToExplicitString() const override
Definition types.cc:599
StructType(Namespace *nspace, const StructDeclaration *decl, MaybeSpecializationKey specialized_from=std::nullopt)
Definition types.cc:504
bool IsAbstractType() const
Definition types.h:45
static const Type * GetStrongTaggedType()
static const Type * GetUint31Type()
static const Type * GetFloat64Type()
static const Type * GetUnionType(UnionType type)
static const Type * GetUint32Type()
static const Type * GetInt8Type()
static const Type * GetRawPtrType()
static const Type * GetNoContextType()
static const Type * GetTaggedType()
static std::optional< const Type * > ImplicitlyConvertableFrom(const Type *to, const Type *from)
static const Type * GetUint8Type()
static GenericType * GetMutableReferenceGeneric()
Definition type-oracle.h:93
static const Type * GetUint16Type()
static const Type * GetExternalPointerType()
static const Type * GetObjectType()
static const Type * GetMutableSliceType(const Type *referenced_type)
static const Type * GetVoidType()
static const Type * GetInt32Type()
static const Type * GetUIntPtrType()
static const Type * GetJSObjectType()
static const TopType * GetTopType(std::string reason, const Type *source_type)
static const Type * GetIntPtrType()
static const Type * GetBoolType()
static const Type * GetSmiType()
static const Type * GetMapType()
static const Type * GetContextType()
static const Type * GetTrustedPointerType()
static GenericType * GetWeakGeneric()
static const Type * GetProtectedPointerType()
static GenericType * GetLazyGeneric()
static GenericType * GetConstReferenceGeneric()
Definition type-oracle.h:90
static const Type * GetConstSliceType(const Type *referenced_type)
static const Type * GetNeverType()
static const Type * GetFloat64OrUndefinedOrHoleType()
static const Type * GetInt16Type()
static const Type * GetCppHeapPointerType()
static void VisitStructMethods(StructType *struct_type, const StructDeclaration *struct_declaration)
static void VisitClassFieldsAndMethods(ClassType *class_type, const ClassDeclaration *class_declaration)
const Type * parent_
Definition types.h:189
bool IsAbstractName(const std::string &name) const
Definition types.cc:175
bool IsNever() const
Definition types.h:126
virtual std::string GetConstexprGeneratedTypeName() const
Definition types.cc:115
static std::optional< const Type * > MatchUnaryGeneric(const Type *type, GenericType *generic)
Definition types.cc:573
std::string GetGeneratedTNodeTypeName() const
Definition types.cc:189
virtual std::string GetGeneratedTNodeTypeNameImpl() const =0
virtual bool IsSubtypeOf(const Type *supertype) const
Definition types.cc:101
std::optional< const AggregateType * > AggregateSupertype() const
Definition types.cc:142
virtual std::string GetRuntimeType() const
Definition types.cc:1444
static std::string ComputeName(const std::string &basename, MaybeSpecializationKey specialized_from)
Definition types.cc:547
std::optional< const StructType * > StructSupertype() const
Definition types.cc:133
std::string GetHandleTypeName(HandleKind kind, const std::string &type_name) const
Definition types.cc:71
virtual std::string ToExplicitString() const =0
virtual std::string SimpleNameImpl() const =0
virtual std::string GetGeneratedTypeNameImpl() const =0
virtual size_t AlignmentLog2() const
Definition types.cc:1259
std::string GetGeneratedTypeName() const
Definition types.cc:180
size_t id() const
Definition types.h:151
virtual std::string GetDebugType() const
Definition types.cc:1464
std::string HandlifiedCppTypeName(HandleKind kind) const
Definition types.cc:83
std::optional< const ClassType * > ClassSupertype() const
Definition types.cc:124
const MaybeSpecializationKey & GetSpecializedFrom() const
Definition types.h:152
virtual const Type * ConstexprVersion() const
Definition types.h:165
std::string ToString() const
Definition types.cc:37
static const Type * CommonSupertype(const Type *a, const Type *b)
Definition types.cc:152
void set_parent(const Type *t)
Definition types.h:178
virtual std::string SimpleName() const
Definition types.cc:57
std::set< std::string > aliases_
Definition types.h:190
std::string TagglifiedCppTypeName() const
Definition types.cc:92
virtual bool IsConstexpr() const
Definition types.h:136
const Type * parent() const
Definition types.h:124
std::set< const Type *, TypeLess > types_
Definition types.h:492
std::string GetConstexprGeneratedTypeName() const override
Definition types.cc:350
static void InsertGeneratedTNodeTypeName(std::set< std::string > &names, const Type *t)
Definition types.cc:285
std::string GetGeneratedTNodeTypeNameImpl() const override
Definition types.cc:296
std::string ToExplicitString() const override
Definition types.cc:256
std::string GetRuntimeType() const override
Definition types.cc:329
static UnionType FromType(const Type *t)
Definition types.h:468
std::string SimpleNameImpl() const override
Definition types.cc:271
static void InsertConstexprGeneratedTypeName(std::set< std::string > &names, const Type *t)
Definition types.cc:339
void Subtract(const Type *t)
Definition types.cc:399
std::string GetDebugType() const override
Definition types.cc:385
static VisitResult NeverResult()
Definition types.cc:1236
static VisitResult TopTypeResult(std::string top_reason, const Type *from_type)
Definition types.cc:1242
const Type * type() const
Definition types.h:846
const StackRange & stack_range() const
Definition types.h:848
const int size_
Definition assembler.cc:132
JSRegExp::Flags flags_
int end
LineAndColumn current
LineAndColumn previous
int32_t offset
std::optional< TNode< JSArray > > a
ZoneVector< RpoNumber > & result
int s
Definition mul-fft.cc:297
constexpr int WhichPowerOfTwo(T value)
Definition bits.h:195
VarDeclarationStatement * MakeConstDeclarationStatement(std::string name, Expression *initializer)
Definition ast.h:1323
bool operator<(const Type &a, const Type &b)
Definition types.cc:1175
bool IsAssignableFrom(const Type *to, const Type *from)
Definition types.cc:1169
std::ostream & operator<<(std::ostream &os, Identifier *id)
Definition ast.h:263
size_t LoweredSlotCount(const Type *type)
Definition types.cc:1216
std::optional< NameAndType > ExtractSimpleFieldArraySize(const ClassType &class_type, Expression *array_size)
Definition types.cc:1433
std::string StringLiteralQuote(const std::string &s)
Definition utils.cc:54
void ReportError(Args &&... args)
Definition utils.h:96
bool IsAnyUnsignedInteger(const Type *type)
Definition types.cc:1402
T * MakeNode(Args... args)
Definition ast.h:1286
std::string ToString(Args &&... args)
Definition utils.h:41
void PrintSignature(std::ostream &os, const Signature &sig, bool with_names)
Definition types.cc:1061
VisitResult ProjectStructField(VisitResult structure, const std::string &fieldname)
Definition types.cc:1177
FieldAccessExpression * MakeFieldAccessExpression(Expression *object, std::string field)
Definition ast.h:1291
std::optional< SpecializationKey< GenericType > > MaybeSpecializationKey
Definition types.h:93
bool Is32BitIntegralType(const Type *type)
Definition types.cc:1427
std::string CamelifyString(const std::string &underscore_string)
Definition utils.cc:278
bool IsAllowedAsBitField(const Type *type)
Definition types.cc:1410
std::optional< std::tuple< size_t, std::string > > SizeOf(const Type *type)
Definition types.cc:1337
bool IsPointerSizeIntegralType(const Type *type)
Definition types.cc:1422
bool StringStartsWith(const std::string &s, const std::string &prefix)
Definition utils.h:357
std::vector< const Type * > TypeVector
Definition types.h:85
IdentifierExpression * MakeIdentifierExpression(std::vector< std::string > namespace_qualification, std::string name, std::vector< TypeExpression * > args={})
Definition ast.h:1297
TypeVector LowerType(const Type *type)
Definition types.cc:1210
const Type * SubtractType(const Type *a, const Type *b)
Definition types.cc:411
void PrintCommaSeparatedList(std::ostream &os, const T &list, C &&transform)
Definition utils.h:163
CallExpression * MakeCallExpression(IdentifierExpression *callee, std::vector< Expression * > arguments, std::vector< Identifier * > labels={})
Definition ast.h:1309
MessageBuilder Error(Args &&... args)
Definition utils.h:81
TypeVector LowerParameterTypes(const TypeVector &parameters)
Definition types.cc:1218
constexpr int kUInt8Size
Definition globals.h:394
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
constexpr int kInt32Size
Definition globals.h:401
constexpr int kUInt16Size
Definition globals.h:399
constexpr int kDoubleSize
Definition globals.h:407
BytecodeSequenceNode * parent_
#define V8_NOEXCEPT
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
std::optional< ClassFieldIndexInfo > index
Definition types.h:221
NameAndType name_and_type
Definition types.h:222
SourcePosition pos
Definition types.h:219
std::optional< size_t > offset
Definition types.h:230
std::tuple< size_t, std::string > GetFieldSizeInformation() const
Definition types.cc:1249
void ValidateAlignment(ResidueClass at_offset) const
Definition types.cc:1317
LabelDeclarationVector labels
Definition types.h:927
ParameterTypes parameter_types
Definition types.h:923
bool HasSameTypesAs(const Signature &other, ParameterMode mode=ParameterMode::kProcessImplicit) const
Definition types.cc:1128
TypeVector GetExplicitTypes() const
Definition types.h:936
const TypeVector & types() const
Definition types.h:920
Symbol identifier