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 #ifndef V8_TORQUE_TYPES_H_
6 #define V8_TORQUE_TYPES_H_
7
8 #include <algorithm>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
13
14 #include "src/base/optional.h"
15 #include "src/torque/ast.h"
16 #include "src/torque/constants.h"
17 #include "src/torque/source-positions.h"
18 #include "src/torque/utils.h"
19
20 namespace v8 {
21 namespace internal {
22 namespace torque {
23
24 class AggregateType;
25 struct Identifier;
26 class Macro;
27 class Method;
28 class GenericType;
29 class StructType;
30 class Type;
31 class ClassType;
32 class Value;
33 class Namespace;
34
35 class TypeBase {
36 public:
37 enum class Kind {
38 kTopType,
39 kAbstractType,
40 kBuiltinPointerType,
41 kUnionType,
42 kBitFieldStructType,
43 kStructType,
44 kClassType
45 };
46 virtual ~TypeBase() = default;
IsTopType()47 bool IsTopType() const { return kind() == Kind::kTopType; }
IsAbstractType()48 bool IsAbstractType() const { return kind() == Kind::kAbstractType; }
IsBuiltinPointerType()49 bool IsBuiltinPointerType() const {
50 return kind() == Kind::kBuiltinPointerType;
51 }
IsUnionType()52 bool IsUnionType() const { return kind() == Kind::kUnionType; }
IsBitFieldStructType()53 bool IsBitFieldStructType() const {
54 return kind() == Kind::kBitFieldStructType;
55 }
IsStructType()56 bool IsStructType() const { return kind() == Kind::kStructType; }
IsClassType()57 bool IsClassType() const { return kind() == Kind::kClassType; }
IsAggregateType()58 bool IsAggregateType() const { return IsStructType() || IsClassType(); }
59
60 protected:
TypeBase(Kind kind)61 explicit TypeBase(Kind kind) : kind_(kind) {}
kind()62 Kind kind() const { return kind_; }
63
64 private:
65 const Kind kind_;
66 };
67
68 #define DECLARE_TYPE_BOILERPLATE(x) \
69 static x* cast(TypeBase* declarable) { \
70 DCHECK(declarable->Is##x()); \
71 return static_cast<x*>(declarable); \
72 } \
73 static const x* cast(const TypeBase* declarable) { \
74 DCHECK(declarable->Is##x()); \
75 return static_cast<const x*>(declarable); \
76 } \
77 static x* DynamicCast(TypeBase* declarable) { \
78 if (!declarable) return nullptr; \
79 if (!declarable->Is##x()) return nullptr; \
80 return static_cast<x*>(declarable); \
81 } \
82 static const x* DynamicCast(const TypeBase* declarable) { \
83 if (!declarable) return nullptr; \
84 if (!declarable->Is##x()) return nullptr; \
85 return static_cast<const x*>(declarable); \
86 }
87
88 using TypeVector = std::vector<const Type*>;
89
90 template <typename T>
91 struct SpecializationKey {
92 T* generic;
93 TypeVector specialized_types;
94 };
95
96 using MaybeSpecializationKey = base::Optional<SpecializationKey<GenericType>>;
97
98 struct TypeChecker {
99 // The type of the object. This string is not guaranteed to correspond to a
100 // C++ class, but just to a type checker function: for any type "Foo" here,
101 // the function Object::IsFoo must exist.
102 std::string type;
103 // If {type} is "MaybeObject", then {weak_ref_to} indicates the corresponding
104 // strong object type. Otherwise, {weak_ref_to} is empty.
105 std::string weak_ref_to;
106 };
107
108 class V8_EXPORT_PRIVATE Type : public TypeBase {
109 public:
110 Type& operator=(const Type& other) = delete;
111 virtual bool IsSubtypeOf(const Type* supertype) const;
112
113 // Default rendering for error messages etc.
114 std::string ToString() const;
115
116 // This name is not unique, but short and somewhat descriptive.
117 // Used for naming generated code.
118 virtual std::string SimpleName() const;
119
120 std::string UnhandlifiedCppTypeName() const;
121 std::string HandlifiedCppTypeName() const;
122
parent()123 const Type* parent() const { return parent_; }
IsVoid()124 bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
IsNever()125 bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
IsBool()126 bool IsBool() const { return IsAbstractName(BOOL_TYPE_STRING); }
IsConstexprBool()127 bool IsConstexprBool() const {
128 return IsAbstractName(CONSTEXPR_BOOL_TYPE_STRING);
129 }
IsVoidOrNever()130 bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
131 std::string GetGeneratedTypeName() const;
132 std::string GetGeneratedTNodeTypeName() const;
IsConstexpr()133 virtual bool IsConstexpr() const {
134 if (parent()) DCHECK(!parent()->IsConstexpr());
135 return false;
136 }
IsTransient()137 virtual bool IsTransient() const { return false; }
NonConstexprVersion()138 virtual const Type* NonConstexprVersion() const { return this; }
139 std::string GetConstexprGeneratedTypeName() const;
140 base::Optional<const ClassType*> ClassSupertype() const;
141 base::Optional<const StructType*> StructSupertype() const;
GetTypeCheckers()142 virtual std::vector<TypeChecker> GetTypeCheckers() const { return {}; }
143 virtual std::string GetRuntimeType() const;
144 static const Type* CommonSupertype(const Type* a, const Type* b);
AddAlias(std::string alias)145 void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
id()146 size_t id() const { return id_; }
GetSpecializedFrom()147 const MaybeSpecializationKey& GetSpecializedFrom() const {
148 return specialized_from_;
149 }
150
151 static base::Optional<const Type*> MatchUnaryGeneric(const Type* type,
152 GenericType* generic);
153
154 static std::string ComputeName(const std::string& basename,
155 MaybeSpecializationKey specialized_from);
SetConstexprVersion(const Type * type)156 virtual void SetConstexprVersion(const Type* type) const {
157 constexpr_version_ = type;
158 }
159
ConstexprVersion()160 virtual const Type* ConstexprVersion() const {
161 if (constexpr_version_) return constexpr_version_;
162 if (IsConstexpr()) return this;
163 if (parent()) return parent()->ConstexprVersion();
164 return nullptr;
165 }
166
167 virtual size_t AlignmentLog2() const;
168
169 protected:
170 Type(TypeBase::Kind kind, const Type* parent,
171 MaybeSpecializationKey specialized_from = base::nullopt);
172 Type(const Type& other) V8_NOEXCEPT;
set_parent(const Type * t)173 void set_parent(const Type* t) { parent_ = t; }
174 int Depth() const;
175 virtual std::string ToExplicitString() const = 0;
176 virtual std::string GetGeneratedTypeNameImpl() const = 0;
177 virtual std::string GetGeneratedTNodeTypeNameImpl() const = 0;
178 virtual std::string SimpleNameImpl() const = 0;
179
180 private:
181 bool IsAbstractName(const std::string& name) const;
182
183 // If {parent_} is not nullptr, then this type is a subtype of {parent_}.
184 const Type* parent_;
185 mutable std::set<std::string> aliases_;
186 size_t id_;
187 MaybeSpecializationKey specialized_from_;
188 mutable const Type* constexpr_version_ = nullptr;
189 };
190
hash_value(const TypeVector & types)191 inline size_t hash_value(const TypeVector& types) {
192 size_t hash = 0;
193 for (const Type* t : types) {
194 hash = base::hash_combine(hash, t);
195 }
196 return hash;
197 }
198
199 struct NameAndType {
200 std::string name;
201 const Type* type;
202 };
203
204 std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
205
206 struct Field {
207 // TODO(danno): This likely should be refactored, the handling of the types
208 // using the universal grab-bag utility with std::tie, as well as the
209 // reliance of string types is quite clunky.
210 std::tuple<size_t, std::string> GetFieldSizeInformation() const;
211
212 void ValidateAlignment(ResidueClass at_offset) const;
213
214 SourcePosition pos;
215 const AggregateType* aggregate;
216 base::Optional<Expression*> index;
217 NameAndType name_and_type;
218
219 // The byte offset of this field from the beginning of the containing class or
220 // struct. Most structs are never packed together in memory, and are only used
221 // to hold a batch of related CSA TNode values, in which case |offset| is
222 // irrelevant.
223 // The offset may be unknown because the field is after an indexed field or
224 // because we don't support the struct field for on-heap layouts.
225 base::Optional<size_t> offset;
226
227 bool is_weak;
228 bool const_qualified;
229 bool generate_verify;
230 };
231
232 std::ostream& operator<<(std::ostream& os, const Field& name_and_type);
233
234 class TopType final : public Type {
235 public:
DECLARE_TYPE_BOILERPLATE(TopType)236 DECLARE_TYPE_BOILERPLATE(TopType)
237 std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
GetGeneratedTNodeTypeNameImpl()238 std::string GetGeneratedTNodeTypeNameImpl() const override {
239 return source_type_->GetGeneratedTNodeTypeName();
240 }
ToExplicitString()241 std::string ToExplicitString() const override {
242 std::stringstream s;
243 s << "inaccessible " + source_type_->ToString();
244 return s.str();
245 }
246
source_type()247 const Type* source_type() const { return source_type_; }
reason()248 const std::string reason() const { return reason_; }
249
250 private:
251 friend class TypeOracle;
TopType(std::string reason,const Type * source_type)252 explicit TopType(std::string reason, const Type* source_type)
253 : Type(Kind::kTopType, nullptr),
254 reason_(std::move(reason)),
255 source_type_(source_type) {}
SimpleNameImpl()256 std::string SimpleNameImpl() const override { return "TopType"; }
257
258 std::string reason_;
259 const Type* source_type_;
260 };
261
262 class AbstractType final : public Type {
263 public:
DECLARE_TYPE_BOILERPLATE(AbstractType)264 DECLARE_TYPE_BOILERPLATE(AbstractType)
265 const std::string& name() const { return name_; }
ToExplicitString()266 std::string ToExplicitString() const override { return name(); }
GetGeneratedTypeNameImpl()267 std::string GetGeneratedTypeNameImpl() const override {
268 if (generated_type_.empty()) {
269 return parent()->GetGeneratedTypeName();
270 }
271 return IsConstexpr() ? generated_type_ : "TNode<" + generated_type_ + ">";
272 }
273 std::string GetGeneratedTNodeTypeNameImpl() const override;
IsConstexpr()274 bool IsConstexpr() const final {
275 const bool is_constexpr = flags_ & AbstractTypeFlag::kConstexpr;
276 DCHECK_IMPLIES(non_constexpr_version_ != nullptr, is_constexpr);
277 return is_constexpr;
278 }
279
NonConstexprVersion()280 const Type* NonConstexprVersion() const override {
281 if (non_constexpr_version_) return non_constexpr_version_;
282 if (!IsConstexpr()) return this;
283 if (parent()) return parent()->NonConstexprVersion();
284 return nullptr;
285 }
286
287 std::vector<TypeChecker> GetTypeCheckers() const override;
288
289 size_t AlignmentLog2() const override;
290
291 private:
292 friend class TypeOracle;
AbstractType(const Type * parent,AbstractTypeFlags flags,const std::string & name,const std::string & generated_type,const Type * non_constexpr_version,MaybeSpecializationKey specialized_from)293 AbstractType(const Type* parent, AbstractTypeFlags flags,
294 const std::string& name, const std::string& generated_type,
295 const Type* non_constexpr_version,
296 MaybeSpecializationKey specialized_from)
297 : Type(Kind::kAbstractType, parent, specialized_from),
298 flags_(flags),
299 name_(name),
300 generated_type_(generated_type),
301 non_constexpr_version_(non_constexpr_version) {
302 if (parent) DCHECK_EQ(parent->IsConstexpr(), IsConstexpr());
303 DCHECK_EQ(IsConstexprName(name), IsConstexpr());
304 DCHECK_IMPLIES(non_constexpr_version_ != nullptr, IsConstexpr());
305 DCHECK(!(IsConstexpr() && (flags_ & AbstractTypeFlag::kTransient)));
306 }
307
SimpleNameImpl()308 std::string SimpleNameImpl() const override {
309 if (IsConstexpr()) {
310 const Type* non_constexpr_version = NonConstexprVersion();
311 if (non_constexpr_version == nullptr) {
312 ReportError("Cannot find non-constexpr type corresponding to ", *this);
313 }
314 return "constexpr_" + non_constexpr_version->SimpleName();
315 }
316 return name();
317 }
318
IsTransient()319 bool IsTransient() const override {
320 return flags_ & AbstractTypeFlag::kTransient;
321 }
322
UseParentTypeChecker()323 bool UseParentTypeChecker() const {
324 return flags_ & AbstractTypeFlag::kUseParentTypeChecker;
325 }
326
327 AbstractTypeFlags flags_;
328 const std::string name_;
329 const std::string generated_type_;
330 const Type* non_constexpr_version_;
331 };
332
333 // For now, builtin pointers are restricted to Torque-defined builtins.
334 class V8_EXPORT_PRIVATE BuiltinPointerType final : public Type {
335 public:
336 DECLARE_TYPE_BOILERPLATE(BuiltinPointerType)
337 std::string ToExplicitString() const override;
GetGeneratedTypeNameImpl()338 std::string GetGeneratedTypeNameImpl() const override {
339 return parent()->GetGeneratedTypeName();
340 }
GetGeneratedTNodeTypeNameImpl()341 std::string GetGeneratedTNodeTypeNameImpl() const override {
342 return parent()->GetGeneratedTNodeTypeName();
343 }
344
parameter_types()345 const TypeVector& parameter_types() const { return parameter_types_; }
return_type()346 const Type* return_type() const { return return_type_; }
347
hash_value(const BuiltinPointerType & p)348 friend size_t hash_value(const BuiltinPointerType& p) {
349 size_t result = base::hash_value(p.return_type_);
350 for (const Type* parameter : p.parameter_types_) {
351 result = base::hash_combine(result, parameter);
352 }
353 return result;
354 }
355 bool operator==(const BuiltinPointerType& other) const {
356 return parameter_types_ == other.parameter_types_ &&
357 return_type_ == other.return_type_;
358 }
function_pointer_type_id()359 size_t function_pointer_type_id() const { return function_pointer_type_id_; }
360
GetTypeCheckers()361 std::vector<TypeChecker> GetTypeCheckers() const override {
362 return {{"Smi", ""}};
363 }
364
365 bool HasContextParameter() const;
366
367 private:
368 friend class TypeOracle;
BuiltinPointerType(const Type * parent,TypeVector parameter_types,const Type * return_type,size_t function_pointer_type_id)369 BuiltinPointerType(const Type* parent, TypeVector parameter_types,
370 const Type* return_type, size_t function_pointer_type_id)
371 : Type(Kind::kBuiltinPointerType, parent),
372 parameter_types_(parameter_types),
373 return_type_(return_type),
374 function_pointer_type_id_(function_pointer_type_id) {}
375 std::string SimpleNameImpl() const override;
376
377 const TypeVector parameter_types_;
378 const Type* const return_type_;
379 const size_t function_pointer_type_id_;
380 };
381
382 bool operator<(const Type& a, const Type& b);
383 struct TypeLess {
operatorTypeLess384 bool operator()(const Type* const a, const Type* const b) const {
385 return *a < *b;
386 }
387 };
388
389 class V8_EXPORT_PRIVATE UnionType final : public Type {
390 public:
DECLARE_TYPE_BOILERPLATE(UnionType)391 DECLARE_TYPE_BOILERPLATE(UnionType)
392 std::string GetGeneratedTypeNameImpl() const override {
393 return "TNode<" + GetGeneratedTNodeTypeName() + ">";
394 }
395 std::string GetGeneratedTNodeTypeNameImpl() const override;
GetRuntimeType()396 std::string GetRuntimeType() const override {
397 return parent()->GetRuntimeType();
398 }
399
hash_value(const UnionType & p)400 friend size_t hash_value(const UnionType& p) {
401 size_t result = 0;
402 for (const Type* t : p.types_) {
403 result = base::hash_combine(result, t);
404 }
405 return result;
406 }
407 bool operator==(const UnionType& other) const {
408 return types_ == other.types_;
409 }
410
GetSingleMember()411 base::Optional<const Type*> GetSingleMember() const {
412 if (types_.size() == 1) {
413 DCHECK_EQ(*types_.begin(), parent());
414 return *types_.begin();
415 }
416 return base::nullopt;
417 }
418
IsSubtypeOf(const Type * other)419 bool IsSubtypeOf(const Type* other) const override {
420 for (const Type* member : types_) {
421 if (!member->IsSubtypeOf(other)) return false;
422 }
423 return true;
424 }
425
IsSupertypeOf(const Type * other)426 bool IsSupertypeOf(const Type* other) const {
427 for (const Type* member : types_) {
428 if (other->IsSubtypeOf(member)) {
429 return true;
430 }
431 }
432 return false;
433 }
434
IsTransient()435 bool IsTransient() const override {
436 for (const Type* member : types_) {
437 if (member->IsTransient()) {
438 return true;
439 }
440 }
441 return false;
442 }
443
IsConstexpr()444 bool IsConstexpr() const override { return parent()->IsConstexpr(); }
445
NonConstexprVersion()446 const Type* NonConstexprVersion() const override {
447 if (!IsConstexpr()) return this;
448 return parent()->NonConstexprVersion();
449 }
450
Extend(const Type * t)451 void Extend(const Type* t) {
452 if (const UnionType* union_type = UnionType::DynamicCast(t)) {
453 for (const Type* member : union_type->types_) {
454 Extend(member);
455 }
456 } else {
457 if (t->IsSubtypeOf(this)) return;
458 set_parent(CommonSupertype(parent(), t));
459 EraseIf(&types_,
460 [&](const Type* member) { return member->IsSubtypeOf(t); });
461 types_.insert(t);
462 }
463 }
464 std::string ToExplicitString() const override;
465
466 void Subtract(const Type* t);
467
FromType(const Type * t)468 static UnionType FromType(const Type* t) {
469 const UnionType* union_type = UnionType::DynamicCast(t);
470 return union_type ? UnionType(*union_type) : UnionType(t);
471 }
472
GetTypeCheckers()473 std::vector<TypeChecker> GetTypeCheckers() const override {
474 std::vector<TypeChecker> result;
475 for (const Type* member : types_) {
476 std::vector<TypeChecker> sub_result = member->GetTypeCheckers();
477 result.insert(result.end(), sub_result.begin(), sub_result.end());
478 }
479 return result;
480 }
481
482 private:
UnionType(const Type * t)483 explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {}
484 void RecomputeParent();
485 std::string SimpleNameImpl() const override;
486
487 std::set<const Type*, TypeLess> types_;
488 };
489
490 const Type* SubtractType(const Type* a, const Type* b);
491
492 struct BitField {
493 SourcePosition pos;
494 NameAndType name_and_type;
495 int offset;
496 int num_bits;
497 };
498
499 class V8_EXPORT_PRIVATE BitFieldStructType final : public Type {
500 public:
501 DECLARE_TYPE_BOILERPLATE(BitFieldStructType)
502 std::string ToExplicitString() const override;
GetGeneratedTypeNameImpl()503 std::string GetGeneratedTypeNameImpl() const override {
504 return parent()->GetGeneratedTypeName();
505 }
GetGeneratedTNodeTypeNameImpl()506 std::string GetGeneratedTNodeTypeNameImpl() const override {
507 return parent()->GetGeneratedTNodeTypeName();
508 }
509
GetTypeCheckers()510 std::vector<TypeChecker> GetTypeCheckers() const override {
511 return parent()->GetTypeCheckers();
512 }
513
SetConstexprVersion(const Type *)514 void SetConstexprVersion(const Type*) const override { UNREACHABLE(); }
ConstexprVersion()515 const Type* ConstexprVersion() const override {
516 return parent()->ConstexprVersion();
517 }
518
RegisterField(BitField field)519 void RegisterField(BitField field) { fields_.push_back(std::move(field)); }
520
name()521 const std::string& name() const { return decl_->name->value; }
fields()522 const std::vector<BitField>& fields() const { return fields_; }
523
524 const BitField& LookupField(const std::string& name) const;
525
526 private:
527 friend class TypeOracle;
BitFieldStructType(Namespace * nspace,const Type * parent,const BitFieldStructDeclaration * decl)528 BitFieldStructType(Namespace* nspace, const Type* parent,
529 const BitFieldStructDeclaration* decl)
530 : Type(Kind::kBitFieldStructType, parent),
531 namespace_(nspace),
532 decl_(decl) {}
SimpleNameImpl()533 std::string SimpleNameImpl() const override { return name(); }
534
535 Namespace* namespace_;
536 const BitFieldStructDeclaration* decl_;
537 std::vector<BitField> fields_;
538 };
539
540 class AggregateType : public Type {
541 public:
DECLARE_TYPE_BOILERPLATE(AggregateType)542 DECLARE_TYPE_BOILERPLATE(AggregateType)
543 std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
GetGeneratedTNodeTypeNameImpl()544 std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }
545
546 virtual void Finalize() const = 0;
547
SetFields(std::vector<Field> fields)548 void SetFields(std::vector<Field> fields) { fields_ = std::move(fields); }
fields()549 const std::vector<Field>& fields() const {
550 if (!is_finalized_) Finalize();
551 return fields_;
552 }
553 bool HasField(const std::string& name) const;
554 const Field& LookupField(const std::string& name) const;
name()555 const std::string& name() const { return name_; }
nspace()556 Namespace* nspace() const { return namespace_; }
557
RegisterField(Field field)558 virtual const Field& RegisterField(Field field) {
559 fields_.push_back(field);
560 return fields_.back();
561 }
562
RegisterMethod(Method * method)563 void RegisterMethod(Method* method) { methods_.push_back(method); }
Methods()564 const std::vector<Method*>& Methods() const {
565 if (!is_finalized_) Finalize();
566 return methods_;
567 }
568 std::vector<Method*> Methods(const std::string& name) const;
569
570 std::vector<const AggregateType*> GetHierarchy() const;
GetTypeCheckers()571 std::vector<TypeChecker> GetTypeCheckers() const override {
572 return {{name_, ""}};
573 }
574
575 protected:
576 AggregateType(Kind kind, const Type* parent, Namespace* nspace,
577 const std::string& name,
578 MaybeSpecializationKey specialized_from = base::nullopt)
Type(kind,parent,specialized_from)579 : Type(kind, parent, specialized_from),
580 is_finalized_(false),
581 namespace_(nspace),
582 name_(name) {}
583
584 void CheckForDuplicateFields() const;
585 // Use this lookup if you do not want to trigger finalization on this type.
586 const Field& LookupFieldInternal(const std::string& name) const;
SimpleNameImpl()587 std::string SimpleNameImpl() const override { return name_; }
588
589 protected:
590 mutable bool is_finalized_;
591 std::vector<Field> fields_;
592
593 private:
594 Namespace* namespace_;
595 std::string name_;
596 std::vector<Method*> methods_;
597 };
598
599 class StructType final : public AggregateType {
600 public:
601 DECLARE_TYPE_BOILERPLATE(StructType)
602
603 std::string GetGeneratedTypeNameImpl() const override;
604
605 // Returns the sum of the size of all members.
606 size_t PackedSize() const;
607
608 size_t AlignmentLog2() const override;
609
610 enum class ClassificationFlag {
611 kEmpty = 0,
612 kTagged = 1 << 0,
613 kUntagged = 1 << 1,
614 kMixed = kTagged | kUntagged,
615 };
616 using Classification = base::Flags<ClassificationFlag>;
617
618 // Classifies a struct as containing tagged data, untagged data, or both.
619 Classification ClassifyContents() const;
620
GetPosition()621 SourcePosition GetPosition() const { return decl_->pos; }
622
623 private:
624 friend class TypeOracle;
625 StructType(Namespace* nspace, const StructDeclaration* decl,
626 MaybeSpecializationKey specialized_from = base::nullopt);
627
628 void Finalize() const override;
629 std::string ToExplicitString() const override;
630 std::string SimpleNameImpl() const override;
631
632 const StructDeclaration* decl_;
633 std::string generated_type_name_;
634 };
635
636 class TypeAlias;
637
638 enum class ObjectSlotKind : uint8_t {
639 kNoPointer,
640 kStrongPointer,
641 kMaybeObjectPointer,
642 kCustomWeakPointer
643 };
644
Combine(ObjectSlotKind a,ObjectSlotKind b)645 inline base::Optional<ObjectSlotKind> Combine(ObjectSlotKind a,
646 ObjectSlotKind b) {
647 if (a == b) return {a};
648 if (std::min(a, b) == ObjectSlotKind::kStrongPointer &&
649 std::max(a, b) == ObjectSlotKind::kMaybeObjectPointer) {
650 return {ObjectSlotKind::kMaybeObjectPointer};
651 }
652 return base::nullopt;
653 }
654
655 class ClassType final : public AggregateType {
656 public:
657 DECLARE_TYPE_BOILERPLATE(ClassType)
658 std::string ToExplicitString() const override;
659 std::string GetGeneratedTypeNameImpl() const override;
660 std::string GetGeneratedTNodeTypeNameImpl() const override;
IsExtern()661 bool IsExtern() const { return flags_ & ClassFlag::kExtern; }
ShouldGeneratePrint()662 bool ShouldGeneratePrint() const {
663 return !IsExtern() ||
664 ((flags_ & ClassFlag::kGeneratePrint) && !HasUndefinedLayout());
665 }
ShouldGenerateVerify()666 bool ShouldGenerateVerify() const {
667 return !IsExtern() || ((flags_ & ClassFlag::kGenerateVerify) &&
668 (!HasUndefinedLayout() && !IsShape()));
669 }
ShouldGenerateBodyDescriptor()670 bool ShouldGenerateBodyDescriptor() const {
671 if (IsAbstract()) return false;
672 return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern();
673 }
DoNotGenerateCast()674 bool DoNotGenerateCast() const {
675 return flags_ & ClassFlag::kDoNotGenerateCast;
676 }
IsTransient()677 bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
IsAbstract()678 bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; }
HasSameInstanceTypeAsParent()679 bool HasSameInstanceTypeAsParent() const {
680 return flags_ & ClassFlag::kHasSameInstanceTypeAsParent;
681 }
GenerateCppClassDefinitions()682 bool GenerateCppClassDefinitions() const {
683 return flags_ & ClassFlag::kGenerateCppClassDefinitions || !IsExtern() ||
684 ShouldGenerateBodyDescriptor();
685 }
ShouldGenerateFullClassDefinition()686 bool ShouldGenerateFullClassDefinition() const {
687 return !IsExtern() && !(flags_ & ClassFlag::kCustomCppClass);
688 }
689 // Class with multiple or non-standard maps, do not auto-generate map.
HasCustomMap()690 bool HasCustomMap() const { return flags_ & ClassFlag::kCustomMap; }
ShouldExport()691 bool ShouldExport() const { return flags_ & ClassFlag::kExport; }
IsShape()692 bool IsShape() const { return flags_ & ClassFlag::kIsShape; }
693 bool HasStaticSize() const;
header_size()694 size_t header_size() const {
695 if (!is_finalized_) Finalize();
696 return header_size_;
697 }
size()698 ResidueClass size() const {
699 if (!is_finalized_) Finalize();
700 return size_;
701 }
GetSuperClass()702 const ClassType* GetSuperClass() const {
703 if (parent() == nullptr) return nullptr;
704 return parent()->IsClassType() ? ClassType::DynamicCast(parent()) : nullptr;
705 }
706 void GenerateAccessors();
707 bool AllowInstantiation() const;
RegisterField(Field field)708 const Field& RegisterField(Field field) override {
709 return AggregateType::RegisterField(field);
710 }
711 void Finalize() const override;
712
713 std::vector<Field> ComputeAllFields() const;
714 std::vector<Field> ComputeHeaderFields() const;
715 std::vector<Field> ComputeArrayFields() const;
716 // The slots of an object are the tagged pointer sized offsets in an object
717 // that may or may not require GC visiting. These helper functions determine
718 // what kind of GC visiting the individual slots require.
719 std::vector<ObjectSlotKind> ComputeHeaderSlotKinds() const;
720 base::Optional<ObjectSlotKind> ComputeArraySlotKind() const;
721 bool HasNoPointerSlots() const;
722 bool HasIndexedFieldsIncludingInParents() const;
723 const Field* GetFieldPreceding(size_t field_index) const;
724
725 // Given that the field exists in this class or a superclass, returns the
726 // specific class that declared the field.
727 const ClassType* GetClassDeclaringField(const Field& f) const;
728
729 std::string GetSliceMacroName(const Field& field) const;
730
GetInstanceTypeConstraints()731 const InstanceTypeConstraints& GetInstanceTypeConstraints() const {
732 return decl_->instance_type_constraints;
733 }
IsHighestInstanceTypeWithinParent()734 bool IsHighestInstanceTypeWithinParent() const {
735 return flags_ & ClassFlag::kHighestInstanceTypeWithinParent;
736 }
IsLowestInstanceTypeWithinParent()737 bool IsLowestInstanceTypeWithinParent() const {
738 return flags_ & ClassFlag::kLowestInstanceTypeWithinParent;
739 }
HasUndefinedLayout()740 bool HasUndefinedLayout() const {
741 return flags_ & ClassFlag::kUndefinedLayout;
742 }
GetPosition()743 SourcePosition GetPosition() const { return decl_->pos; }
744 SourceId AttributedToFile() const;
745
746 // TODO(tebbi): We should no longer pass around types as const pointers, so
747 // that we can avoid mutable fields and const initializers for
748 // late-initialized portions of types like this one.
749 void InitializeInstanceTypes(base::Optional<int> own,
750 base::Optional<std::pair<int, int>> range) const;
751 base::Optional<int> OwnInstanceType() const;
752 base::Optional<std::pair<int, int>> InstanceTypeRange() const;
753
754 private:
755 friend class TypeOracle;
756 friend class TypeVisitor;
757 ClassType(const Type* parent, Namespace* nspace, const std::string& name,
758 ClassFlags flags, const std::string& generates,
759 const ClassDeclaration* decl, const TypeAlias* alias);
760
761 void GenerateSliceAccessor(size_t field_index);
762
763 size_t header_size_;
764 ResidueClass size_;
765 mutable ClassFlags flags_;
766 const std::string generates_;
767 const ClassDeclaration* decl_;
768 const TypeAlias* alias_;
769 mutable base::Optional<int> own_instance_type_;
770 mutable base::Optional<std::pair<int, int>> instance_type_range_;
771 };
772
773 inline std::ostream& operator<<(std::ostream& os, const Type& t) {
774 os << t.ToString();
775 return os;
776 }
777
778 class VisitResult {
779 public:
780 VisitResult() = default;
VisitResult(const Type * type,const std::string & constexpr_value)781 VisitResult(const Type* type, const std::string& constexpr_value)
782 : type_(type), constexpr_value_(constexpr_value) {
783 DCHECK(type->IsConstexpr());
784 }
785 static VisitResult NeverResult();
786 static VisitResult TopTypeResult(std::string top_reason,
787 const Type* from_type);
VisitResult(const Type * type,StackRange stack_range)788 VisitResult(const Type* type, StackRange stack_range)
789 : type_(type), stack_range_(stack_range) {
790 DCHECK(!type->IsConstexpr());
791 }
type()792 const Type* type() const { return type_; }
constexpr_value()793 const std::string& constexpr_value() const { return *constexpr_value_; }
stack_range()794 const StackRange& stack_range() const { return *stack_range_; }
SetType(const Type * new_type)795 void SetType(const Type* new_type) { type_ = new_type; }
IsOnStack()796 bool IsOnStack() const { return stack_range_ != base::nullopt; }
797 bool operator==(const VisitResult& other) const {
798 return type_ == other.type_ && constexpr_value_ == other.constexpr_value_ &&
799 stack_range_ == other.stack_range_;
800 }
801
802 private:
803 const Type* type_ = nullptr;
804 base::Optional<std::string> constexpr_value_;
805 base::Optional<StackRange> stack_range_;
806 };
807
808 VisitResult ProjectStructField(VisitResult structure,
809 const std::string& fieldname);
810
811 class VisitResultVector : public std::vector<VisitResult> {
812 public:
VisitResultVector()813 VisitResultVector() : std::vector<VisitResult>() {}
VisitResultVector(std::initializer_list<VisitResult> init)814 VisitResultVector(std::initializer_list<VisitResult> init)
815 : std::vector<VisitResult>(init) {}
ComputeTypeVector()816 TypeVector ComputeTypeVector() const {
817 TypeVector result;
818 for (auto& visit_result : *this) {
819 result.push_back(visit_result.type());
820 }
821 return result;
822 }
823 };
824
825 std::ostream& operator<<(std::ostream& os, const TypeVector& types);
826
827 using NameAndTypeVector = std::vector<NameAndType>;
828
829 struct LabelDefinition {
830 std::string name;
831 NameAndTypeVector parameters;
832 };
833
834 using LabelDefinitionVector = std::vector<LabelDefinition>;
835
836 struct LabelDeclaration {
837 Identifier* name;
838 TypeVector types;
839 };
840
841 using LabelDeclarationVector = std::vector<LabelDeclaration>;
842
843 struct ParameterTypes {
844 TypeVector types;
845 bool var_args;
846 };
847
848 std::ostream& operator<<(std::ostream& os, const ParameterTypes& parameters);
849
850 enum class ParameterMode { kProcessImplicit, kIgnoreImplicit };
851
852 using NameVector = std::vector<Identifier*>;
853
854 struct Signature {
SignatureSignature855 Signature(NameVector n, base::Optional<std::string> arguments_variable,
856 ParameterTypes p, size_t i, const Type* r, LabelDeclarationVector l,
857 bool transitioning)
858 : parameter_names(std::move(n)),
859 arguments_variable(arguments_variable),
860 parameter_types(std::move(p)),
861 implicit_count(i),
862 return_type(r),
863 labels(std::move(l)),
864 transitioning(transitioning) {}
865 Signature() = default;
typesSignature866 const TypeVector& types() const { return parameter_types.types; }
867 NameVector parameter_names;
868 base::Optional<std::string> arguments_variable;
869 ParameterTypes parameter_types;
870 size_t implicit_count = 0;
ExplicitCountSignature871 size_t ExplicitCount() const { return types().size() - implicit_count; }
872 const Type* return_type;
873 LabelDeclarationVector labels;
874 bool transitioning = false;
875 bool HasSameTypesAs(
876 const Signature& other,
877 ParameterMode mode = ParameterMode::kProcessImplicit) const;
GetImplicitTypesSignature878 TypeVector GetImplicitTypes() const {
879 return TypeVector(parameter_types.types.begin(),
880 parameter_types.types.begin() + implicit_count);
881 }
GetExplicitTypesSignature882 TypeVector GetExplicitTypes() const {
883 return TypeVector(parameter_types.types.begin() + implicit_count,
884 parameter_types.types.end());
885 }
886 bool HasContextParameter() const;
887 };
888
889 void PrintSignature(std::ostream& os, const Signature& sig, bool with_names);
890 std::ostream& operator<<(std::ostream& os, const Signature& sig);
891
892 bool IsAssignableFrom(const Type* to, const Type* from);
893
894 TypeVector LowerType(const Type* type);
895 size_t LoweredSlotCount(const Type* type);
896 TypeVector LowerParameterTypes(const TypeVector& parameters);
897 TypeVector LowerParameterTypes(const ParameterTypes& parameter_types,
898 size_t vararg_count = 0);
899
900 base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type);
901 bool IsAnyUnsignedInteger(const Type* type);
902 bool IsAllowedAsBitField(const Type* type);
903 bool IsPointerSizeIntegralType(const Type* type);
904 bool Is32BitIntegralType(const Type* type);
905
906 base::Optional<NameAndType> ExtractSimpleFieldArraySize(
907 const ClassType& class_type, Expression* array_size);
908
909 } // namespace torque
910 } // namespace internal
911 } // namespace v8
912
913 #endif // V8_TORQUE_TYPES_H_
914