From 70f455351df6d283878b1226896b8e0609807688 Mon Sep 17 00:00:00 2001 From: Samir Jindel Date: Tue, 27 Mar 2018 22:26:07 +0000 Subject: [PATCH] [kernel] Add field for instantiate-to-bounds algorithm in TypeParameter. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Idd1859b378080f01dc5d5078ee0960021c1689b6 Reviewed-on: https://dart-review.googlesource.com/48424 Reviewed-by: RĂ©gis Crelier Reviewed-by: Dmitry Stefantsov --- pkg/kernel/binary.md | 1 + pkg/kernel/lib/ast.dart | 7 ++ pkg/kernel/lib/binary/ast_from_binary.dart | 1 + pkg/kernel/lib/binary/ast_to_binary.dart | 1 + pkg/kernel/lib/clone.dart | 3 + pkg/kernel/lib/text/ast_to_text.dart | 4 + .../frontend/kernel_binary_flowgraph.cc | 75 +++++++++++++------ .../frontend/kernel_binary_flowgraph.h | 43 ++++++++++- 8 files changed, 113 insertions(+), 22 deletions(-) diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md index 6179db37cf891..6a577c3c226f1 100644 --- a/pkg/kernel/binary.md +++ b/pkg/kernel/binary.md @@ -1200,6 +1200,7 @@ type TypeParameter { List annotations; StringReference name; // Cosmetic, may be empty, not unique. DartType bound; // 'dynamic' if no explicit bound was given. + Option defaultType; // type used when the parameter is not passed } ``` diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart index 099307e93bc1f..c2fa92f3c5b49 100644 --- a/pkg/kernel/lib/ast.dart +++ b/pkg/kernel/lib/ast.dart @@ -5220,6 +5220,13 @@ class TypeParameter extends TreeNode { /// be set to the root class for type parameters without an explicit bound. DartType bound; + /// The default value of the type variable. It is used to provide the + /// corresponding missing type argument in type annotations and as the + /// fall-back type value in type inference at compile time. At run time, + /// [defaultType] is used by the backends in place of the missing type + /// argument of a dynamic invocation of a generic function. + DartType defaultType; + TypeParameter([this.name, this.bound]); // Must match serialized bit positions. diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart index 4869901d817a0..951aeddb3dbe3 100644 --- a/pkg/kernel/lib/binary/ast_from_binary.dart +++ b/pkg/kernel/lib/binary/ast_from_binary.dart @@ -1750,6 +1750,7 @@ class BinaryBuilder { node.annotations = readAnnotationList(node); node.name = readStringOrNullIfEmpty(); node.bound = readDartType(); + node.defaultType = readDartTypeOption(); } Arguments readArguments() { diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart index a71ec328927e1..a050b728dbe0b 100644 --- a/pkg/kernel/lib/binary/ast_to_binary.dart +++ b/pkg/kernel/lib/binary/ast_to_binary.dart @@ -1716,6 +1716,7 @@ class BinaryPrinter implements Visitor, BinarySink { writeAnnotationList(node.annotations); writeStringReference(node.name ?? ''); writeNode(node.bound); + writeOptionalNode(node.defaultType); } // ================================================================ diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart index 39019020c5412..22dbf96d5f5c3 100644 --- a/pkg/kernel/lib/clone.dart +++ b/pkg/kernel/lib/clone.dart @@ -470,6 +470,9 @@ class CloneVisitor implements TreeVisitor { var newNode = new TypeParameter(node.name); typeSubstitution[node] = new TypeParameterType(newNode); newNode.bound = visitType(node.bound); + if (node.defaultType != null) { + newNode.defaultType = visitType(node.defaultType); + } return newNode..flags = node.flags; } diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart index ade2e8e3cebfa..1a19346045a03 100644 --- a/pkg/kernel/lib/text/ast_to_text.dart +++ b/pkg/kernel/lib/text/ast_to_text.dart @@ -1842,6 +1842,10 @@ class Printer extends Visitor { writeWord(getTypeParameterName(node)); writeSpaced('extends'); writeType(node.bound); + if (node.defaultType != null) { + writeSpaced('='); + writeType(node.defaultType); + } } visitConstantExpression(ConstantExpression node) { diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index 4761c27a16b91..43f80921894e6 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -80,6 +80,32 @@ void FunctionNodeHelper::ReadUntilExcluding(Field field) { } } +void TypeParameterHelper::ReadUntilExcluding(Field field) { + for (; next_read_ < field; ++next_read_) { + switch (next_read_) { + case kFlags: + flags_ = builder_->ReadFlags(); + break; + case kAnnotations: + builder_->SkipListOfExpressions(); // read annotations. + break; + case kName: + name_index_ = builder_->ReadStringReference(); // read name index. + break; + case kBound: + builder_->SkipDartType(); + break; + case kDefaultType: + if (builder_->ReadTag() == kSomething) { + builder_->SkipDartType(); + } + break; + case kEnd: + return; + } + } +} + void VariableDeclarationHelper::ReadUntilExcluding(Field field) { if (field <= next_read_) return; @@ -1189,10 +1215,14 @@ void StreamingScopeBuilder::VisitFunctionNode() { intptr_t list_length = builder_->ReadListLength(); // read type_parameters list length. for (intptr_t i = 0; i < list_length; ++i) { - builder_->ReadFlags(); // read flags. - builder_->SkipListOfExpressions(); // read annotations. - builder_->SkipStringReference(); // read ith name index. + TypeParameterHelper helper(builder_); + helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound); VisitDartType(); // read ith bound. + helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kDefaultType); + if (builder_->ReadTag() == kSomething) { + VisitDartType(); // read ith default type. + } + helper.Finish(); } function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters); @@ -1977,10 +2007,14 @@ void StreamingScopeBuilder::VisitFunctionType(bool simple) { intptr_t list_length = builder_->ReadListLength(); // read type_parameters list length. for (int i = 0; i < list_length; ++i) { - builder_->SkipFlags(); // read flags. - builder_->SkipListOfExpressions(); // read annotations. - builder_->SkipStringReference(); // read string index (name). - VisitDartType(); // read dart type. + TypeParameterHelper helper(builder_); + helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound); + VisitDartType(); // read bound. + helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kDefaultType); + if (builder_->ReadTag() == kSomething) { + VisitDartType(); // read default type. + } + helper.Finish(); } builder_->ReadUInt(); // read required parameter count. builder_->ReadUInt(); // read total parameter count. @@ -4569,10 +4603,11 @@ Fragment StreamingFlowGraphBuilder::BuildArgumentTypeChecks( } TypeParameter& forwarding_param = TypeParameter::Handle(Z); for (intptr_t i = 0; i < num_type_params; ++i) { - ReadFlags(); // skip flags - SkipListOfExpressions(); // skip annotations - String& name = H.DartSymbolObfuscate(ReadStringReference()); // read name + TypeParameterHelper helper(this); + helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound); + String& name = H.DartSymbolObfuscate(helper.name_index_); AbstractType& bound = T.BuildType(); // read bound + helper.Finish(); if (forwarding_target != NULL) { forwarding_param ^= forwarding_params.TypeAt(i); @@ -5488,10 +5523,8 @@ void StreamingFlowGraphBuilder::SkipListOfVariableDeclarations() { void StreamingFlowGraphBuilder::SkipTypeParametersList() { intptr_t list_length = ReadListLength(); // read list length. for (intptr_t i = 0; i < list_length; ++i) { - SkipFlags(); // read ith flags. - SkipListOfExpressions(); // read annotations. - SkipStringReference(); // read ith name index. - SkipDartType(); // read ith bound. + TypeParameterHelper helper(this); + helper.Finish(); } } @@ -9603,15 +9636,14 @@ void StreamingFlowGraphBuilder::LoadAndSetupTypeParameters( { AlternativeReadingScope alt(reader_); for (intptr_t i = 0; i < type_parameter_count; i++) { - SkipFlags(); - SkipListOfExpressions(); // read annotations. + TypeParameterHelper helper(this); + helper.Finish(); parameter = TypeParameter::New( set_on_class ? *active_class->klass : Class::Handle(Z), parameterized_function, i, - H.DartSymbolObfuscate(ReadStringReference()), // read ith name index. + H.DartSymbolObfuscate(helper.name_index_), // read ith name index. null_bound, TokenPosition::kNoSource); type_parameters.SetTypeAt(i, parameter); - SkipDartType(); // read guard. } } @@ -9629,9 +9661,8 @@ void StreamingFlowGraphBuilder::LoadAndSetupTypeParameters( // Step b) Fill in the bounds of all [TypeParameter]s. for (intptr_t i = 0; i < type_parameter_count; i++) { - SkipFlags(); - SkipListOfExpressions(); // read annotations. - SkipStringReference(); // read ith name index. + TypeParameterHelper helper(this); + helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound); // TODO(github.com/dart-lang/kernel/issues/42): This should be handled // by the frontend. @@ -9648,6 +9679,8 @@ void StreamingFlowGraphBuilder::LoadAndSetupTypeParameters( } parameter.set_bound(bound); } + + helper.Finish(); } } diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h index 0a16a9437f800..efef56d827160 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h @@ -76,11 +76,51 @@ class FunctionNodeHelper { intptr_t next_read_; }; -struct TypeParameterHelper { +class TypeParameterHelper { + public: + enum Field { + kStart, // tag. + kFlags, + kAnnotations, + kName, + kBound, + kDefaultType, + kEnd, + }; + enum Flag { kIsGenericCovariantImpl = 1 << 0, kIsGenericCovariantInterface = 1 << 1 }; + + explicit TypeParameterHelper(StreamingFlowGraphBuilder* builder) { + builder_ = builder; + next_read_ = kStart; + } + + void ReadUntilIncluding(Field field) { + ReadUntilExcluding(static_cast(static_cast(field) + 1)); + } + + void ReadUntilExcluding(Field field); + + void SetNext(Field field) { next_read_ = field; } + void SetJustRead(Field field) { next_read_ = field + 1; } + + void ReadUntilExcludingAndSetJustRead(Field field) { + ReadUntilExcluding(field); + SetJustRead(field); + } + + void Finish() { ReadUntilExcluding(kEnd); } + + TokenPosition position_; + uint8_t flags_; + StringIndex name_index_; + + private: + StreamingFlowGraphBuilder* builder_; + intptr_t next_read_; }; // Helper class that reads a kernel VariableDeclaration from binary. @@ -1434,6 +1474,7 @@ class StreamingFlowGraphBuilder { friend class StreamingDartTypeTranslator; friend class StreamingScopeBuilder; friend class VariableDeclarationHelper; + friend class TypeParameterHelper; }; class AlternativeScriptScope {