Commit 35a61355 authored by Georg Schmid's avatar Georg Schmid Committed by Commit Bot

[torque] Replace ReferenceType by generic Torque struct Reference<T>

This CL removes the built-in reference type in favor of a Torque-implemented generic struct, i.e., internal::Reference<T>. It also adds various infrastructure for getting and creating new generic struct instances, as well as matching against them.

R=tebbi@chromium.org

Change-Id: I1e3d6afe355a0603fa9c3ad789c6b8a97d1b3c26
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1718148
Commit-Queue: Georg Schmid <gsps@google.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62939}
parent 0a424ac1
...@@ -984,6 +984,7 @@ torque_files = [ ...@@ -984,6 +984,7 @@ torque_files = [
"src/builtins/string-slice.tq", "src/builtins/string-slice.tq",
"src/builtins/string-startswith.tq", "src/builtins/string-startswith.tq",
"src/builtins/string-substring.tq", "src/builtins/string-substring.tq",
"src/builtins/torque-internal.tq",
"src/builtins/typed-array-createtypedarray.tq", "src/builtins/typed-array-createtypedarray.tq",
"src/builtins/typed-array-every.tq", "src/builtins/typed-array-every.tq",
"src/builtins/typed-array-filter.tq", "src/builtins/typed-array-filter.tq",
......
// 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.
namespace torque_internal {
struct Reference<T: type> {
const object: HeapObject;
const offset: intptr;
}
} // namespace torque_internal
...@@ -847,6 +847,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -847,6 +847,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Reference is the CSA-equivalent of a Torque reference value, // Reference is the CSA-equivalent of a Torque reference value,
// representing an inner pointer into a HeapObject. // representing an inner pointer into a HeapObject.
// TODO(gsps): Remove in favor of flattened {Load,Store}Reference interface
struct Reference { struct Reference {
TNode<HeapObject> object; TNode<HeapObject> object;
TNode<IntPtrT> offset; TNode<IntPtrT> offset;
......
...@@ -46,8 +46,7 @@ namespace torque { ...@@ -46,8 +46,7 @@ namespace torque {
#define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \ #define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \
V(BasicTypeExpression) \ V(BasicTypeExpression) \
V(FunctionTypeExpression) \ V(FunctionTypeExpression) \
V(UnionTypeExpression) \ V(UnionTypeExpression)
V(ReferenceTypeExpression)
#define AST_STATEMENT_NODE_KIND_LIST(V) \ #define AST_STATEMENT_NODE_KIND_LIST(V) \
V(BlockStatement) \ V(BlockStatement) \
...@@ -619,13 +618,6 @@ struct UnionTypeExpression : TypeExpression { ...@@ -619,13 +618,6 @@ struct UnionTypeExpression : TypeExpression {
TypeExpression* b; TypeExpression* b;
}; };
struct ReferenceTypeExpression : TypeExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ReferenceTypeExpression)
ReferenceTypeExpression(SourcePosition pos, TypeExpression* referenced_type)
: TypeExpression(kKind, pos), referenced_type(referenced_type) {}
TypeExpression* referenced_type;
};
struct ExpressionStatement : Statement { struct ExpressionStatement : Statement {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExpressionStatement) DEFINE_AST_NODE_LEAF_BOILERPLATE(ExpressionStatement)
ExpressionStatement(SourcePosition pos, Expression* expression) ExpressionStatement(SourcePosition pos, Expression* expression)
......
...@@ -49,6 +49,8 @@ static const char* const FLOAT64_TYPE_STRING = "float64"; ...@@ -49,6 +49,8 @@ static const char* const FLOAT64_TYPE_STRING = "float64";
static const char* const CONST_INT31_TYPE_STRING = "constexpr int31"; static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32"; static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64"; static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
static const char* const TORQUE_INTERNAL_NAMESPACE_STRING = "torque_internal";
static const char* const REFERENCE_TYPE_STRING = "Reference";
inline bool IsConstexprName(const std::string& name) { inline bool IsConstexprName(const std::string& name) {
return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) == return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) ==
......
...@@ -305,8 +305,7 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, ...@@ -305,8 +305,7 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
std::string catch_name = std::string catch_name =
PreCallableExceptionPreparation(instruction.catch_block); PreCallableExceptionPreparation(instruction.catch_block);
out_ << " "; out_ << " ";
bool needs_flattening = bool needs_flattening = return_type->IsStructType();
return_type->IsStructType() || return_type->IsReferenceType();
if (needs_flattening) { if (needs_flattening) {
out_ << "std::tie("; out_ << "std::tie(";
PrintCommaSeparatedList(out_, results); PrintCommaSeparatedList(out_, results);
...@@ -766,11 +765,6 @@ void CSAGenerator::EmitCSAValue(VisitResult result, ...@@ -766,11 +765,6 @@ void CSAGenerator::EmitCSAValue(VisitResult result,
out); out);
} }
out << "}"; out << "}";
} else if (result.type()->IsReferenceType()) {
DCHECK_EQ(2, result.stack_range().Size());
size_t offset = result.stack_range().begin().offset;
out << "CodeStubAssembler::Reference{" << values.Peek(BottomOffset{offset})
<< ", " << values.Peek(BottomOffset{offset + 1}) << "}";
} else { } else {
DCHECK_EQ(1, result.stack_range().Size()); DCHECK_EQ(1, result.stack_range().Size());
out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName() out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName()
......
...@@ -74,11 +74,7 @@ base::Optional<const Type*> InferTypeArgument(const std::string& to_infer, ...@@ -74,11 +74,7 @@ base::Optional<const Type*> InferTypeArgument(const std::string& to_infer,
basic->name == to_infer) { basic->name == to_infer) {
return argument; return argument;
} }
auto* ref = ReferenceTypeExpression::DynamicCast(parameter); // TODO(gsps): Perform type inference for generic types
if (ref && argument->IsReferenceType()) {
return InferTypeArgument(to_infer, ref->referenced_type,
ReferenceType::cast(argument)->referenced_type());
}
return base::nullopt; return base::nullopt;
} }
......
...@@ -505,11 +505,6 @@ class Generic : public Declarable { ...@@ -505,11 +505,6 @@ class Generic : public Declarable {
SpecializationMap<Callable> specializations_; SpecializationMap<Callable> specializations_;
}; };
struct SpecializationKey {
Generic* generic;
TypeVector specialized_types;
};
class GenericStructType : public Declarable { class GenericStructType : public Declarable {
public: public:
DECLARE_DECLARABLE_BOILERPLATE(GenericStructType, generic_type) DECLARE_DECLARABLE_BOILERPLATE(GenericStructType, generic_type)
......
...@@ -205,7 +205,7 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) { ...@@ -205,7 +205,7 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
TypeVisitor::MakeSignature(decl->signature.get()); TypeVisitor::MakeSignature(decl->signature.get());
for (Generic* generic : generic_list) { for (Generic* generic : generic_list) {
Signature generic_signature_with_types = Signature generic_signature_with_types =
MakeSpecializedSignature(SpecializationKey{ MakeSpecializedSignature(SpecializationKey<Generic>{
generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)}); generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
if (signature_with_types.HasSameTypesAs(generic_signature_with_types, if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
ParameterMode::kIgnoreImplicit)) { ParameterMode::kIgnoreImplicit)) {
...@@ -233,7 +233,7 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) { ...@@ -233,7 +233,7 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
stream << "\ncandidates are:"; stream << "\ncandidates are:";
for (Generic* generic : generic_list) { for (Generic* generic : generic_list) {
stream << "\n " stream << "\n "
<< MakeSpecializedSignature(SpecializationKey{ << MakeSpecializedSignature(SpecializationKey<Generic>{
generic, generic,
TypeVisitor::ComputeTypeVector(decl->generic_parameters)}); TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
} }
...@@ -245,8 +245,9 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) { ...@@ -245,8 +245,9 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
matching_generic->IdentifierPosition()); matching_generic->IdentifierPosition());
} }
Specialize(SpecializationKey{matching_generic, TypeVisitor::ComputeTypeVector( Specialize(SpecializationKey<Generic>{matching_generic,
decl->generic_parameters)}, TypeVisitor::ComputeTypeVector(
decl->generic_parameters)},
matching_generic->declaration()->callable, decl->signature.get(), matching_generic->declaration()->callable, decl->signature.get(),
decl->body, decl->pos); decl->body, decl->pos);
} }
...@@ -267,7 +268,8 @@ void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) { ...@@ -267,7 +268,8 @@ void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
GlobalContext::AddCppInclude(decl->include_path); GlobalContext::AddCppInclude(decl->include_path);
} }
void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) { void DeclarationVisitor::DeclareSpecializedTypes(
const SpecializationKey<Generic>& key) {
size_t i = 0; size_t i = 0;
const std::size_t generic_parameter_count = const std::size_t generic_parameter_count =
key.generic->declaration()->generic_parameters.size(); key.generic->declaration()->generic_parameters.size();
...@@ -288,7 +290,7 @@ void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) { ...@@ -288,7 +290,7 @@ void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
} }
Signature DeclarationVisitor::MakeSpecializedSignature( Signature DeclarationVisitor::MakeSpecializedSignature(
const SpecializationKey& key) { const SpecializationKey<Generic>& key) {
CurrentScope::Scope generic_scope(key.generic->ParentScope()); CurrentScope::Scope generic_scope(key.generic->ParentScope());
// Create a temporary fake-namespace just to temporarily declare the // Create a temporary fake-namespace just to temporarily declare the
// specialization aliases for the generic types to create a signature. // specialization aliases for the generic types to create a signature.
...@@ -299,7 +301,8 @@ Signature DeclarationVisitor::MakeSpecializedSignature( ...@@ -299,7 +301,8 @@ Signature DeclarationVisitor::MakeSpecializedSignature(
key.generic->declaration()->callable->signature.get()); key.generic->declaration()->callable->signature.get());
} }
Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) { Callable* DeclarationVisitor::SpecializeImplicit(
const SpecializationKey<Generic>& key) {
if (!key.generic->declaration()->body && if (!key.generic->declaration()->body &&
IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) == IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
nullptr) { nullptr) {
...@@ -318,7 +321,7 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) { ...@@ -318,7 +321,7 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
} }
Callable* DeclarationVisitor::Specialize( Callable* DeclarationVisitor::Specialize(
const SpecializationKey& key, CallableNode* declaration, const SpecializationKey<Generic>& key, CallableNode* declaration,
base::Optional<const CallableNodeSignature*> signature, base::Optional<const CallableNodeSignature*> signature,
base::Optional<Statement*> body, SourcePosition position) { base::Optional<Statement*> body, SourcePosition position) {
CurrentSourcePosition::Scope pos_scope(position); CurrentSourcePosition::Scope pos_scope(position);
......
...@@ -107,15 +107,16 @@ class DeclarationVisitor { ...@@ -107,15 +107,16 @@ class DeclarationVisitor {
static void Visit(ExternConstDeclaration* decl); static void Visit(ExternConstDeclaration* decl);
static void Visit(CppIncludeDeclaration* decl); static void Visit(CppIncludeDeclaration* decl);
static Signature MakeSpecializedSignature(const SpecializationKey& key); static Signature MakeSpecializedSignature(
static Callable* SpecializeImplicit(const SpecializationKey& key); const SpecializationKey<Generic>& key);
static Callable* SpecializeImplicit(const SpecializationKey<Generic>& key);
static Callable* Specialize( static Callable* Specialize(
const SpecializationKey& key, CallableNode* declaration, const SpecializationKey<Generic>& key, CallableNode* declaration,
base::Optional<const CallableNodeSignature*> signature, base::Optional<const CallableNodeSignature*> signature,
base::Optional<Statement*> body, SourcePosition position); base::Optional<Statement*> body, SourcePosition position);
private: private:
static void DeclareSpecializedTypes(const SpecializationKey& key); static void DeclareSpecializedTypes(const SpecializationKey<Generic>& key);
}; };
} // namespace torque } // namespace torque
......
...@@ -1599,7 +1599,7 @@ void FailCallableLookup(const std::string& reason, const QualifiedName& name, ...@@ -1599,7 +1599,7 @@ void FailCallableLookup(const std::string& reason, const QualifiedName& name,
ReportError(stream.str()); ReportError(stream.str());
} }
Callable* GetOrCreateSpecialization(const SpecializationKey& key) { Callable* GetOrCreateSpecialization(const SpecializationKey<Generic>& key) {
if (base::Optional<Callable*> specialization = if (base::Optional<Callable*> specialization =
key.generic->specializations().Get(key.specialized_types)) { key.generic->specializations().Get(key.specialized_types)) {
return *specialization; return *specialization;
...@@ -1664,7 +1664,8 @@ Callable* ImplementationVisitor::LookupCallable( ...@@ -1664,7 +1664,8 @@ Callable* ImplementationVisitor::LookupCallable(
overloads.push_back(generic); overloads.push_back(generic);
overload_signatures.push_back( overload_signatures.push_back(
DeclarationVisitor::MakeSpecializedSignature( DeclarationVisitor::MakeSpecializedSignature(
SpecializationKey{generic, *inferred_specialization_types})); SpecializationKey<Generic>{generic,
*inferred_specialization_types}));
} else if (Callable* callable = Callable::DynamicCast(declarable)) { } else if (Callable* callable = Callable::DynamicCast(declarable)) {
overloads.push_back(callable); overloads.push_back(callable);
overload_signatures.push_back(callable->signature()); overload_signatures.push_back(callable->signature());
...@@ -1717,9 +1718,9 @@ Callable* ImplementationVisitor::LookupCallable( ...@@ -1717,9 +1718,9 @@ Callable* ImplementationVisitor::LookupCallable(
} }
if (Generic* generic = Generic::DynamicCast(overloads[best])) { if (Generic* generic = Generic::DynamicCast(overloads[best])) {
result = GetOrCreateSpecialization( result = GetOrCreateSpecialization(SpecializationKey<Generic>{
SpecializationKey{generic, *generic->InferSpecializationTypes( generic, *generic->InferSpecializationTypes(specialization_types,
specialization_types, parameter_types)}); parameter_types)});
} else { } else {
result = Callable::cast(overloads[best]); result = Callable::cast(overloads[best]);
} }
...@@ -1927,8 +1928,9 @@ LocationReference ImplementationVisitor::GetLocationReference( ...@@ -1927,8 +1928,9 @@ LocationReference ImplementationVisitor::GetLocationReference(
} }
if (expr->generic_arguments.size() != 0) { if (expr->generic_arguments.size() != 0) {
Generic* generic = Declarations::LookupUniqueGeneric(name); Generic* generic = Declarations::LookupUniqueGeneric(name);
Callable* specialization = GetOrCreateSpecialization(SpecializationKey{ Callable* specialization =
generic, TypeVisitor::ComputeTypeVector(expr->generic_arguments)}); GetOrCreateSpecialization(SpecializationKey<Generic>{
generic, TypeVisitor::ComputeTypeVector(expr->generic_arguments)});
if (Builtin* builtin = Builtin::DynamicCast(specialization)) { if (Builtin* builtin = Builtin::DynamicCast(specialization)) {
DCHECK(!builtin->IsExternal()); DCHECK(!builtin->IsExternal());
return LocationReference::Temporary(GetBuiltinCode(builtin), return LocationReference::Temporary(GetBuiltinCode(builtin),
...@@ -1963,8 +1965,8 @@ LocationReference ImplementationVisitor::GetLocationReference( ...@@ -1963,8 +1965,8 @@ LocationReference ImplementationVisitor::GetLocationReference(
LocationReference ImplementationVisitor::GetLocationReference( LocationReference ImplementationVisitor::GetLocationReference(
DereferenceExpression* expr) { DereferenceExpression* expr) {
VisitResult ref = Visit(expr->reference); VisitResult ref = Visit(expr->reference);
const ReferenceType* type = ReferenceType::DynamicCast(ref.type()); if (!StructType::MatchUnaryGeneric(ref.type(),
if (!type) { TypeOracle::GetReferenceGeneric())) {
ReportError("Operator * expects a reference but found a value of type ", ReportError("Operator * expects a reference but found a value of type ",
*ref.type()); *ref.type());
} }
...@@ -2542,10 +2544,6 @@ StackRange ImplementationVisitor::LowerParameter( ...@@ -2542,10 +2544,6 @@ StackRange ImplementationVisitor::LowerParameter(
range.Extend(parameter_range); range.Extend(parameter_range);
} }
return range; return range;
} else if (type->IsReferenceType()) {
lowered_parameters->Push(parameter_name + ".object");
lowered_parameters->Push(parameter_name + ".offset");
return lowered_parameters->TopRange(2);
} else { } else {
lowered_parameters->Push(parameter_name); lowered_parameters->Push(parameter_name);
return lowered_parameters->TopRange(1); return lowered_parameters->TopRange(1);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "src/torque/cfg.h" #include "src/torque/cfg.h"
#include "src/torque/declarations.h" #include "src/torque/declarations.h"
#include "src/torque/global-context.h" #include "src/torque/global-context.h"
#include "src/torque/type-oracle.h"
#include "src/torque/types.h" #include "src/torque/types.h"
#include "src/torque/utils.h" #include "src/torque/utils.h"
...@@ -52,7 +53,8 @@ class LocationReference { ...@@ -52,7 +53,8 @@ class LocationReference {
// pointer. // pointer.
static LocationReference HeapReference(VisitResult heap_reference) { static LocationReference HeapReference(VisitResult heap_reference) {
LocationReference result; LocationReference result;
DCHECK(heap_reference.type()->IsReferenceType()); DCHECK(StructType::MatchUnaryGeneric(heap_reference.type(),
TypeOracle::GetReferenceGeneric()));
result.heap_reference_ = std::move(heap_reference); result.heap_reference_ = std::move(heap_reference);
return result; return result;
} }
...@@ -112,7 +114,8 @@ class LocationReference { ...@@ -112,7 +114,8 @@ class LocationReference {
const Type* ReferencedType() const { const Type* ReferencedType() const {
if (IsHeapReference()) { if (IsHeapReference()) {
return ReferenceType::cast(heap_reference().type())->referenced_type(); return *StructType::MatchUnaryGeneric(heap_reference().type(),
TypeOracle::GetReferenceGeneric());
} }
return GetVisitResult().type(); return GetVisitResult().type();
} }
......
...@@ -297,6 +297,7 @@ void CreateFieldReferenceInstruction::TypeInstruction( ...@@ -297,6 +297,7 @@ void CreateFieldReferenceInstruction::TypeInstruction(
stack->Push(TypeOracle::GetIntPtrType()); stack->Push(TypeOracle::GetIntPtrType());
} }
// TODO(gsps): Remove in favor of a method on Reference<T>
void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const { ControlFlowGraph* cfg) const {
ExpectType(TypeOracle::GetIntPtrType(), stack->Pop()); ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
...@@ -305,6 +306,7 @@ void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, ...@@ -305,6 +306,7 @@ void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
stack->Push(type); stack->Push(type);
} }
// TODO(gsps): Remove in favor of a method on Reference<T>
void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const { ControlFlowGraph* cfg) const {
ExpectSubtype(stack->Pop(), type); ExpectSubtype(stack->Pop(), type);
......
...@@ -879,7 +879,11 @@ base::Optional<ParseResult> MakeFunctionTypeExpression( ...@@ -879,7 +879,11 @@ base::Optional<ParseResult> MakeFunctionTypeExpression(
base::Optional<ParseResult> MakeReferenceTypeExpression( base::Optional<ParseResult> MakeReferenceTypeExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto referenced_type = child_results->NextAs<TypeExpression*>(); auto referenced_type = child_results->NextAs<TypeExpression*>();
TypeExpression* result = MakeNode<ReferenceTypeExpression>(referenced_type); std::vector<std::string> namespace_qualification{
TORQUE_INTERNAL_NAMESPACE_STRING};
std::vector<TypeExpression*> generic_arguments{referenced_type};
TypeExpression* result = MakeNode<BasicTypeExpression>(
namespace_qualification, REFERENCE_TYPE_STRING, generic_arguments);
return ParseResult{result}; return ParseResult{result};
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/torque/type-oracle.h" #include "src/torque/type-oracle.h"
#include "src/torque/type-visitor.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -23,6 +24,39 @@ void TypeOracle::FinalizeAggregateTypes() { ...@@ -23,6 +24,39 @@ void TypeOracle::FinalizeAggregateTypes() {
} }
} }
// static
const StructType* TypeOracle::GetGenericStructTypeInstance(
GenericStructType* generic_struct, TypeVector arg_types) {
auto& params = generic_struct->generic_parameters();
auto& specializations = generic_struct->specializations();
if (params.size() != arg_types.size()) {
ReportError("Generic struct takes ", params.size(), " parameters, but ",
arg_types.size(), " were given");
}
if (auto specialization = specializations.Get(arg_types)) {
return *specialization;
} else {
CurrentScope::Scope generic_scope(generic_struct->ParentScope());
// Create a temporary fake-namespace just to temporarily declare the
// specialization aliases for the generic types to create a signature.
Namespace tmp_namespace("_tmp");
CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
auto arg_types_iterator = arg_types.begin();
for (auto param : params) {
TypeAlias* alias = Declarations::DeclareType(param, *arg_types_iterator);
alias->SetIsUserDefined(false);
arg_types_iterator++;
}
auto struct_type = TypeVisitor::ComputeType(generic_struct->declaration(),
{{generic_struct, arg_types}});
specializations.Add(arg_types, struct_type);
return struct_type;
}
}
} // namespace torque } // namespace torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -30,8 +30,11 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -30,8 +30,11 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return result; return result;
} }
static StructType* GetStructType(const std::string& name) { static StructType* GetStructType(
StructType* result = new StructType(CurrentNamespace(), name); const std::string& basename,
StructType::MaybeSpecializationKey specialized_from) {
StructType* result =
new StructType(CurrentNamespace(), basename, specialized_from);
Get().aggregate_types_.push_back(std::unique_ptr<StructType>(result)); Get().aggregate_types_.push_back(std::unique_ptr<StructType>(result));
return result; return result;
} }
...@@ -60,8 +63,17 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -60,8 +63,17 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return result; return result;
} }
static const ReferenceType* GetReferenceType(const Type* referenced_type) { static const StructType* GetGenericStructTypeInstance(
return Get().reference_types_.Add(ReferenceType(referenced_type)); GenericStructType* generic_struct, TypeVector arg_types);
static GenericStructType* GetReferenceGeneric() {
return Declarations::LookupUniqueGenericStructType(QualifiedName(
{TORQUE_INTERNAL_NAMESPACE_STRING}, REFERENCE_TYPE_STRING));
}
static const StructType* GetReferenceType(const Type* referenced_type) {
return GetGenericStructTypeInstance(GetReferenceGeneric(),
{referenced_type});
} }
static const std::vector<const BuiltinPointerType*>& static const std::vector<const BuiltinPointerType*>&
...@@ -245,7 +257,6 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -245,7 +257,6 @@ class TypeOracle : public ContextualClass<TypeOracle> {
Deduplicator<BuiltinPointerType> function_pointer_types_; Deduplicator<BuiltinPointerType> function_pointer_types_;
std::vector<const BuiltinPointerType*> all_builtin_pointer_types_; std::vector<const BuiltinPointerType*> all_builtin_pointer_types_;
Deduplicator<UnionType> union_types_; Deduplicator<UnionType> union_types_;
Deduplicator<ReferenceType> reference_types_;
std::vector<std::unique_ptr<Type>> nominal_types_; std::vector<std::unique_ptr<Type>> nominal_types_;
std::vector<std::unique_ptr<AggregateType>> aggregate_types_; std::vector<std::unique_ptr<AggregateType>> aggregate_types_;
std::vector<std::unique_ptr<Type>> top_types_; std::vector<std::unique_ptr<Type>> top_types_;
......
...@@ -110,25 +110,12 @@ void DeclareMethods(AggregateType* container_type, ...@@ -110,25 +110,12 @@ void DeclareMethods(AggregateType* container_type,
} }
} }
namespace { const StructType* TypeVisitor::ComputeType(
std::string ComputeStructName(StructDeclaration* decl) { StructDeclaration* decl,
TypeVector args; StructType::MaybeSpecializationKey specialized_from) {
if (decl->IsGeneric()) {
args.resize(decl->generic_parameters.size());
std::transform(
decl->generic_parameters.begin(), decl->generic_parameters.end(),
args.begin(), [](Identifier* parameter) {
return Declarations::LookupTypeAlias(QualifiedName(parameter->value))
->type();
});
}
return StructType::ComputeName(decl->name->value, args);
}
} // namespace
const StructType* TypeVisitor::ComputeType(StructDeclaration* decl) {
CurrentSourcePosition::Scope position_activator(decl->pos); CurrentSourcePosition::Scope position_activator(decl->pos);
StructType* struct_type = TypeOracle::GetStructType(ComputeStructName(decl)); StructType* struct_type =
TypeOracle::GetStructType(decl->name->value, specialized_from);
size_t offset = 0; size_t offset = 0;
for (auto& field : decl->fields) { for (auto& field : decl->fields) {
CurrentSourcePosition::Scope position_activator( CurrentSourcePosition::Scope position_activator(
...@@ -214,34 +201,8 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) { ...@@ -214,34 +201,8 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
} else { } else {
auto* generic_struct = auto* generic_struct =
Declarations::LookupUniqueGenericStructType(qualified_name); Declarations::LookupUniqueGenericStructType(qualified_name);
auto& params = generic_struct->generic_parameters(); type = TypeOracle::GetGenericStructTypeInstance(generic_struct,
auto& specializations = generic_struct->specializations(); ComputeTypeVector(args));
if (params.size() != args.size()) {
ReportError("Generic struct takes ", params.size(),
" parameters, but only ", args.size(), " were given");
}
std::vector<const Type*> arg_types = ComputeTypeVector(args);
if (auto specialization = specializations.Get(arg_types)) {
type = *specialization;
} else {
CurrentScope::Scope generic_scope(generic_struct->ParentScope());
// Create a temporary fake-namespace just to temporarily declare the
// specialization aliases for the generic types to create a signature.
Namespace tmp_namespace("_tmp");
CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
auto arg_types_iterator = arg_types.begin();
for (auto param : params) {
TypeAlias* alias =
Declarations::DeclareType(param, *arg_types_iterator);
alias->SetIsUserDefined(false);
arg_types_iterator++;
}
auto struct_type = ComputeType(generic_struct->declaration());
specializations.Add(arg_types, struct_type);
type = struct_type;
}
pos = generic_struct->declaration()->name->pos; pos = generic_struct->declaration()->name->pos;
} }
...@@ -254,10 +215,6 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) { ...@@ -254,10 +215,6 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
UnionTypeExpression::DynamicCast(type_expression)) { UnionTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetUnionType(ComputeType(union_type->a), return TypeOracle::GetUnionType(ComputeType(union_type->a),
ComputeType(union_type->b)); ComputeType(union_type->b));
} else if (auto* reference_type =
ReferenceTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetReferenceType(
ComputeType(reference_type->referenced_type));
} else { } else {
auto* function_type_exp = FunctionTypeExpression::cast(type_expression); auto* function_type_exp = FunctionTypeExpression::cast(type_expression);
TypeVector argument_types; TypeVector argument_types;
......
...@@ -31,10 +31,13 @@ class TypeVisitor { ...@@ -31,10 +31,13 @@ class TypeVisitor {
private: private:
friend class TypeAlias; friend class TypeAlias;
friend class TypeOracle;
static const Type* ComputeType(TypeDeclaration* decl); static const Type* ComputeType(TypeDeclaration* decl);
static const AbstractType* ComputeType(AbstractTypeDeclaration* decl); static const AbstractType* ComputeType(AbstractTypeDeclaration* decl);
static const Type* ComputeType(TypeAliasDeclaration* decl); static const Type* ComputeType(TypeAliasDeclaration* decl);
static const StructType* ComputeType(StructDeclaration* decl); static const StructType* ComputeType(
StructDeclaration* decl,
StructType::MaybeSpecializationKey specialized_from = base::nullopt);
static const ClassType* ComputeType(ClassDeclaration* decl); static const ClassType* ComputeType(ClassDeclaration* decl);
}; };
......
...@@ -276,13 +276,14 @@ std::string StructType::GetGeneratedTypeNameImpl() const { ...@@ -276,13 +276,14 @@ std::string StructType::GetGeneratedTypeNameImpl() const {
} }
// static // static
std::string StructType::ComputeName(const std::string& basename, std::string StructType::ComputeName(
const std::vector<const Type*>& args) { const std::string& basename,
if (args.size() == 0) return basename; StructType::MaybeSpecializationKey specialized_from) {
if (!specialized_from) return basename;
std::stringstream s; std::stringstream s;
s << basename << "<"; s << basename << "<";
bool first = true; bool first = true;
for (auto t : args) { for (auto t : specialized_from->specialized_types) {
if (!first) { if (!first) {
s << ", "; s << ", ";
} }
...@@ -293,6 +294,43 @@ std::string StructType::ComputeName(const std::string& basename, ...@@ -293,6 +294,43 @@ std::string StructType::ComputeName(const std::string& basename,
return s.str(); return s.str();
} }
std::string StructType::MangledName() const {
std::stringstream result;
// TODO(gsps): Add 'ST' as a prefix once we can control the generated type
// name from Torque code
result << basename_;
if (specialized_from_) {
for (const Type* t : specialized_from_->specialized_types) {
std::string arg_type_string = t->MangledName();
result << arg_type_string.size() << arg_type_string;
}
}
return result.str();
}
// static
base::Optional<const Type*> StructType::MatchUnaryGeneric(
const Type* type, GenericStructType* generic) {
if (auto* struct_type = StructType::DynamicCast(type)) {
return MatchUnaryGeneric(struct_type, generic);
}
return base::nullopt;
}
// static
base::Optional<const Type*> StructType::MatchUnaryGeneric(
const StructType* type, GenericStructType* generic) {
DCHECK_EQ(generic->generic_parameters().size(), 1);
if (!type->specialized_from_) {
return base::nullopt;
}
auto& key = type->specialized_from_.value();
if (key.generic != generic || key.specialized_types.size() != 1) {
return base::nullopt;
}
return {key.specialized_types[0]};
}
std::vector<Method*> AggregateType::Methods(const std::string& name) const { std::vector<Method*> AggregateType::Methods(const std::string& name) const {
if (!is_finalized_) Finalize(); if (!is_finalized_) Finalize();
std::vector<Method*> result; std::vector<Method*> result;
...@@ -560,9 +598,6 @@ void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) { ...@@ -560,9 +598,6 @@ void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) {
for (const Field& field : s->fields()) { for (const Field& field : s->fields()) {
AppendLoweredTypes(field.name_and_type.type, result); AppendLoweredTypes(field.name_and_type.type, result);
} }
} else if (type->IsReferenceType()) {
result->push_back(TypeOracle::GetHeapObjectType());
result->push_back(TypeOracle::GetIntPtrType());
} else { } else {
result->push_back(type); result->push_back(type);
} }
......
...@@ -25,6 +25,7 @@ class AggregateType; ...@@ -25,6 +25,7 @@ class AggregateType;
struct Identifier; struct Identifier;
class Macro; class Macro;
class Method; class Method;
class GenericStructType;
class StructType; class StructType;
class ClassType; class ClassType;
class Value; class Value;
...@@ -36,7 +37,6 @@ class TypeBase { ...@@ -36,7 +37,6 @@ class TypeBase {
kTopType, kTopType,
kAbstractType, kAbstractType,
kBuiltinPointerType, kBuiltinPointerType,
kReferenceType,
kUnionType, kUnionType,
kStructType, kStructType,
kClassType kClassType
...@@ -47,7 +47,6 @@ class TypeBase { ...@@ -47,7 +47,6 @@ class TypeBase {
bool IsBuiltinPointerType() const { bool IsBuiltinPointerType() const {
return kind() == Kind::kBuiltinPointerType; return kind() == Kind::kBuiltinPointerType;
} }
bool IsReferenceType() const { return kind() == Kind::kReferenceType; }
bool IsUnionType() const { return kind() == Kind::kUnionType; } bool IsUnionType() const { return kind() == Kind::kUnionType; }
bool IsStructType() const { return kind() == Kind::kStructType; } bool IsStructType() const { return kind() == Kind::kStructType; }
bool IsClassType() const { return kind() == Kind::kClassType; } bool IsClassType() const { return kind() == Kind::kClassType; }
...@@ -143,6 +142,12 @@ struct NameAndType { ...@@ -143,6 +142,12 @@ struct NameAndType {
std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type); std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
template <typename T>
struct SpecializationKey {
T* generic;
TypeVector specialized_types;
};
struct Field { struct Field {
// TODO(danno): This likely should be refactored, the handling of the types // TODO(danno): This likely should be refactored, the handling of the types
// using the universal grab-bag utility with std::tie, as well as the // using the universal grab-bag utility with std::tie, as well as the
...@@ -298,43 +303,6 @@ class V8_EXPORT_PRIVATE BuiltinPointerType final : public Type { ...@@ -298,43 +303,6 @@ class V8_EXPORT_PRIVATE BuiltinPointerType final : public Type {
const size_t function_pointer_type_id_; const size_t function_pointer_type_id_;
}; };
class ReferenceType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(ReferenceType)
std::string MangledName() const override {
return "RT" + referenced_type_->MangledName();
}
std::string ToExplicitString() const override {
std::string s = referenced_type_->ToString();
if (s.find(' ') != std::string::npos) {
s = "(" + s + ")";
}
return "&" + s;
}
std::string GetGeneratedTypeNameImpl() const override {
return "CodeStubAssembler::Reference";
}
std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }
const Type* referenced_type() const { return referenced_type_; }
friend size_t hash_value(const ReferenceType& p) {
return base::hash_combine(static_cast<size_t>(Kind::kReferenceType),
p.referenced_type_);
}
bool operator==(const ReferenceType& other) const {
return referenced_type_ == other.referenced_type_;
}
private:
friend class TypeOracle;
explicit ReferenceType(const Type* referenced_type)
: Type(Kind::kReferenceType, nullptr),
referenced_type_(referenced_type) {}
const Type* const referenced_type_;
};
bool operator<(const Type& a, const Type& b); bool operator<(const Type& a, const Type& b);
struct TypeLess { struct TypeLess {
bool operator()(const Type* const a, const Type* const b) const { bool operator()(const Type* const a, const Type* const b) const {
...@@ -500,32 +468,38 @@ class AggregateType : public Type { ...@@ -500,32 +468,38 @@ class AggregateType : public Type {
class StructType final : public AggregateType { class StructType final : public AggregateType {
public: public:
DECLARE_TYPE_BOILERPLATE(StructType) DECLARE_TYPE_BOILERPLATE(StructType)
using MaybeSpecializationKey =
base::Optional<SpecializationKey<GenericStructType>>;
std::string ToExplicitString() const override; std::string ToExplicitString() const override;
std::string GetGeneratedTypeNameImpl() const override; std::string GetGeneratedTypeNameImpl() const override;
std::string MangledName() const override { std::string MangledName() const override;
// TODO(gsps): Generate more readable mangled names
std::string str(name());
std::replace(str.begin(), str.end(), ',', '_');
std::replace(str.begin(), str.end(), ' ', '_');
std::replace(str.begin(), str.end(), '<', '_');
std::replace(str.begin(), str.end(), '>', '_');
return str;
}
static std::string ComputeName(const std::string& basename, static base::Optional<const Type*> MatchUnaryGeneric(
const std::vector<const Type*>& args); const Type* type, GenericStructType* generic);
static base::Optional<const Type*> MatchUnaryGeneric(
const StructType* type, GenericStructType* generic);
private: private:
friend class TypeOracle; friend class TypeOracle;
StructType(Namespace* nspace, const std::string& name) StructType(Namespace* nspace, const std::string& basename,
: AggregateType(Kind::kStructType, nullptr, nspace, name) {} MaybeSpecializationKey specialized_from = base::nullopt)
: AggregateType(Kind::kStructType, nullptr, nspace,
ComputeName(basename, specialized_from)),
basename_(basename),
specialized_from_(specialized_from) {}
void Finalize() const override { void Finalize() const override {
is_finalized_ = true; is_finalized_ = true;
CheckForDuplicateFields(); CheckForDuplicateFields();
} }
const std::string& GetStructName() const { return name(); } static std::string ComputeName(const std::string& basename,
MaybeSpecializationKey specialized_from);
std::string basename_;
MaybeSpecializationKey specialized_from_;
}; };
class TypeAlias; class TypeAlias;
......
...@@ -898,7 +898,8 @@ namespace test { ...@@ -898,7 +898,8 @@ namespace test {
const ref:&Smi = & array.a; const ref:&Smi = & array.a;
* ref = 3 + * ref; * ref = 3 + * ref;
-- * ref; -- * ref;
Swap(& array.b, array.GetA()); // TODO(gsps): Remove explicit type arg once inference works
Swap<Smi>(& array.b, array.GetA());
check(array.a == 2); check(array.a == 2);
check(array.b == 9); check(array.b == 9);
} }
...@@ -993,7 +994,7 @@ namespace test { ...@@ -993,7 +994,7 @@ namespace test {
const snd: T2; const snd: T2;
} }
macro Swap<T1: type, T2: type>(tuple: TestTuple<T1, T2>): macro TupleSwap<T1: type, T2: type>(tuple: TestTuple<T1, T2>):
TestTuple<T2, T1> { TestTuple<T2, T1> {
return TestTuple<T2, T1>{fst: tuple.snd, snd: tuple.fst}; return TestTuple<T2, T1>{fst: tuple.snd, snd: tuple.fst};
} }
...@@ -1001,7 +1002,7 @@ namespace test { ...@@ -1001,7 +1002,7 @@ namespace test {
@export @export
macro TestGenericStruct2(): TestTuple<Smi, intptr> { macro TestGenericStruct2(): TestTuple<Smi, intptr> {
const intptrAndSmi = TestTuple<intptr, Smi>{fst: 1, snd: 2}; const intptrAndSmi = TestTuple<intptr, Smi>{fst: 1, snd: 2};
const smiAndIntptr = Swap<intptr, Smi>(intptrAndSmi); const smiAndIntptr = TupleSwap<intptr, Smi>(intptrAndSmi);
check(intptrAndSmi.fst == smiAndIntptr.snd); check(intptrAndSmi.fst == smiAndIntptr.snd);
check(intptrAndSmi.snd == smiAndIntptr.fst); check(intptrAndSmi.snd == smiAndIntptr.fst);
return smiAndIntptr; return smiAndIntptr;
......
...@@ -20,6 +20,13 @@ constexpr const char* kTestTorquePrelude = R"( ...@@ -20,6 +20,13 @@ constexpr const char* kTestTorquePrelude = R"(
type void; type void;
type never; type never;
namespace torque_internal {
struct Reference<T: type> {
const object: HeapObject;
const offset: intptr;
}
}
type Tagged generates 'TNode<Object>' constexpr 'ObjectPtr'; type Tagged generates 'TNode<Object>' constexpr 'ObjectPtr';
type Smi extends Tagged generates 'TNode<Smi>' constexpr 'Smi'; type Smi extends Tagged generates 'TNode<Smi>' constexpr 'Smi';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment