summaryrefslogtreecommitdiff
path: root/deps/v8/src/torque
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/torque')
-rw-r--r--deps/v8/src/torque/ast.h27
-rw-r--r--deps/v8/src/torque/class-debug-reader-generator.cc54
-rw-r--r--deps/v8/src/torque/constants.h24
-rw-r--r--deps/v8/src/torque/csa-generator.cc47
-rw-r--r--deps/v8/src/torque/declaration-visitor.cc14
-rw-r--r--deps/v8/src/torque/declarations.h1
-rw-r--r--deps/v8/src/torque/earley-parser.h4
-rw-r--r--deps/v8/src/torque/global-context.cc2
-rw-r--r--deps/v8/src/torque/global-context.h1
-rw-r--r--deps/v8/src/torque/implementation-visitor.cc255
-rw-r--r--deps/v8/src/torque/implementation-visitor.h8
-rw-r--r--deps/v8/src/torque/instance-type-generator.cc376
-rw-r--r--deps/v8/src/torque/ls/json.h6
-rw-r--r--deps/v8/src/torque/ls/message-handler.cc17
-rw-r--r--deps/v8/src/torque/server-data.h5
-rw-r--r--deps/v8/src/torque/torque-compiler.cc3
-rw-r--r--deps/v8/src/torque/torque-parser.cc146
-rw-r--r--deps/v8/src/torque/type-oracle.h2
-rw-r--r--deps/v8/src/torque/type-visitor.cc11
-rw-r--r--deps/v8/src/torque/types.cc18
-rw-r--r--deps/v8/src/torque/types.h27
-rw-r--r--deps/v8/src/torque/utils.cc16
22 files changed, 820 insertions, 244 deletions
diff --git a/deps/v8/src/torque/ast.h b/deps/v8/src/torque/ast.h
index 5ce25cf13a..fcbb02124d 100644
--- a/deps/v8/src/torque/ast.h
+++ b/deps/v8/src/torque/ast.h
@@ -90,7 +90,8 @@ namespace torque {
AST_STATEMENT_NODE_KIND_LIST(V) \
AST_DECLARATION_NODE_KIND_LIST(V) \
V(Identifier) \
- V(LabelBlock)
+ V(LabelBlock) \
+ V(ClassBody)
struct AstNode {
public:
@@ -792,6 +793,12 @@ struct TypeDeclaration : Declaration {
Identifier* name;
};
+struct InstanceTypeConstraints {
+ InstanceTypeConstraints() : value(-1), num_flags_bits(-1) {}
+ int value;
+ int num_flags_bits;
+};
+
struct AbstractTypeDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(AbstractTypeDeclaration)
AbstractTypeDeclaration(SourcePosition pos, Identifier* name, bool transient,
@@ -1069,24 +1076,38 @@ struct StructDeclaration : TypeDeclaration {
bool IsGeneric() const { return !generic_parameters.empty(); }
};
+struct ClassBody : AstNode {
+ DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassBody)
+ ClassBody(SourcePosition pos, std::vector<Declaration*> methods,
+ std::vector<ClassFieldExpression> fields)
+ : AstNode(kKind, pos),
+ methods(std::move(methods)),
+ fields(std::move(fields)) {}
+ std::vector<Declaration*> methods;
+ std::vector<ClassFieldExpression> fields;
+};
+
struct ClassDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration)
ClassDeclaration(SourcePosition pos, Identifier* name, ClassFlags flags,
base::Optional<TypeExpression*> super,
base::Optional<std::string> generates,
std::vector<Declaration*> methods,
- std::vector<ClassFieldExpression> fields)
+ std::vector<ClassFieldExpression> fields,
+ InstanceTypeConstraints instance_type_constraints)
: TypeDeclaration(kKind, pos, name),
flags(flags),
super(super),
generates(std::move(generates)),
methods(std::move(methods)),
- fields(std::move(fields)) {}
+ fields(std::move(fields)),
+ instance_type_constraints(std::move(instance_type_constraints)) {}
ClassFlags flags;
base::Optional<TypeExpression*> super;
base::Optional<std::string> generates;
std::vector<Declaration*> methods;
std::vector<ClassFieldExpression> fields;
+ InstanceTypeConstraints instance_type_constraints;
};
struct CppIncludeDeclaration : Declaration {
diff --git a/deps/v8/src/torque/class-debug-reader-generator.cc b/deps/v8/src/torque/class-debug-reader-generator.cc
index 6abdffcc91..fca2409959 100644
--- a/deps/v8/src/torque/class-debug-reader-generator.cc
+++ b/deps/v8/src/torque/class-debug-reader-generator.cc
@@ -10,12 +10,20 @@ namespace v8 {
namespace internal {
namespace torque {
+const char* tq_object_override_decls =
+ R"( std::vector<std::unique_ptr<ObjectProperty>> GetProperties(
+ d::MemoryAccessor accessor) const override;
+ const char* GetName() const override;
+ void Visit(TqObjectVisitor* visitor) const override;
+ bool IsSuperclassOf(const TqObject* other) const override;
+)";
+
namespace {
void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
std::ostream& cc_contents, std::ostream& visitor,
std::unordered_set<const ClassType*>* done) {
// Make sure each class only gets generated once.
- if (!type.IsExtern() || !done->insert(&type).second) return;
+ if (!done->insert(&type).second) return;
const ClassType* super_type = type.GetSuperClass();
// We must emit the classes in dependency order. If the super class hasn't
@@ -25,6 +33,10 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
done);
}
+ // Classes with undefined layout don't grant any particular value here and may
+ // not correspond with actual C++ classes, so skip them.
+ if (type.HasUndefinedLayout()) return;
+
const std::string name = type.name();
const std::string super_name =
super_type == nullptr ? "Object" : super_type->name();
@@ -32,10 +44,7 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
h_contents << " public:\n";
h_contents << " inline Tq" << name << "(uintptr_t address) : Tq"
<< super_name << "(address) {}\n";
- h_contents << " std::vector<std::unique_ptr<ObjectProperty>> "
- "GetProperties(d::MemoryAccessor accessor) const override;\n";
- h_contents << " const char* GetName() const override;\n";
- h_contents << " void Visit(TqObjectVisitor* visitor) const override;\n";
+ h_contents << tq_object_override_decls;
cc_contents << "\nconst char* Tq" << name << "::GetName() const {\n";
cc_contents << " return \"v8::internal::" << name << "\";\n";
@@ -46,6 +55,13 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
cc_contents << " visitor->Visit" << name << "(this);\n";
cc_contents << "}\n";
+ cc_contents << "\nbool Tq" << name
+ << "::IsSuperclassOf(const TqObject* other) const {\n";
+ cc_contents
+ << " return GetName() != other->GetName() && dynamic_cast<const Tq"
+ << name << "*>(other) != nullptr;\n";
+ cc_contents << "}\n";
+
visitor << " virtual void Visit" << name << "(const Tq" << name
<< "* object) {\n";
visitor << " Visit" << super_name << "(object);\n";
@@ -71,9 +87,10 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
if (is_field_tagged) {
field_value_type = "uintptr_t";
field_value_type_compressed = "i::Tagged_t";
- field_cc_type = "v8::internal::" + (field_class_type.has_value()
- ? (*field_class_type)->name()
- : "Object");
+ field_cc_type = "v8::internal::" +
+ (field_class_type.has_value()
+ ? (*field_class_type)->GetGeneratedTNodeTypeName()
+ : "Object");
field_cc_type_compressed =
COMPRESS_POINTERS_BOOL ? "v8::internal::TaggedValue" : field_cc_type;
} else {
@@ -107,7 +124,7 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
std::string index_param;
std::string index_offset;
if (field.index) {
- const Type* index_type = (*field.index)->name_and_type.type;
+ const Type* index_type = field.index->type;
std::string index_type_name;
std::string index_value;
if (index_type == TypeOracle::GetSmiType()) {
@@ -129,18 +146,17 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
}
get_props_impl << " Value<" << index_type_name
<< "> indexed_field_count = Get"
- << CamelifyString((*field.index)->name_and_type.name)
+ << CamelifyString(field.index->name)
<< "Value(accessor);\n";
indexed_field_info =
", " + index_value + ", GetArrayKind(indexed_field_count.validity)";
index_param = ", size_t offset";
index_offset = " + offset * sizeof(value)";
}
- get_props_impl
- << " result.push_back(v8::base::make_unique<ObjectProperty>(\""
- << field_name << "\", \"" << field_cc_type_compressed << "\", \""
- << field_cc_type << "\", " << address_getter << "()"
- << indexed_field_info << "));\n";
+ get_props_impl << " result.push_back(std::make_unique<ObjectProperty>(\""
+ << field_name << "\", \"" << field_cc_type_compressed
+ << "\", \"" << field_cc_type << "\", " << address_getter
+ << "()" << indexed_field_info << "));\n";
h_contents << " uintptr_t " << address_getter << "() const;\n";
h_contents << " Value<" << field_value_type << "> " << field_getter
@@ -158,7 +174,8 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents,
<< address_getter << "()" << index_offset
<< ", reinterpret_cast<uint8_t*>(&value), sizeof(value));\n";
cc_contents << " return {validity, "
- << (is_field_tagged ? "Decompress(value, address_)" : "value")
+ << (is_field_tagged ? "EnsureDecompressed(value, address_)"
+ : "value")
<< "};\n";
cc_contents << "}\n";
}
@@ -192,6 +209,11 @@ void ImplementationVisitor::GenerateClassDebugReaders(
h_contents
<< "\n#include \"tools/debug_helper/debug-helper-internal.h\"\n\n";
+ h_contents << "// Unset a windgi.h macro that causes conflicts.\n";
+ h_contents << "#ifdef GetBValue\n";
+ h_contents << "#undef GetBValue\n";
+ h_contents << "#endif\n\n";
+
cc_contents << "#include \"torque-generated/" << file_name << ".h\"\n";
cc_contents << "#include \"include/v8-internal.h\"\n\n";
cc_contents << "namespace i = v8::internal;\n\n";
diff --git a/deps/v8/src/torque/constants.h b/deps/v8/src/torque/constants.h
index efbbf9588e..ebfbab0cba 100644
--- a/deps/v8/src/torque/constants.h
+++ b/deps/v8/src/torque/constants.h
@@ -55,6 +55,25 @@ static const char* const REFERENCE_TYPE_STRING = "Reference";
static const char* const SLICE_TYPE_STRING = "Slice";
static const char* const STRUCT_NAMESPACE_STRING = "_struct";
+static const char* const ANNOTATION_GENERATE_PRINT = "@generatePrint";
+static const char* const ANNOTATION_NO_VERIFIER = "@noVerifier";
+static const char* const ANNOTATION_ABSTRACT = "@abstract";
+static const char* const ANNOTATION_INSTANTIATED_ABSTRACT_CLASS =
+ "@dirtyInstantiatedAbstractClass";
+static const char* const ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT =
+ "@hasSameInstanceTypeAsParent";
+static const char* const ANNOTATION_GENERATE_CPP_CLASS = "@generateCppClass";
+static const char* const ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT =
+ "@highestInstanceTypeWithinParentClassRange";
+static const char* const ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT =
+ "@lowestInstanceTypeWithinParentClassRange";
+static const char* const ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE =
+ "@reserveBitsInInstanceType";
+static const char* const ANNOTATION_INSTANCE_TYPE_VALUE =
+ "@apiExposedInstanceTypeValue";
+static const char* const ANNOTATION_IF = "@if";
+static const char* const ANNOTATION_IFNOT = "@ifnot";
+
inline bool IsConstexprName(const std::string& name) {
return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) ==
CONSTEXPR_TYPE_PREFIX;
@@ -80,7 +99,10 @@ enum class ClassFlag {
kInstantiatedAbstractClass = 1 << 5,
kHasSameInstanceTypeAsParent = 1 << 6,
kGenerateCppClassDefinitions = 1 << 7,
- kHasIndexedField = 1 << 8
+ kHasIndexedField = 1 << 8,
+ kHighestInstanceTypeWithinParent = 1 << 9,
+ kLowestInstanceTypeWithinParent = 1 << 10,
+ kUndefinedLayout = 1 << 11,
};
using ClassFlags = base::Flags<ClassFlag>;
diff --git a/deps/v8/src/torque/csa-generator.cc b/deps/v8/src/torque/csa-generator.cc
index 7925783914..2a10e4f353 100644
--- a/deps/v8/src/torque/csa-generator.cc
+++ b/deps/v8/src/torque/csa-generator.cc
@@ -41,7 +41,7 @@ Stack<std::string> CSAGenerator::EmitBlock(const Block* block) {
Stack<std::string> stack;
for (const Type* t : block->InputTypes()) {
stack.Push(FreshNodeName());
- out_ << " compiler::TNode<" << t->GetGeneratedTNodeTypeName() << "> "
+ out_ << " TNode<" << t->GetGeneratedTNodeTypeName() << "> "
<< stack.Top() << ";\n";
}
out_ << " ca_.Bind(&" << BlockName(block);
@@ -56,14 +56,10 @@ Stack<std::string> CSAGenerator::EmitBlock(const Block* block) {
}
void CSAGenerator::EmitSourcePosition(SourcePosition pos, bool always_emit) {
- std::string file = SourceFileMap::AbsolutePath(pos.source);
+ const std::string& file = SourceFileMap::AbsolutePath(pos.source);
if (always_emit || !previous_position_.CompareStartIgnoreColumn(pos)) {
// Lines in Torque SourcePositions are zero-based, while the
// CodeStubAssembler and downwind systems are one-based.
- for (auto& c : file) {
- if (c == '\\')
- c = '/';
- }
out_ << " ca_.SetSourcePosition(\"" << file << "\", "
<< (pos.start.line + 1) << ");\n";
previous_position_ = pos;
@@ -123,8 +119,8 @@ void CSAGenerator::EmitInstruction(
for (const Type* lowered : LowerType(type)) {
results.push_back(FreshNodeName());
stack->Push(results.back());
- out_ << " compiler::TNode<" << lowered->GetGeneratedTNodeTypeName()
- << "> " << stack->Top() << ";\n";
+ out_ << " TNode<" << lowered->GetGeneratedTNodeTypeName() << "> "
+ << stack->Top() << ";\n";
out_ << " USE(" << stack->Top() << ");\n";
}
out_ << " ";
@@ -179,7 +175,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
for (const Type* type : LowerType(return_type)) {
results.push_back(FreshNodeName());
stack->Push(results.back());
- out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
+ out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> "
<< stack->Top() << ";\n";
out_ << " USE(" << stack->Top() << ");\n";
}
@@ -302,7 +298,7 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
for (const Type* type : LowerType(return_type)) {
results.push_back(FreshNodeName());
stack->Push(results.back());
- out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> "
+ out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> "
<< stack->Top() << ";\n";
out_ << " USE(" << stack->Top() << ");\n";
}
@@ -354,8 +350,8 @@ void CSAGenerator::EmitInstruction(
for (const Type* type :
LowerType(instruction.macro->signature().return_type)) {
results.push_back(FreshNodeName());
- out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName()
- << "> " << results.back() << ";\n";
+ out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> "
+ << results.back() << ";\n";
out_ << " USE(" << results.back() << ");\n";
}
}
@@ -453,9 +449,8 @@ void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction,
} else {
std::string result_name = FreshNodeName();
if (result_types.size() == 1) {
- out_ << " compiler::TNode<"
- << result_types[0]->GetGeneratedTNodeTypeName() << "> "
- << result_name << ";\n";
+ out_ << " TNode<" << result_types[0]->GetGeneratedTNodeTypeName()
+ << "> " << result_name << ";\n";
}
std::string catch_name =
PreCallableExceptionPreparation(instruction.catch_block);
@@ -503,8 +498,7 @@ void CSAGenerator::EmitInstruction(
stack->Push(FreshNodeName());
std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
- out_ << " compiler::TNode<" << generated_type << "> " << stack->Top()
- << " = ";
+ out_ << " TNode<" << generated_type << "> " << stack->Top() << " = ";
if (generated_type != "Object") out_ << "TORQUE_CAST(";
out_ << "CodeStubAssembler(state_).CallBuiltinPointer(Builtins::"
"CallableFor(ca_."
@@ -543,8 +537,7 @@ void CSAGenerator::PostCallableExceptionPreparation(
if (!return_type->IsNever()) {
out_ << " ca_.Goto(&" << catch_name << "_skip);\n";
}
- out_ << " compiler::TNode<Object> " << catch_name
- << "_exception_object;\n";
+ out_ << " TNode<Object> " << catch_name << "_exception_object;\n";
out_ << " ca_.Bind(&" << catch_name << "__label, &" << catch_name
<< "_exception_object);\n";
out_ << " ca_.Goto(&" << block_name;
@@ -579,9 +572,8 @@ void CSAGenerator::EmitInstruction(const CallRuntimeInstruction& instruction,
} else {
std::string result_name = FreshNodeName();
if (result_types.size() == 1) {
- out_ << " compiler::TNode<"
- << result_types[0]->GetGeneratedTNodeTypeName() << "> "
- << result_name << ";\n";
+ out_ << " TNode<" << result_types[0]->GetGeneratedTNodeTypeName()
+ << "> " << result_name << ";\n";
}
std::string catch_name =
PreCallableExceptionPreparation(instruction.catch_block);
@@ -722,10 +714,9 @@ void CSAGenerator::EmitInstruction(
std::string offset_name = FreshNodeName();
stack->Push(offset_name);
- out_ << " compiler::TNode<IntPtrT> " << offset_name
- << " = ca_.IntPtrConstant(";
- out_ << field.aggregate->GetGeneratedTNodeTypeName() << "::k"
- << CamelifyString(field.name_and_type.name) << "Offset";
+ out_ << " TNode<IntPtrT> " << offset_name << " = ca_.IntPtrConstant(";
+ out_ << field.aggregate->GetGeneratedTNodeTypeName() << "::k"
+ << CamelifyString(field.name_and_type.name) << "Offset";
out_ << ");\n"
<< " USE(" << stack->Top() << ");\n";
}
@@ -776,8 +767,8 @@ void CSAGenerator::EmitCSAValue(VisitResult result,
out << "}";
} else {
DCHECK_EQ(1, result.stack_range().Size());
- out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName()
- << ">{" << values.Peek(result.stack_range().begin()) << "}";
+ out << "TNode<" << result.type()->GetGeneratedTNodeTypeName() << ">{"
+ << values.Peek(result.stack_range().begin()) << "}";
}
}
diff --git a/deps/v8/src/torque/declaration-visitor.cc b/deps/v8/src/torque/declaration-visitor.cc
index f762337463..c2fa1af98e 100644
--- a/deps/v8/src/torque/declaration-visitor.cc
+++ b/deps/v8/src/torque/declaration-visitor.cc
@@ -93,20 +93,6 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
}
}
- if (TorqueBuiltinDeclaration::DynamicCast(decl)) {
- for (size_t i = 0; i < signature.types().size(); ++i) {
- const Type* type = signature.types()[i];
- if (!type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
- const Identifier* id = signature.parameter_names.size() > i
- ? signature.parameter_names[i]
- : nullptr;
- Error("Untagged argument ", id ? (id->value + " ") : "", "at position ",
- i, " to builtin ", decl->name, " is not supported.")
- .Position(id ? id->pos : decl->pos);
- }
- }
- }
-
if (const StructType* struct_type =
StructType::DynamicCast(signature.return_type)) {
Error("Builtins ", decl->name, " cannot return structs ",
diff --git a/deps/v8/src/torque/declarations.h b/deps/v8/src/torque/declarations.h
index 240680fa1e..f3d2544ae1 100644
--- a/deps/v8/src/torque/declarations.h
+++ b/deps/v8/src/torque/declarations.h
@@ -5,6 +5,7 @@
#ifndef V8_TORQUE_DECLARATIONS_H_
#define V8_TORQUE_DECLARATIONS_H_
+#include <memory>
#include <string>
#include "src/torque/declarable.h"
diff --git a/deps/v8/src/torque/earley-parser.h b/deps/v8/src/torque/earley-parser.h
index 9f7ba6a7ae..43ad6eb452 100644
--- a/deps/v8/src/torque/earley-parser.h
+++ b/deps/v8/src/torque/earley-parser.h
@@ -6,6 +6,7 @@
#define V8_TORQUE_EARLEY_PARSER_H_
#include <map>
+#include <memory>
#include <vector>
#include "src/base/optional.h"
@@ -82,6 +83,7 @@ enum class ParseResultHolderBase::TypeId {
kTypeswitchCase,
kStdVectorOfTypeswitchCase,
kStdVectorOfIdentifierPtr,
+ kOptionalClassBody,
kJsonValue,
kJsonMember,
@@ -248,7 +250,7 @@ class Symbol {
size_t rule_number() const { return rules_.size(); }
void AddRule(const Rule& rule) {
- rules_.push_back(base::make_unique<Rule>(rule));
+ rules_.push_back(std::make_unique<Rule>(rule));
rules_.back()->SetLeftHandSide(this);
}
diff --git a/deps/v8/src/torque/global-context.cc b/deps/v8/src/torque/global-context.cc
index 13503038c5..e236de5a93 100644
--- a/deps/v8/src/torque/global-context.cc
+++ b/deps/v8/src/torque/global-context.cc
@@ -19,7 +19,7 @@ GlobalContext::GlobalContext(Ast ast)
CurrentSourcePosition::Scope current_source_position(
SourcePosition{CurrentSourceFile::Get(), {-1, -1}, {-1, -1}});
default_namespace_ =
- RegisterDeclarable(base::make_unique<Namespace>(kBaseNamespaceName));
+ RegisterDeclarable(std::make_unique<Namespace>(kBaseNamespaceName));
}
TargetArchitecture::TargetArchitecture(bool force_32bit)
diff --git a/deps/v8/src/torque/global-context.h b/deps/v8/src/torque/global-context.h
index e1106adbd1..940325b51a 100644
--- a/deps/v8/src/torque/global-context.h
+++ b/deps/v8/src/torque/global-context.h
@@ -6,6 +6,7 @@
#define V8_TORQUE_GLOBAL_CONTEXT_H_
#include <map>
+#include <memory>
#include "src/common/globals.h"
#include "src/torque/ast.h"
diff --git a/deps/v8/src/torque/implementation-visitor.cc b/deps/v8/src/torque/implementation-visitor.cc
index 8f36afd020..0c50a70099 100644
--- a/deps/v8/src/torque/implementation-visitor.cc
+++ b/deps/v8/src/torque/implementation-visitor.cc
@@ -526,7 +526,6 @@ void ImplementationVisitor::Visit(Builtin* builtin) {
source_out() << " USE(" << parameter0 << ");\n";
for (size_t i = 1; i < signature.parameter_names.size(); ++i) {
- const std::string& parameter_name = signature.parameter_names[i]->value;
const Type* type = signature.types()[i];
const bool mark_as_used = signature.implicit_count > i;
std::string var = AddParameter(i, builtin, &parameters, &parameter_types,
@@ -534,8 +533,8 @@ void ImplementationVisitor::Visit(Builtin* builtin) {
source_out() << " " << type->GetGeneratedTypeName() << " " << var
<< " = "
<< "UncheckedCast<" << type->GetGeneratedTNodeTypeName()
- << ">(Parameter(Descriptor::k"
- << CamelifyString(parameter_name) << "));\n";
+ << ">(Parameter(Descriptor::ParameterIndex<" << (i - 1)
+ << ">()));\n";
source_out() << " USE(" << var << ");\n";
}
}
@@ -1008,48 +1007,40 @@ const Type* ImplementationVisitor::Visit(AssertStatement* stmt) {
#if defined(DEBUG)
do_check = true;
#endif
- if (do_check) {
- // CSA_ASSERT & co. are not used here on purpose for two reasons. First,
- // Torque allows and handles two types of expressions in the if protocol
- // automagically, ones that return TNode<BoolT> and those that use the
- // BranchIf(..., Label* true, Label* false) idiom. Because the machinery to
- // handle this is embedded in the expression handling and to it's not
- // possible to make the decision to use CSA_ASSERT or CSA_ASSERT_BRANCH
- // isn't trivial up-front. Secondly, on failure, the assert text should be
- // the corresponding Torque code, not the -gen.cc code, which would be the
- // case when using CSA_ASSERT_XXX.
- Block* true_block = assembler().NewBlock(assembler().CurrentStack());
- Block* false_block = assembler().NewBlock(assembler().CurrentStack(), true);
- GenerateExpressionBranch(stmt->expression, true_block, false_block);
+ Block* resume_block;
+
+ if (!do_check) {
+ Block* unreachable_block = assembler().NewBlock(assembler().CurrentStack());
+ resume_block = assembler().NewBlock(assembler().CurrentStack());
+ assembler().Goto(resume_block);
+ assembler().Bind(unreachable_block);
+ }
+
+ // CSA_ASSERT & co. are not used here on purpose for two reasons. First,
+ // Torque allows and handles two types of expressions in the if protocol
+ // automagically, ones that return TNode<BoolT> and those that use the
+ // BranchIf(..., Label* true, Label* false) idiom. Because the machinery to
+ // handle this is embedded in the expression handling and to it's not
+ // possible to make the decision to use CSA_ASSERT or CSA_ASSERT_BRANCH
+ // isn't trivial up-front. Secondly, on failure, the assert text should be
+ // the corresponding Torque code, not the -gen.cc code, which would be the
+ // case when using CSA_ASSERT_XXX.
+ Block* true_block = assembler().NewBlock(assembler().CurrentStack());
+ Block* false_block = assembler().NewBlock(assembler().CurrentStack(), true);
+ GenerateExpressionBranch(stmt->expression, true_block, false_block);
- assembler().Bind(false_block);
+ assembler().Bind(false_block);
- assembler().Emit(AbortInstruction{
- AbortInstruction::Kind::kAssertionFailure,
- "Torque assert '" + FormatAssertSource(stmt->source) + "' failed"});
+ assembler().Emit(AbortInstruction{
+ AbortInstruction::Kind::kAssertionFailure,
+ "Torque assert '" + FormatAssertSource(stmt->source) + "' failed"});
- assembler().Bind(true_block);
- } else {
- // Visit the expression so bindings only used in asserts are marked
- // as such. Otherwise they might be wrongly reported as unused bindings
- // in release builds.
- stmt->expression->VisitAllSubExpressions([](Expression* expression) {
- if (auto id = IdentifierExpression::DynamicCast(expression)) {
- ValueBindingsManager::Get().TryLookup(id->name->value);
- } else if (auto call = CallExpression::DynamicCast(expression)) {
- for (Identifier* label : call->labels) {
- LabelBindingsManager::Get().TryLookup(label->value);
- }
- // TODO(szuend): In case the call expression resolves to a macro
- // callable, mark the macro as used as well.
- } else if (auto call = CallMethodExpression::DynamicCast(expression)) {
- for (Identifier* label : call->labels) {
- LabelBindingsManager::Get().TryLookup(label->value);
- }
- // TODO(szuend): Mark the underlying macro as used.
- }
- });
+ assembler().Bind(true_block);
+
+ if (!do_check) {
+ assembler().Bind(resume_block);
}
+
return TypeOracle::GetVoidType();
}
@@ -1214,16 +1205,16 @@ InitializerResults ImplementationVisitor::VisitInitializerResults(
result.names.push_back(initializer.name);
Expression* e = initializer.expression;
const Field& field = class_type->LookupField(initializer.name->value);
- auto field_index = field.index;
+ bool has_index = field.index.has_value();
if (SpreadExpression* s = SpreadExpression::DynamicCast(e)) {
- if (!field_index) {
+ if (!has_index) {
ReportError(
"spread expressions can only be used to initialize indexed class "
"fields ('",
initializer.name->value, "' is not)");
}
e = s->spreadee;
- } else if (field_index) {
+ } else if (has_index) {
ReportError("the indexed class field '", initializer.name->value,
"' must be initialized with a spread operator");
}
@@ -1261,7 +1252,7 @@ void ImplementationVisitor::InitializeClass(
void ImplementationVisitor::InitializeFieldFromSpread(
VisitResult object, const Field& field,
const InitializerResults& initializer_results) {
- NameAndType index = (*field.index)->name_and_type;
+ const NameAndType& index = *field.index;
VisitResult iterator =
initializer_results.field_value_map.at(field.name_and_type.name);
VisitResult length = initializer_results.field_value_map.at(index.name);
@@ -1289,15 +1280,14 @@ VisitResult ImplementationVisitor::AddVariableObjectSize(
}
VisitResult index_field_size =
VisitResult(TypeOracle::GetConstInt31Type(), "kTaggedSize");
- VisitResult initializer_value = initializer_results.field_value_map.at(
- (*current_field->index)->name_and_type.name);
+ VisitResult initializer_value =
+ initializer_results.field_value_map.at(current_field->index->name);
Arguments args;
args.parameters.push_back(object_size);
args.parameters.push_back(initializer_value);
args.parameters.push_back(index_field_size);
- object_size =
- GenerateCall("%AddIndexedFieldSizeToObjectSize", args,
- {(*current_field->index)->name_and_type.type}, false);
+ object_size = GenerateCall("%AddIndexedFieldSizeToObjectSize", args,
+ {current_field->index->type}, false);
}
++current_field;
}
@@ -1860,12 +1850,12 @@ LocationReference ImplementationVisitor::GetLocationReference(
{
StackScope length_scope(this);
// Get a reference to the length
- const Field* index_field = field.index.value();
+ const NameAndType& index_field = field.index.value();
GenerateCopy(object_result);
- assembler().Emit(CreateFieldReferenceInstruction{
- object_result.type(), index_field->name_and_type.name});
+ assembler().Emit(CreateFieldReferenceInstruction{object_result.type(),
+ index_field.name});
VisitResult length_reference(
- TypeOracle::GetReferenceType(index_field->name_and_type.type),
+ TypeOracle::GetReferenceType(index_field.type),
assembler().TopRange(2));
// Load the length from the reference and convert it to intptr
@@ -2670,13 +2660,34 @@ void ImplementationVisitor::Visit(Declarable* declarable) {
}
}
-void ImplementationVisitor::GenerateBuiltinDefinitions(
+std::string MachineTypeString(const Type* type) {
+ if (type->IsSubtypeOf(TypeOracle::GetSmiType())) {
+ return "MachineType::TaggedSigned()";
+ }
+ if (type->IsSubtypeOf(TypeOracle::GetHeapObjectType())) {
+ return "MachineType::TaggedPointer()";
+ }
+ if (type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
+ return "MachineType::AnyTagged()";
+ }
+ return "MachineTypeOf<" + type->GetGeneratedTNodeTypeName() + ">::value";
+}
+
+void ImplementationVisitor::GenerateBuiltinDefinitionsAndInterfaceDescriptors(
const std::string& output_directory) {
- std::stringstream new_contents_stream;
- std::string file_name = "builtin-definitions-tq.h";
+ std::stringstream builtin_definitions;
+ std::string builtin_definitions_file_name = "builtin-definitions-tq.h";
+
+ // This file contains plain interface descriptor definitions and has to be
+ // included in the middle of interface-descriptors.h. Thus it is not a normal
+ // header file and uses the .inc suffix instead of the .h suffix.
+ std::stringstream interface_descriptors;
+ std::string interface_descriptors_file_name = "interface-descriptors-tq.inc";
{
- IncludeGuardScope include_guard(new_contents_stream, file_name);
- new_contents_stream
+ IncludeGuardScope builtin_definitions_include_guard(
+ builtin_definitions, builtin_definitions_file_name);
+
+ builtin_definitions
<< "\n"
"#define BUILTIN_LIST_FROM_TORQUE(CPP, TFJ, TFC, TFS, TFH, "
"ASM) "
@@ -2684,40 +2695,67 @@ void ImplementationVisitor::GenerateBuiltinDefinitions(
for (auto& declarable : GlobalContext::AllDeclarables()) {
Builtin* builtin = Builtin::DynamicCast(declarable.get());
if (!builtin || builtin->IsExternal()) continue;
- size_t firstParameterIndex = 1;
- bool declareParameters = true;
if (builtin->IsStub()) {
- new_contents_stream << "TFS(" << builtin->ExternalName();
+ builtin_definitions << "TFC(" << builtin->ExternalName() << ", "
+ << builtin->ExternalName();
+ std::string descriptor_name = builtin->ExternalName() + "Descriptor";
+ constexpr size_t kFirstNonContextParameter = 1;
+ size_t parameter_count =
+ builtin->parameter_names().size() - kFirstNonContextParameter;
+
+ interface_descriptors << "class " << descriptor_name
+ << " : public TorqueInterfaceDescriptor<"
+ << parameter_count << "> {\n";
+ interface_descriptors << " DECLARE_DESCRIPTOR_WITH_BASE("
+ << descriptor_name
+ << ", TorqueInterfaceDescriptor)\n";
+
+ interface_descriptors << " MachineType ReturnType() override {\n";
+ interface_descriptors
+ << " return "
+ << MachineTypeString(builtin->signature().return_type) << ";\n";
+ interface_descriptors << " }\n";
+
+ interface_descriptors << " std::array<MachineType, " << parameter_count
+ << "> ParameterTypes() override {\n";
+ interface_descriptors << " return {";
+ for (size_t i = kFirstNonContextParameter;
+ i < builtin->parameter_names().size(); ++i) {
+ bool last = i + 1 == builtin->parameter_names().size();
+ const Type* type = builtin->signature().parameter_types.types[i];
+ interface_descriptors << MachineTypeString(type)
+ << (last ? "" : ", ");
+ }
+ interface_descriptors << "};\n";
+
+ interface_descriptors << " }\n";
+ interface_descriptors << "};\n\n";
} else {
- new_contents_stream << "TFJ(" << builtin->ExternalName();
+ builtin_definitions << "TFJ(" << builtin->ExternalName();
if (builtin->IsVarArgsJavaScript()) {
- new_contents_stream
+ builtin_definitions
<< ", SharedFunctionInfo::kDontAdaptArgumentsSentinel";
- declareParameters = false;
} else {
DCHECK(builtin->IsFixedArgsJavaScript());
// FixedArg javascript builtins need to offer the parameter
// count.
int parameter_count =
static_cast<int>(builtin->signature().ExplicitCount());
- new_contents_stream << ", " << parameter_count;
+ builtin_definitions << ", " << parameter_count;
// And the receiver is explicitly declared.
- new_contents_stream << ", kReceiver";
- firstParameterIndex = builtin->signature().implicit_count;
- }
- }
- if (declareParameters) {
- for (size_t i = firstParameterIndex;
- i < builtin->parameter_names().size(); ++i) {
- Identifier* parameter = builtin->parameter_names()[i];
- new_contents_stream << ", k" << CamelifyString(parameter->value);
+ builtin_definitions << ", kReceiver";
+ for (size_t i = builtin->signature().implicit_count;
+ i < builtin->parameter_names().size(); ++i) {
+ Identifier* parameter = builtin->parameter_names()[i];
+ builtin_definitions << ", k" << CamelifyString(parameter->value);
+ }
}
}
- new_contents_stream << ") \\\n";
+ builtin_definitions << ") \\\n";
}
- new_contents_stream << "\n";
+ builtin_definitions << "\n";
- new_contents_stream
+ builtin_definitions
<< "#define TORQUE_FUNCTION_POINTER_TYPE_TO_BUILTIN_MAP(V) \\\n";
for (const BuiltinPointerType* type :
TypeOracle::AllBuiltinPointerTypes()) {
@@ -2728,13 +2766,15 @@ void ImplementationVisitor::GenerateBuiltinDefinitions(
SourcePosition{CurrentSourceFile::Get(), {-1, -1}, {-1, -1}});
ReportError("unable to find any builtin with type \"", *type, "\"");
}
- new_contents_stream << " V(" << type->function_pointer_type_id() << ","
+ builtin_definitions << " V(" << type->function_pointer_type_id() << ","
<< example_builtin->ExternalName() << ")\\\n";
}
- new_contents_stream << "\n";
+ builtin_definitions << "\n";
}
- std::string new_contents(new_contents_stream.str());
- WriteFile(output_directory + "/" + file_name, new_contents);
+ WriteFile(output_directory + "/" + builtin_definitions_file_name,
+ builtin_definitions.str());
+ WriteFile(output_directory + "/" + interface_descriptors_file_name,
+ interface_descriptors.str());
}
namespace {
@@ -2894,40 +2934,8 @@ class MacroFieldOffsetsGenerator : public FieldOffsetsGenerator {
private:
std::ostream& out_;
};
-} // namespace
-
-void ImplementationVisitor::GenerateInstanceTypes(
- const std::string& output_directory) {
- std::stringstream header;
- std::string file_name = "instance-types-tq.h";
- {
- IncludeGuardScope(header, file_name);
- header << "#define TORQUE_DEFINED_INSTANCE_TYPES(V) \\\n";
- for (const TypeAlias* alias : GlobalContext::GetClasses()) {
- const ClassType* type = ClassType::DynamicCast(alias->type());
- if (type->IsExtern()) continue;
- std::string type_name =
- CapifyStringWithUnderscores(type->name()) + "_TYPE";
- header << " V(" << type_name << ") \\\n";
- }
- header << "\n\n";
-
- header << "#define TORQUE_STRUCT_LIST_GENERATOR(V, _) \\\n";
- for (const TypeAlias* alias : GlobalContext::GetClasses()) {
- const ClassType* type = ClassType::DynamicCast(alias->type());
- if (type->IsExtern()) continue;
- std::string type_name =
- CapifyStringWithUnderscores(type->name()) + "_TYPE";
- std::string variable_name = SnakeifyString(type->name());
- header << " V(_, " << type_name << ", " << type->name() << ", "
- << variable_name << ") \\\n";
- }
- header << "\n";
- }
- std::string output_header_path = output_directory + "/" + file_name;
- WriteFile(output_header_path, header.str());
-}
+} // namespace
void ImplementationVisitor::GenerateCppForInternalClasses(
const std::string& output_directory) {
@@ -3148,7 +3156,7 @@ void CppClassGenerator::GenerateClassConstructors() {
if (type_->IsInstantiatedAbstractClass()) {
// This is a hack to prevent wrong instance type checks.
inl_ << " // Instance check omitted because class is annotated with "
- "@dirtyInstantiatedAbstractClass.\n";
+ << ANNOTATION_INSTANTIATED_ABSTRACT_CLASS << ".\n";
} else {
inl_ << " SLOW_DCHECK(this->Is" << name_ << "());\n";
}
@@ -3241,7 +3249,8 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) {
const std::string offset = "k" + CamelifyString(name) + "Offset";
base::Optional<const ClassType*> class_type = field_type->ClassSupertype();
- std::string type = class_type ? (*class_type)->name() : "Object";
+ std::string type =
+ class_type ? (*class_type)->GetGeneratedTNodeTypeName() : "Object";
// Generate declarations in header.
if (!class_type && field_type != TypeOracle::GetObjectType()) {
@@ -3302,7 +3311,6 @@ void ImplementationVisitor::GenerateClassDefinitions(
{
IncludeGuardScope header_guard(header, basename + ".h");
- header << "#include \"src/objects/heap-number.h\"\n";
header << "#include \"src/objects/objects.h\"\n";
header << "#include \"src/objects/smi.h\"\n";
header << "#include \"torque-generated/field-offsets-tq.h\"\n";
@@ -3314,9 +3322,11 @@ void ImplementationVisitor::GenerateClassDefinitions(
IncludeGuardScope inline_header_guard(inline_header, basename + "-inl.h");
inline_header << "#include \"torque-generated/class-definitions-tq.h\"\n\n";
inline_header << "#include \"src/objects/js-promise.h\"\n";
+ inline_header << "#include \"src/objects/js-weak-refs.h\"\n";
inline_header << "#include \"src/objects/module.h\"\n";
inline_header << "#include \"src/objects/objects-inl.h\"\n";
- inline_header << "#include \"src/objects/script.h\"\n\n";
+ inline_header << "#include \"src/objects/script.h\"\n";
+ inline_header << "#include \"src/objects/shared-function-info.h\"\n\n";
IncludeObjectMacrosScope inline_header_macros(inline_header);
NamespaceScope inline_header_namespaces(inline_header, {"v8", "internal"});
@@ -3328,6 +3338,7 @@ void ImplementationVisitor::GenerateClassDefinitions(
implementation << "#include \"src/objects/embedder-data-array-inl.h\"\n";
implementation << "#include \"src/objects/js-generator-inl.h\"\n";
implementation << "#include \"src/objects/js-regexp-inl.h\"\n";
+ implementation << "#include \"src/objects/js-weak-refs-inl.h\"\n";
implementation
<< "#include \"src/objects/js-regexp-string-iterator-inl.h\"\n";
implementation << "#include \"src/objects/literal-objects-inl.h\"\n";
@@ -3346,7 +3357,7 @@ void ImplementationVisitor::GenerateClassDefinitions(
// Generate forward declarations for every class.
for (const TypeAlias* alias : GlobalContext::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
- header << "class " << type->name() << ";\n";
+ header << "class " << type->GetGeneratedTNodeTypeName() << ";\n";
}
for (const TypeAlias* alias : GlobalContext::GetClasses()) {
@@ -3439,13 +3450,13 @@ void GenerateClassFieldVerifier(const std::string& class_name,
if (!field_type->IsSubtypeOf(TypeOracle::GetObjectType())) return;
if (f.index) {
- if ((*f.index)->name_and_type.type != TypeOracle::GetSmiType()) {
+ if (f.index->type != TypeOracle::GetSmiType()) {
ReportError("Non-SMI values are not (yet) supported as indexes.");
}
// We already verified the index field because it was listed earlier, so we
// can assume it's safe to read here.
cc_contents << " for (int i = 0; i < TaggedField<Smi, " << class_name
- << "::k" << CamelifyString((*f.index)->name_and_type.name)
+ << "::k" << CamelifyString(f.index->name)
<< "Offset>::load(o).value(); ++i) {\n";
} else {
cc_contents << " {\n";
diff --git a/deps/v8/src/torque/implementation-visitor.h b/deps/v8/src/torque/implementation-visitor.h
index eb1a6c4452..e1ebfeeb17 100644
--- a/deps/v8/src/torque/implementation-visitor.h
+++ b/deps/v8/src/torque/implementation-visitor.h
@@ -5,6 +5,7 @@
#ifndef V8_TORQUE_IMPLEMENTATION_VISITOR_H_
#define V8_TORQUE_IMPLEMENTATION_VISITOR_H_
+#include <memory>
#include <string>
#include "src/base/macros.h"
@@ -260,7 +261,7 @@ class BlockBindings {
void Add(std::string name, T value, bool mark_as_used = false) {
ReportErrorIfAlreadyBound(name);
auto binding =
- base::make_unique<Binding<T>>(manager_, name, std::move(value));
+ std::make_unique<Binding<T>>(manager_, name, std::move(value));
if (mark_as_used) binding->SetUsed();
bindings_.push_back(std::move(binding));
}
@@ -268,7 +269,7 @@ class BlockBindings {
void Add(const Identifier* name, T value, bool mark_as_used = false) {
ReportErrorIfAlreadyBound(name->value);
auto binding =
- base::make_unique<Binding<T>>(manager_, name, std::move(value));
+ std::make_unique<Binding<T>>(manager_, name, std::move(value));
if (mark_as_used) binding->SetUsed();
bindings_.push_back(std::move(binding));
}
@@ -342,7 +343,8 @@ bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
class ImplementationVisitor {
public:
- void GenerateBuiltinDefinitions(const std::string& output_directory);
+ void GenerateBuiltinDefinitionsAndInterfaceDescriptors(
+ const std::string& output_directory);
void GenerateClassFieldOffsets(const std::string& output_directory);
void GeneratePrintDefinitions(const std::string& output_directory);
void GenerateClassDefinitions(const std::string& output_directory);
diff --git a/deps/v8/src/torque/instance-type-generator.cc b/deps/v8/src/torque/instance-type-generator.cc
new file mode 100644
index 0000000000..275e706485
--- /dev/null
+++ b/deps/v8/src/torque/instance-type-generator.cc
@@ -0,0 +1,376 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/torque/implementation-visitor.h"
+
+namespace v8 {
+namespace internal {
+namespace torque {
+
+namespace {
+
+// Contains all necessary state for a single class type during the process of
+// assigning instance types, and provides a convenient way to access the list of
+// types that inherit from this one.
+struct InstanceTypeTree {
+ explicit InstanceTypeTree(const ClassType* type)
+ : type(type),
+ parent(nullptr),
+ start(INT_MAX),
+ end(INT_MIN),
+ value(-1),
+ num_values(0),
+ num_own_values(0) {}
+ const ClassType* type;
+ InstanceTypeTree* parent;
+ std::vector<std::unique_ptr<InstanceTypeTree>> children;
+ int start; // Start of range for this and subclasses, or INT_MAX.
+ int end; // End of range for this and subclasses, or INT_MIN.
+ int value; // Assigned value for this class itself, or -1 when unassigned.
+ int num_values; // Number of values assigned for this and subclasses.
+ int num_own_values; // How many values this needs (not including subclasses).
+};
+
+// Assembles all class types into a tree, but doesn't yet attempt to assign
+// instance types for them.
+std::unique_ptr<InstanceTypeTree> BuildInstanceTypeTree() {
+ // First, build InstanceTypeTree instances for every class but don't try to
+ // attach them to their subclasses yet.
+ std::unordered_map<const ClassType*, InstanceTypeTree*> map_by_type;
+ std::vector<std::unique_ptr<InstanceTypeTree>> unparented_types;
+ for (auto& p : GlobalContext::AllDeclarables()) {
+ if (const TypeAlias* alias = TypeAlias::DynamicCast(p.get())) {
+ const Type* type = alias->type();
+ const ClassType* class_type = ClassType::DynamicCast(type);
+ if (class_type == nullptr) {
+ continue;
+ }
+ auto& map_slot = map_by_type[class_type];
+ if (map_slot != nullptr) {
+ continue; // We already encountered this type.
+ }
+ std::unique_ptr<InstanceTypeTree> type_tree =
+ std::make_unique<InstanceTypeTree>(class_type);
+ map_slot = type_tree.get();
+ unparented_types.push_back(std::move(type_tree));
+ }
+ }
+
+ // Second, assemble them all into a tree following the inheritance hierarchy.
+ std::unique_ptr<InstanceTypeTree> root;
+ for (auto& type_tree : unparented_types) {
+ const ClassType* parent = type_tree->type->GetSuperClass();
+ if (parent == nullptr) {
+ if (root != nullptr)
+ Error("Expected only one root class type. Found: ", root->type->name(),
+ " and ", type_tree->type->name())
+ .Position(type_tree->type->GetPosition());
+ root = std::move(type_tree);
+ } else {
+ map_by_type[parent]->children.push_back(std::move(type_tree));
+ }
+ }
+ return root;
+}
+
+// Propagates constraints about instance types from children to their parents.
+void PropagateInstanceTypeConstraints(InstanceTypeTree* root) {
+ for (auto& child : root->children) {
+ PropagateInstanceTypeConstraints(child.get());
+ if (child->start < root->start) root->start = child->start;
+ if (child->end > root->end) root->end = child->end;
+ root->num_values += child->num_values;
+ }
+ const InstanceTypeConstraints& constraints =
+ root->type->GetInstanceTypeConstraints();
+ if ((!root->type->IsAbstract() ||
+ root->type->IsInstantiatedAbstractClass()) &&
+ !root->type->HasSameInstanceTypeAsParent()) {
+ root->num_own_values = 1;
+ }
+ root->num_values += root->num_own_values;
+ if (constraints.num_flags_bits != -1) {
+ // Children won't get any types assigned; must be done manually in C++.
+ root->children.clear();
+ root->num_values = 1 << constraints.num_flags_bits;
+ root->num_own_values = root->num_values;
+ root->start = 0;
+ root->end = root->num_values - 1;
+ }
+ if (constraints.value != -1) {
+ if (root->num_own_values != 1) {
+ Error("Instance type value requested for abstract class ",
+ root->type->name())
+ .Position(root->type->GetPosition());
+ }
+ root->value = constraints.value;
+ if (constraints.value < root->start) root->start = constraints.value;
+ if (constraints.value > root->end) root->end = constraints.value;
+ }
+}
+
+// Assigns values for the type itself, not including any children. Returns the
+// next available value.
+int SelectOwnValues(InstanceTypeTree* root, int start_value) {
+ if (root->value == -1) {
+ root->value = start_value;
+ } else if (root->value < start_value) {
+ Error("Failed to assign instance type ", root->value, " to ",
+ root->type->name())
+ .Position(root->type->GetPosition());
+ }
+ return root->value + root->num_own_values;
+}
+
+// Sorting function for types that don't have specific values they must include.
+// Prioritizes bigger type ranges (those with more subtypes) first, and
+// then sorts alphabetically within each size category.
+struct CompareUnconstrainedTypes {
+ constexpr bool operator()(const InstanceTypeTree* a,
+ const InstanceTypeTree* b) const {
+ return (a->num_values > b->num_values)
+ ? true
+ : (a->num_values < b->num_values)
+ ? false
+ : std::less<std::string>()(a->type->name(),
+ b->type->name());
+ }
+};
+
+// Assigns concrete values for every instance type range, and sorts the children
+// at each layer of the tree into increasing order. Appends the newly-assigned
+// tree to the destination vector. Returns the first unassigned value after
+// those that have been used.
+int SolveInstanceTypeConstraints(
+ std::unique_ptr<InstanceTypeTree> root, int start_value,
+ std::vector<std::unique_ptr<InstanceTypeTree>>* destination) {
+ if (root->start < start_value) {
+ Error("Failed to assign instance type ", root->start, " to ",
+ root->type->name())
+ .Position(root->type->GetPosition());
+ }
+
+ // First, separate the children into four groups:
+ // - The one child that must go first, if it exists;
+ // - Children with specific value requirements ("constrained");
+ // - Children without specific value requirements ("unconstrained");
+ // - The one child that must go last, if it exists.
+ std::unique_ptr<InstanceTypeTree> lowest_child;
+ std::unique_ptr<InstanceTypeTree> highest_child;
+ std::multimap<int, std::unique_ptr<InstanceTypeTree>>
+ constrained_children_by_start;
+ // Using std::map because you can't std::move out of a std::set until C++17.
+ std::map<InstanceTypeTree*, std::unique_ptr<InstanceTypeTree>,
+ CompareUnconstrainedTypes>
+ unconstrained_children_by_size;
+ for (auto& child : root->children) {
+ if (child->type->IsHighestInstanceTypeWithinParent()) {
+ if (highest_child) {
+ Error("Two classes requested to be the highest instance type: ",
+ highest_child->type->name(), " and ", child->type->name(),
+ " within range for parent class ", root->type->name())
+ .Position(child->type->GetPosition());
+ }
+ if (child->type->IsLowestInstanceTypeWithinParent()) {
+ Error(
+ "Class requested to be both highest and lowest instance type "
+ "within its parent range: ",
+ child->type->name())
+ .Position(child->type->GetPosition());
+ }
+ highest_child = std::move(child);
+ } else if (child->type->IsLowestInstanceTypeWithinParent()) {
+ if (lowest_child) {
+ Error("Two classes requested to be the lowest instance type: ",
+ lowest_child->type->name(), " and ", child->type->name(),
+ " within range for parent class ", root->type->name())
+ .Position(child->type->GetPosition());
+ }
+ lowest_child = std::move(child);
+ } else if (child->start > child->end) {
+ unconstrained_children_by_size.insert(
+ std::make_pair(child.get(), std::move(child)));
+ } else {
+ constrained_children_by_start.insert(
+ std::make_pair(child->start, std::move(child)));
+ }
+ }
+ root->children.clear();
+
+ bool own_type_pending = root->num_own_values > 0;
+
+ // Second, iterate and place the children in ascending order.
+ if (lowest_child != nullptr) {
+ start_value = SolveInstanceTypeConstraints(std::move(lowest_child),
+ start_value, &root->children);
+ }
+ for (auto& constrained_child_pair : constrained_children_by_start) {
+ // Select the next constrained child type in ascending order.
+ std::unique_ptr<InstanceTypeTree> constrained_child =
+ std::move(constrained_child_pair.second);
+
+ // Try to place the root type before the constrained child type if it fits.
+ if (own_type_pending) {
+ if ((root->value != -1 && root->value < constrained_child->start) ||
+ (root->value == -1 &&
+ start_value + root->num_own_values <= constrained_child->start)) {
+ start_value = SelectOwnValues(root.get(), start_value);
+ own_type_pending = false;
+ }
+ }
+
+ // Try to find any unconstrained children that fit before the constrained
+ // one. This simple greedy algorithm just puts the biggest unconstrained
+ // children in first, which might not fill the space as efficiently as
+ // possible but is good enough for our needs.
+ for (auto it = unconstrained_children_by_size.begin();
+ it != unconstrained_children_by_size.end();) {
+ if (it->second->num_values + start_value <= constrained_child->start) {
+ start_value = SolveInstanceTypeConstraints(
+ std::move(it->second), start_value, &root->children);
+ it = unconstrained_children_by_size.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Place the constrained child type.
+ start_value = SolveInstanceTypeConstraints(std::move(constrained_child),
+ start_value, &root->children);
+ }
+ if (own_type_pending) {
+ start_value = SelectOwnValues(root.get(), start_value);
+ own_type_pending = false;
+ }
+ for (auto& child_pair : unconstrained_children_by_size) {
+ start_value = SolveInstanceTypeConstraints(std::move(child_pair.second),
+ start_value, &root->children);
+ }
+ if (highest_child != nullptr) {
+ start_value = SolveInstanceTypeConstraints(std::move(highest_child),
+ start_value, &root->children);
+ }
+
+ // Finally, set the range for this class to include all placed subclasses.
+ root->end = start_value - 1;
+ root->start =
+ root->children.empty() ? start_value : root->children.front()->start;
+ if (root->value != -1 && root->value < root->start) {
+ root->start = root->value;
+ }
+ root->num_values = root->end - root->start + 1;
+
+ if (root->num_values > 0) {
+ destination->push_back(std::move(root));
+ }
+ return start_value;
+}
+
+std::unique_ptr<InstanceTypeTree> SolveInstanceTypeConstraints(
+ std::unique_ptr<InstanceTypeTree> root) {
+ std::vector<std::unique_ptr<InstanceTypeTree>> destination;
+ SolveInstanceTypeConstraints(std::move(root), 0, &destination);
+ return destination.empty() ? nullptr : std::move(destination.front());
+}
+
+std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() {
+ std::unique_ptr<InstanceTypeTree> root = BuildInstanceTypeTree();
+ if (root != nullptr) {
+ PropagateInstanceTypeConstraints(root.get());
+ root = SolveInstanceTypeConstraints(std::move(root));
+ }
+ return root;
+}
+
+// Prints items in macro lists for the given type and its descendants.
+// - definitions: This list is pairs of instance type name and assigned value,
+// such as V(ODDBALL_TYPE, 67). It includes FIRST_* and LAST_* items for each
+// type that has more than one associated InstanceType. Items within those
+// ranges are indented for readability.
+// - values: This list is just instance type names, like V(ODDBALL_TYPE). It
+// does not include any FIRST_* and LAST_* range markers.
+void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
+ std::ostream& values, const std::string& indent) {
+ std::string type_name =
+ CapifyStringWithUnderscores(root->type->name()) + "_TYPE";
+ std::string inner_indent = indent;
+
+ if (root->num_values > 1) {
+ definitions << indent << "V(FIRST_" << type_name << ", " << root->start
+ << ") \\\n";
+ inner_indent += " ";
+ }
+ if (root->num_own_values == 1) {
+ definitions << inner_indent << "V(" << type_name << ", " << root->value
+ << ") \\\n";
+ values << " V(" << type_name << ") \\\n";
+ }
+ for (auto& child : root->children) {
+ PrintInstanceTypes(child.get(), definitions, values, inner_indent);
+ }
+ // We can't emit LAST_STRING_TYPE because it's not a valid flags combination.
+ // So if the class type has multiple own values, which only happens when using
+ // ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, then omit the end marker.
+ if (root->num_values > 1 && root->num_own_values <= 1) {
+ definitions << indent << "V(LAST_" << type_name << ", " << root->end
+ << ") \\\n";
+ }
+}
+
+} // namespace
+
+void ImplementationVisitor::GenerateInstanceTypes(
+ const std::string& output_directory) {
+ std::stringstream header;
+ std::string file_name = "instance-types-tq.h";
+ {
+ IncludeGuardScope guard(header, file_name);
+
+ header << "// Instance types for all classes except for those that use "
+ "InstanceType as flags.\n";
+ header << "#define TORQUE_ASSIGNED_INSTANCE_TYPES(V) \\\n";
+ std::unique_ptr<InstanceTypeTree> instance_types = AssignInstanceTypes();
+ std::stringstream values_list;
+ if (instance_types != nullptr) {
+ PrintInstanceTypes(instance_types.get(), header, values_list, " ");
+ }
+ header << "\n\n";
+
+ header << "// Instance types for all classes except for those that use "
+ "InstanceType as flags.\n";
+ header << "#define TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(V) \\\n";
+ header << values_list.str();
+ header << "\n\n";
+
+ header << "// Instance types for Torque-internal classes.\n";
+ header << "#define TORQUE_INTERNAL_INSTANCE_TYPES(V) \\\n";
+ for (const TypeAlias* alias : GlobalContext::GetClasses()) {
+ const ClassType* type = ClassType::DynamicCast(alias->type());
+ if (type->IsExtern()) continue;
+ std::string type_name =
+ CapifyStringWithUnderscores(type->name()) + "_TYPE";
+ header << " V(" << type_name << ") \\\n";
+ }
+ header << "\n\n";
+
+ header << "// Struct list entries for Torque-internal classes.\n";
+ header << "#define TORQUE_STRUCT_LIST_GENERATOR(V, _) \\\n";
+ for (const TypeAlias* alias : GlobalContext::GetClasses()) {
+ const ClassType* type = ClassType::DynamicCast(alias->type());
+ if (type->IsExtern()) continue;
+ std::string type_name =
+ CapifyStringWithUnderscores(type->name()) + "_TYPE";
+ std::string variable_name = SnakeifyString(type->name());
+ header << " V(_, " << type_name << ", " << type->name() << ", "
+ << variable_name << ") \\\n";
+ }
+ header << "\n";
+ }
+ std::string output_header_path = output_directory + "/" + file_name;
+ WriteFile(output_header_path, header.str());
+}
+
+} // namespace torque
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/src/torque/ls/json.h b/deps/v8/src/torque/ls/json.h
index 43d9f7ab11..1a033cf614 100644
--- a/deps/v8/src/torque/ls/json.h
+++ b/deps/v8/src/torque/ls/json.h
@@ -6,11 +6,11 @@
#define V8_TORQUE_LS_JSON_H_
#include <map>
+#include <memory>
#include <string>
#include <vector>
#include "src/base/logging.h"
-#include "src/base/template-utils.h"
namespace v8 {
namespace internal {
@@ -44,7 +44,7 @@ struct JsonValue {
static JsonValue From(JsonObject object) {
JsonValue result;
result.tag = JsonValue::OBJECT;
- result.object_ = base::make_unique<JsonObject>(std::move(object));
+ result.object_ = std::make_unique<JsonObject>(std::move(object));
return result;
}
@@ -65,7 +65,7 @@ struct JsonValue {
static JsonValue From(JsonArray array) {
JsonValue result;
result.tag = JsonValue::ARRAY;
- result.array_ = base::make_unique<JsonArray>(std::move(array));
+ result.array_ = std::make_unique<JsonArray>(std::move(array));
return result;
}
diff --git a/deps/v8/src/torque/ls/message-handler.cc b/deps/v8/src/torque/ls/message-handler.cc
index 6ec124b5a2..becc97c9dc 100644
--- a/deps/v8/src/torque/ls/message-handler.cc
+++ b/deps/v8/src/torque/ls/message-handler.cc
@@ -87,6 +87,8 @@ void ResetCompilationErrorDiagnostics(MessageWriter writer) {
class DiagnosticCollector {
public:
void AddTorqueMessage(const TorqueMessage& message) {
+ if (!ShouldAddMessageOfKind(message.kind)) return;
+
SourceId id =
message.position ? message.position->source : SourceId::Invalid();
auto& notification = GetOrCreateNotificationForSource(id);
@@ -120,6 +122,20 @@ class DiagnosticCollector {
return notification;
}
+ bool ShouldAddMessageOfKind(TorqueMessage::Kind kind) {
+ // An error can easily cause a lot of false positive lint messages, due to
+ // unused variables, macros, etc. Thus we suppress subsequent lint messages
+ // when there are errors.
+ switch (kind) {
+ case TorqueMessage::Kind::kError:
+ suppress_lint_messages_ = true;
+ return true;
+ case TorqueMessage::Kind::kLint:
+ if (suppress_lint_messages_) return false;
+ return true;
+ }
+ }
+
void PopulateRangeFromSourcePosition(Range range,
const SourcePosition& position) {
range.start().set_line(position.start.line);
@@ -138,6 +154,7 @@ class DiagnosticCollector {
}
std::map<SourceId, PublishDiagnosticsNotification> notifications_;
+ bool suppress_lint_messages_ = false;
};
void SendCompilationDiagnostics(const TorqueCompilerResult& result,
diff --git a/deps/v8/src/torque/server-data.h b/deps/v8/src/torque/server-data.h
index 04cd0b317f..b80d1b67f4 100644
--- a/deps/v8/src/torque/server-data.h
+++ b/deps/v8/src/torque/server-data.h
@@ -6,6 +6,7 @@
#define V8_TORQUE_SERVER_DATA_H_
#include <map>
+#include <memory>
#include <vector>
#include "src/base/macros.h"
@@ -47,12 +48,12 @@ class LanguageServerData : public ContextualClass<LanguageServerData> {
static void SetGlobalContext(GlobalContext global_context) {
Get().global_context_ =
- base::make_unique<GlobalContext>(std::move(global_context));
+ std::make_unique<GlobalContext>(std::move(global_context));
Get().PrepareAllDeclarableSymbols();
}
static void SetTypeOracle(TypeOracle type_oracle) {
- Get().type_oracle_ = base::make_unique<TypeOracle>(std::move(type_oracle));
+ Get().type_oracle_ = std::make_unique<TypeOracle>(std::move(type_oracle));
}
static const Symbols& SymbolsForSourceId(SourceId id) {
diff --git a/deps/v8/src/torque/torque-compiler.cc b/deps/v8/src/torque/torque-compiler.cc
index 3968b001fb..6d2b14fc18 100644
--- a/deps/v8/src/torque/torque-compiler.cc
+++ b/deps/v8/src/torque/torque-compiler.cc
@@ -79,7 +79,8 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
ReportAllUnusedMacros();
- implementation_visitor.GenerateBuiltinDefinitions(output_directory);
+ implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors(
+ output_directory);
implementation_visitor.GenerateClassFieldOffsets(output_directory);
implementation_visitor.GeneratePrintDefinitions(output_directory);
implementation_visitor.GenerateClassDefinitions(output_directory);
diff --git a/deps/v8/src/torque/torque-parser.cc b/deps/v8/src/torque/torque-parser.cc
index d9973dde3c..3639bef97c 100644
--- a/deps/v8/src/torque/torque-parser.cc
+++ b/deps/v8/src/torque/torque-parser.cc
@@ -214,6 +214,10 @@ template <>
V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<std::vector<Identifier*>>::id =
ParseResultTypeId::kStdVectorOfIdentifierPtr;
+template <>
+V8_EXPORT_PRIVATE const ParseResultTypeId
+ ParseResultHolder<base::Optional<ClassBody*>>::id =
+ ParseResultTypeId::kOptionalClassBody;
namespace {
@@ -675,7 +679,9 @@ class AnnotationSet {
Lint("Annotation ", a.name->value, error_message)
.Position(a.name->pos);
}
- map_[a.name->value].push_back(*a.param);
+ if (!map_.insert({a.name->value, {*a.param, a.name->pos}}).second) {
+ Lint("Duplicate annotation ", a.name->value).Position(a.name->pos);
+ }
} else {
if (allowed_without_param.find(a.name->value) ==
allowed_without_param.end()) {
@@ -693,41 +699,104 @@ class AnnotationSet {
}
}
- bool Contains(const std::string& s) { return set_.find(s) != set_.end(); }
- const std::vector<std::string>& GetParams(const std::string& s) {
- return map_[s];
+ bool Contains(const std::string& s) const {
+ return set_.find(s) != set_.end();
+ }
+ base::Optional<std::pair<std::string, SourcePosition>> GetParam(
+ const std::string& s) const {
+ auto it = map_.find(s);
+ return it == map_.end()
+ ? base::Optional<std::pair<std::string, SourcePosition>>()
+ : it->second;
}
private:
std::set<std::string> set_;
- std::map<std::string, std::vector<std::string>> map_;
+ std::map<std::string, std::pair<std::string, SourcePosition>> map_;
};
+int GetAnnotationValue(const AnnotationSet& annotations, const char* name,
+ int default_value) {
+ auto value_and_pos = annotations.GetParam(name);
+ if (!value_and_pos.has_value()) return default_value;
+ const std::string& value = value_and_pos->first;
+ SourcePosition pos = value_and_pos->second;
+ if (value.empty()) {
+ Error("Annotation ", name, " requires an integer parameter").Position(pos);
+ }
+ size_t num_chars_converted = 0;
+ int result = default_value;
+ try {
+ result = std::stoi(value, &num_chars_converted, 0);
+ } catch (const std::invalid_argument&) {
+ Error("Expected an integer for annotation ", name).Position(pos);
+ return result;
+ } catch (const std::out_of_range&) {
+ Error("Integer out of 32-bit range in annotation ", name).Position(pos);
+ return result;
+ }
+ if (num_chars_converted != value.size()) {
+ Error("Parameter for annotation ", name,
+ " must be an integer with no trailing characters")
+ .Position(pos);
+ }
+ return result;
+}
+
+InstanceTypeConstraints MakeInstanceTypeConstraints(
+ const AnnotationSet& annotations) {
+ InstanceTypeConstraints result;
+ result.value =
+ GetAnnotationValue(annotations, ANNOTATION_INSTANCE_TYPE_VALUE, -1);
+ result.num_flags_bits = GetAnnotationValue(
+ annotations, ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, -1);
+ return result;
+}
+
+base::Optional<ParseResult> MakeClassBody(ParseResultIterator* child_results) {
+ auto methods = child_results->NextAs<std::vector<Declaration*>>();
+ auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>();
+ base::Optional<ClassBody*> result =
+ MakeNode<ClassBody>(std::move(methods), std::move(fields));
+ return ParseResult(result);
+}
+
base::Optional<ParseResult> MakeClassDeclaration(
ParseResultIterator* child_results) {
AnnotationSet annotations(
child_results,
- {"@generatePrint", "@noVerifier", "@abstract",
- "@dirtyInstantiatedAbstractClass", "@hasSameInstanceTypeAsParent",
- "@generateCppClass"},
- {});
+ {ANNOTATION_GENERATE_PRINT, ANNOTATION_NO_VERIFIER, ANNOTATION_ABSTRACT,
+ ANNOTATION_INSTANTIATED_ABSTRACT_CLASS,
+ ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT,
+ ANNOTATION_GENERATE_CPP_CLASS,
+ ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT,
+ ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT},
+ {ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE,
+ ANNOTATION_INSTANCE_TYPE_VALUE});
ClassFlags flags = ClassFlag::kNone;
- bool generate_print = annotations.Contains("@generatePrint");
+ bool generate_print = annotations.Contains(ANNOTATION_GENERATE_PRINT);
if (generate_print) flags |= ClassFlag::kGeneratePrint;
- bool generate_verify = !annotations.Contains("@noVerifier");
+ bool generate_verify = !annotations.Contains(ANNOTATION_NO_VERIFIER);
if (generate_verify) flags |= ClassFlag::kGenerateVerify;
- if (annotations.Contains("@abstract")) {
+ if (annotations.Contains(ANNOTATION_ABSTRACT)) {
flags |= ClassFlag::kAbstract;
}
- if (annotations.Contains("@dirtyInstantiatedAbstractClass")) {
+ if (annotations.Contains(ANNOTATION_INSTANTIATED_ABSTRACT_CLASS)) {
flags |= ClassFlag::kInstantiatedAbstractClass;
}
- if (annotations.Contains("@hasSameInstanceTypeAsParent")) {
+ if (annotations.Contains(ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT)) {
flags |= ClassFlag::kHasSameInstanceTypeAsParent;
}
- if (annotations.Contains("@generateCppClass")) {
+ if (annotations.Contains(ANNOTATION_GENERATE_CPP_CLASS)) {
flags |= ClassFlag::kGenerateCppClassDefinitions;
}
+ if (annotations.Contains(ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT)) {
+ flags |= ClassFlag::kHighestInstanceTypeWithinParent;
+ }
+ if (annotations.Contains(ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT)) {
+ flags |= ClassFlag::kLowestInstanceTypeWithinParent;
+ }
+
auto is_extern = child_results->NextAs<bool>();
if (is_extern) flags |= ClassFlag::kExtern;
auto transient = child_results->NextAs<bool>();
@@ -741,8 +810,15 @@ base::Optional<ParseResult> MakeClassDeclaration(
ReportError("Expected type name in extends clause.");
}
auto generates = child_results->NextAs<base::Optional<std::string>>();
- auto methods = child_results->NextAs<std::vector<Declaration*>>();
- auto fields_raw = child_results->NextAs<std::vector<ClassFieldExpression>>();
+ auto body = child_results->NextAs<base::Optional<ClassBody*>>();
+ std::vector<Declaration*> methods;
+ std::vector<ClassFieldExpression> fields_raw;
+ if (body.has_value()) {
+ methods = (*body)->methods;
+ fields_raw = (*body)->fields;
+ } else {
+ flags |= ClassFlag::kUndefinedLayout;
+ }
// Filter to only include fields that should be present based on decoration.
std::vector<ClassFieldExpression> fields;
@@ -751,8 +827,9 @@ base::Optional<ParseResult> MakeClassDeclaration(
[](const ClassFieldExpression& exp) {
for (const ConditionalAnnotation& condition : exp.conditions) {
if (condition.type == ConditionalAnnotationType::kPositive
- ? !BuildFlags::GetFlag(condition.condition, "@if")
- : BuildFlags::GetFlag(condition.condition, "@ifnot")) {
+ ? !BuildFlags::GetFlag(condition.condition, ANNOTATION_IF)
+ : BuildFlags::GetFlag(condition.condition,
+ ANNOTATION_IFNOT)) {
return false;
}
}
@@ -761,7 +838,7 @@ base::Optional<ParseResult> MakeClassDeclaration(
Declaration* result = MakeNode<ClassDeclaration>(
name, flags, std::move(extends), std::move(generates), std::move(methods),
- fields);
+ fields, MakeInstanceTypeConstraints(annotations));
return ParseResult{result};
}
@@ -1358,14 +1435,21 @@ base::Optional<ParseResult> MakeAnnotation(ParseResultIterator* child_results) {
}
base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
- AnnotationSet annotations(child_results, {"@noVerifier"}, {"@if", "@ifnot"});
- bool generate_verify = !annotations.Contains("@noVerifier");
+ AnnotationSet annotations(child_results, {ANNOTATION_NO_VERIFIER},
+ {ANNOTATION_IF, ANNOTATION_IFNOT});
+ bool generate_verify = !annotations.Contains(ANNOTATION_NO_VERIFIER);
std::vector<ConditionalAnnotation> conditions;
- for (const std::string& condition : annotations.GetParams("@if")) {
- conditions.push_back({condition, ConditionalAnnotationType::kPositive});
+ base::Optional<std::pair<std::string, SourcePosition>> if_condition =
+ annotations.GetParam(ANNOTATION_IF);
+ base::Optional<std::pair<std::string, SourcePosition>> ifnot_condition =
+ annotations.GetParam(ANNOTATION_IFNOT);
+ if (if_condition.has_value()) {
+ conditions.push_back(
+ {if_condition->first, ConditionalAnnotationType::kPositive});
}
- for (const std::string& condition : annotations.GetParams("@ifnot")) {
- conditions.push_back({condition, ConditionalAnnotationType::kNegative});
+ if (ifnot_condition.has_value()) {
+ conditions.push_back(
+ {ifnot_condition->first, ConditionalAnnotationType::kNegative});
}
auto weak = child_results->NextAs<bool>();
auto const_qualified = child_results->NextAs<bool>();
@@ -1892,6 +1976,13 @@ struct TorqueGrammar : Grammar {
&block},
MakeMethodDeclaration)};
+ // Result: base::Optional<ClassBody*>
+ Symbol optionalClassBody = {
+ Rule({Token("{"), List<Declaration*>(&method),
+ List<ClassFieldExpression>(&classField), Token("}")},
+ MakeClassBody),
+ Rule({Token(";")}, YieldDefaultValue<base::Optional<ClassBody*>>)};
+
// Result: std::vector<Declaration*>
Symbol declaration = {
Rule({Token("const"), &name, Token(":"), &type, Token("="), expression,
@@ -1905,8 +1996,7 @@ struct TorqueGrammar : Grammar {
Optional<TypeExpression*>(Sequence({Token("extends"), &type})),
Optional<std::string>(
Sequence({Token("generates"), &externalString})),
- Token("{"), List<Declaration*>(&method),
- List<ClassFieldExpression>(&classField), Token("}")},
+ &optionalClassBody},
AsSingletonVector<Declaration*, MakeClassDeclaration>()),
Rule({Token("struct"), &name,
TryOrDefault<GenericParameters>(&genericParameters), Token("{"),
diff --git a/deps/v8/src/torque/type-oracle.h b/deps/v8/src/torque/type-oracle.h
index 643c78c030..03aad34d2a 100644
--- a/deps/v8/src/torque/type-oracle.h
+++ b/deps/v8/src/torque/type-oracle.h
@@ -5,6 +5,8 @@
#ifndef V8_TORQUE_TYPE_ORACLE_H_
#define V8_TORQUE_TYPE_ORACLE_H_
+#include <memory>
+
#include "src/torque/contextual.h"
#include "src/torque/declarable.h"
#include "src/torque/declarations.h"
diff --git a/deps/v8/src/torque/type-visitor.cc b/deps/v8/src/torque/type-visitor.cc
index 9b5c96ee40..b45452058d 100644
--- a/deps/v8/src/torque/type-visitor.cc
+++ b/deps/v8/src/torque/type-visitor.cc
@@ -165,6 +165,12 @@ const ClassType* TypeVisitor::ComputeType(ClassDeclaration* decl) {
"class \"", decl->name->value,
"\" must extend either Tagged or an already declared class");
}
+ if (super_class->HasUndefinedLayout() &&
+ !(decl->flags & ClassFlag::kUndefinedLayout)) {
+ Error("Class \"", decl->name->value,
+ "\" defines its layout but extends a class which does not")
+ .Position(decl->pos);
+ }
}
std::string generates = decl->name->value;
@@ -282,8 +288,9 @@ void TypeVisitor::VisitClassFieldsAndMethods(
"only one indexable field is currently supported per class");
}
seen_indexed_field = true;
- const Field* index_field =
- &(class_type->LookupFieldInternal(*field_expression.index));
+ const NameAndType& index_field =
+ class_type->LookupFieldInternal(*field_expression.index)
+ .name_and_type;
class_type->RegisterField(
{field_expression.name_and_type.name->pos,
class_type,
diff --git a/deps/v8/src/torque/types.cc b/deps/v8/src/torque/types.cc
index fe792401f6..022649e065 100644
--- a/deps/v8/src/torque/types.cc
+++ b/deps/v8/src/torque/types.cc
@@ -50,7 +50,9 @@ bool Type::IsSubtypeOf(const Type* supertype) const {
base::Optional<const ClassType*> Type::ClassSupertype() const {
for (const Type* t = this; t != nullptr; t = t->parent()) {
- if (auto* class_type = ClassType::DynamicCast(t)) return class_type;
+ if (auto* class_type = ClassType::DynamicCast(t)) {
+ return class_type;
+ }
}
return base::nullopt;
}
@@ -86,7 +88,7 @@ bool Type::IsAbstractName(const std::string& name) const {
std::string Type::GetGeneratedTypeName() const {
std::string result = GetGeneratedTypeNameImpl();
- if (result.empty() || result == "compiler::TNode<>") {
+ if (result.empty() || result == "TNode<>") {
ReportError("Generated type is required for type '", ToString(),
"'. Use 'generates' clause in definition.");
}
@@ -382,7 +384,7 @@ std::string ClassType::GetGeneratedTNodeTypeNameImpl() const {
std::string ClassType::GetGeneratedTypeNameImpl() const {
return IsConstexpr() ? GetGeneratedTNodeTypeName()
- : "compiler::TNode<" + GetGeneratedTNodeTypeName() + ">";
+ : "TNode<" + GetGeneratedTNodeTypeName() + ">";
}
std::string ClassType::ToExplicitString() const {
@@ -404,11 +406,11 @@ void ClassType::Finalize() const {
if (const ClassType* super_class = ClassType::DynamicCast(parent())) {
if (super_class->HasIndexedField()) flags_ |= ClassFlag::kHasIndexedField;
if (!super_class->IsAbstract() && !HasSameInstanceTypeAsParent()) {
- Error(
- "Super class must either be abstract (annotate super class with "
- "@abstract) "
- "or this class must have the same instance type as the super class "
- "(annotate this class with @hasSameInstanceTypeAsParent).")
+ Error("Super class must either be abstract (annotate super class with ",
+ ANNOTATION_ABSTRACT,
+ ") or this class must have the same instance type as the super "
+ "class (annotate this class with ",
+ ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT, ").")
.Position(this->decl_->name->pos);
}
}
diff --git a/deps/v8/src/torque/types.h b/deps/v8/src/torque/types.h
index d2198d50c3..0102cf31d5 100644
--- a/deps/v8/src/torque/types.h
+++ b/deps/v8/src/torque/types.h
@@ -156,7 +156,7 @@ struct Field {
SourcePosition pos;
const AggregateType* aggregate;
- base::Optional<const Field*> index;
+ base::Optional<NameAndType> index;
NameAndType name_and_type;
size_t offset;
bool is_weak;
@@ -204,8 +204,7 @@ class AbstractType final : public Type {
return "AT" + str;
}
std::string GetGeneratedTypeNameImpl() const override {
- return IsConstexpr() ? generated_type_
- : "compiler::TNode<" + generated_type_ + ">";
+ return IsConstexpr() ? generated_type_ : "TNode<" + generated_type_ + ">";
}
std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsConstexpr() const override {
@@ -316,7 +315,7 @@ class V8_EXPORT_PRIVATE UnionType final : public Type {
std::string ToExplicitString() const override;
std::string MangledName() const override;
std::string GetGeneratedTypeNameImpl() const override {
- return "compiler::TNode<" + GetGeneratedTNodeTypeName() + ">";
+ return "TNode<" + GetGeneratedTNodeTypeName() + ">";
}
std::string GetGeneratedTNodeTypeNameImpl() const override;
@@ -514,10 +513,12 @@ class ClassType final : public AggregateType {
std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsExtern() const { return flags_ & ClassFlag::kExtern; }
bool ShouldGeneratePrint() const {
- return flags_ & ClassFlag::kGeneratePrint || !IsExtern();
+ return (flags_ & ClassFlag::kGeneratePrint || !IsExtern()) &&
+ !HasUndefinedLayout();
}
bool ShouldGenerateVerify() const {
- return flags_ & ClassFlag::kGenerateVerify || !IsExtern();
+ return (flags_ & ClassFlag::kGenerateVerify || !IsExtern()) &&
+ !HasUndefinedLayout();
}
bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; }
@@ -549,6 +550,20 @@ class ClassType final : public AggregateType {
std::vector<Field> ComputeAllFields() const;
+ const InstanceTypeConstraints& GetInstanceTypeConstraints() const {
+ return decl_->instance_type_constraints;
+ }
+ bool IsHighestInstanceTypeWithinParent() const {
+ return flags_ & ClassFlag::kHighestInstanceTypeWithinParent;
+ }
+ bool IsLowestInstanceTypeWithinParent() const {
+ return flags_ & ClassFlag::kLowestInstanceTypeWithinParent;
+ }
+ bool HasUndefinedLayout() const {
+ return flags_ & ClassFlag::kUndefinedLayout;
+ }
+ SourcePosition GetPosition() const { return decl_->pos; }
+
private:
friend class TypeOracle;
friend class TypeVisitor;
diff --git a/deps/v8/src/torque/utils.cc b/deps/v8/src/torque/utils.cc
index 38862b31b0..4e757ac9e8 100644
--- a/deps/v8/src/torque/utils.cc
+++ b/deps/v8/src/torque/utils.cc
@@ -212,19 +212,25 @@ bool IsValidTypeName(const std::string& s) {
}
std::string CapifyStringWithUnderscores(const std::string& camellified_string) {
+ // Special case: JSAbc yields JS_ABC, not JSABC, for any Abc.
+ size_t js_position = camellified_string.find("JS");
+
std::string result;
- bool previousWasLower = false;
- for (auto current : camellified_string) {
- if (previousWasLower && isupper(current)) {
+ bool previousWasLowerOrDigit = false;
+ for (size_t index = 0; index < camellified_string.size(); ++index) {
+ char current = camellified_string[index];
+ if ((previousWasLowerOrDigit && isupper(current)) ||
+ (js_position != std::string::npos &&
+ index == js_position + strlen("JS"))) {
result += "_";
}
if (current == '.' || current == '-') {
result += "_";
- previousWasLower = false;
+ previousWasLowerOrDigit = false;
continue;
}
result += toupper(current);
- previousWasLower = (islower(current));
+ previousWasLowerOrDigit = islower(current) || isdigit(current);
}
return result;
}