Add partial instantiation support for constant evaluator [PartialInstantiationConstant]
Change-Id: Iaa93da60331737aaa6bceb4d2fe1d791dc7e95e9
Reviewed-on: https://dart-review.googlesource.com/52445
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 0cfe661..f87de3d 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -902,11 +902,22 @@
List<[FieldReference, ConstantReference]> values;
}
-type TearOffConstant extends Constant {
+type PartialInstantiationConstant extends Constant {
Byte tag = 8;
+ ConstantReference tearOffConstant;
+ List<DartType> typeArguments;
+}
+
+type TearOffConstant extends Constant {
+ Byte tag = 9;
CanonicalNameReference staticProcedureReference;
}
+type TypeLiteralConstant extends Constant {
+ Byte tag = 10;
+ DartType type;
+}
+
abstract type Statement extends Node {}
type ExpressionStatement extends Statement {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index d4983da..ce95e14 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -5386,6 +5386,34 @@
}
}
+class PartialInstantiationConstant extends Constant {
+ final TearOffConstant tearOffConstant;
+ final List<DartType> types;
+
+ PartialInstantiationConstant(this.tearOffConstant, this.types);
+
+ visitChildren(Visitor v) {
+ tearOffConstant.acceptReference(v);
+ visitList(types, v);
+ }
+
+ accept(ConstantVisitor v) => v.visitPartialInstantiationConstant(this);
+ acceptReference(Visitor v) =>
+ v.visitPartialInstantiationConstantReference(this);
+
+ String toString() {
+ return '${runtimeType}(${tearOffConstant.procedure}<${types.join(', ')}>)';
+ }
+
+ int get hashCode => tearOffConstant.hashCode ^ listHashCode(types);
+
+ bool operator ==(Object other) {
+ return other is PartialInstantiationConstant &&
+ other.tearOffConstant == tearOffConstant &&
+ listEquals(other.types, types);
+ }
+}
+
class TearOffConstant extends Constant {
final Reference procedureReference;
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 6749c74..bfdf151 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -215,6 +215,14 @@
fieldValues[fieldRef] = constant;
}
return new InstanceConstant(classReference, typeArguments, fieldValues);
+ case ConstantTag.PartialInstantiationConstant:
+ final tearOffConstant = readConstantReference() as TearOffConstant;
+ final int length = readUInt();
+ final List<DartType> types = new List<DartType>(length);
+ for (int i = 0; i < length; i++) {
+ types[i] = readDartType();
+ }
+ return new PartialInstantiationConstant(tearOffConstant, types);
case ConstantTag.TearOffConstant:
final Reference reference = readCanonicalNameReference().getReference();
return new TearOffConstant.byReference(reference);
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 6d4c937..f54d8bc 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -175,6 +175,14 @@
writeCanonicalNameReference(fieldRef.canonicalName);
writeConstantReference(value);
});
+ } else if (constant is PartialInstantiationConstant) {
+ writeByte(ConstantTag.PartialInstantiationConstant);
+ writeConstantReference(constant.tearOffConstant);
+ final int length = constant.types.length;
+ writeUInt30(length);
+ for (int i = 0; i < length; ++i) {
+ writeDartType(constant.types[i]);
+ }
} else if (constant is TearOffConstant) {
writeByte(ConstantTag.TearOffConstant);
writeCanonicalNameReference(constant.procedure.canonicalName);
@@ -1897,6 +1905,19 @@
}
@override
+ void visitPartialInstantiationConstant(PartialInstantiationConstant node) {
+ throw new UnsupportedError(
+ 'serialization of PartialInstantiationConstants ');
+ }
+
+ @override
+ void visitPartialInstantiationConstantReference(
+ PartialInstantiationConstant node) {
+ throw new UnsupportedError(
+ 'serialization of PartialInstantiationConstant references');
+ }
+
+ @override
void visitTearOffConstant(TearOffConstant node) {
throw new UnsupportedError('serialization of TearOffConstants ');
}
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index e55935e..bc70203 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -147,6 +147,7 @@
static const int MapConstant = 5;
static const int ListConstant = 6;
static const int InstanceConstant = 7;
- static const int TearOffConstant = 8;
- static const int TypeLiteralConstant = 9;
+ static const int PartialInstantiationConstant = 8;
+ static const int TearOffConstant = 9;
+ static const int TypeLiteralConstant = 10;
}
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index 84ae345..c618d81 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -729,6 +729,22 @@
return canonicalize(backend.buildSymbolConstant(value));
}
+ visitInstantiation(Instantiation node) {
+ final Constant constant = evaluate(node.expression);
+ if (constant is TearOffConstant) {
+ if (node.typeArguments.length ==
+ constant.procedure.function.typeParameters.length) {
+ return canonicalize(
+ new PartialInstantiationConstant(constant, node.typeArguments));
+ }
+ throw new ConstantEvaluationError(
+ 'The number of type arguments supplied in the partial instantiation '
+ 'does not match the number of type arguments of the $constant.');
+ }
+ throw new ConstantEvaluationError(
+ 'Only tear-off constants can be partially instantiated.');
+ }
+
// Helper methods:
void ensureIsSubtype(Constant constant, DartType type) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index fa6337c..cde0c92 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -283,6 +283,8 @@
R visitMapConstant(MapConstant node) => defaultConstant(node);
R visitListConstant(ListConstant node) => defaultConstant(node);
R visitInstanceConstant(InstanceConstant node) => defaultConstant(node);
+ R visitPartialInstantiationConstant(PartialInstantiationConstant node) =>
+ defaultConstant(node);
R visitTearOffConstant(TearOffConstant node) => defaultConstant(node);
R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
}
@@ -334,6 +336,8 @@
R visitMapConstant(MapConstant node) => defaultConstant(node);
R visitListConstant(ListConstant node) => defaultConstant(node);
R visitInstanceConstant(InstanceConstant node) => defaultConstant(node);
+ R visitPartialInstantiationConstant(PartialInstantiationConstant node) =>
+ defaultConstant(node);
R visitTearOffConstant(TearOffConstant node) => defaultConstant(node);
R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
@@ -359,6 +363,9 @@
defaultConstantReference(node);
R visitInstanceConstantReference(InstanceConstant node) =>
defaultConstantReference(node);
+ R visitPartialInstantiationConstantReference(
+ PartialInstantiationConstant node) =>
+ defaultConstantReference(node);
R visitTearOffConstantReference(TearOffConstant node) =>
defaultConstantReference(node);
R visitTypeLiteralConstantReference(TypeLiteralConstant node) =>
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 4b86b49..157e8186 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -10884,6 +10884,35 @@
temp_instance_ = H.Canonicalize(temp_instance_);
break;
}
+ case kPartialInstantiationConstant: {
+ const intptr_t entry_index = builder_.ReadUInt();
+ temp_object_ = constants.At(entry_index);
+
+ const intptr_t number_of_type_arguments = builder_.ReadUInt();
+ if (temp_class_.NumTypeArguments() > 0) {
+ temp_type_arguments_ =
+ TypeArguments::New(number_of_type_arguments, Heap::kOld);
+ for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
+ temp_type_arguments_.SetTypeAt(j, type_translator_.BuildType());
+ }
+ } else {
+ ASSERT(number_of_type_arguments == 0);
+ temp_type_arguments_ = TypeArguments::null();
+ }
+
+ // Make a copy of the old closure, with the delayed type arguments
+ // set to [temp_type_arguments_].
+ temp_closure_ = Closure::RawCast(temp_object_.raw());
+ temp_function_ = temp_closure_.function();
+ temp_type_arguments2_ = temp_closure_.instantiator_type_arguments();
+ temp_type_arguments3_ = temp_closure_.function_type_arguments();
+ temp_context_ = temp_closure_.context();
+ temp_closure_ = Closure::New(
+ temp_type_arguments2_, Object::null_type_arguments(),
+ temp_type_arguments_, temp_function_, temp_context_, Heap::kOld);
+ temp_instance_ = H.Canonicalize(temp_closure_);
+ break;
+ }
case kTearOffConstant: {
const NameIndex index = builder_.ReadCanonicalNameReference();
NameIndex lib_index = index;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 337c045d6..0396038 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -1680,12 +1680,16 @@
zone_(zone),
temp_type_(AbstractType::Handle(zone)),
temp_type_arguments_(TypeArguments::Handle(zone)),
+ temp_type_arguments2_(TypeArguments::Handle(zone)),
+ temp_type_arguments3_(TypeArguments::Handle(zone)),
temp_object_(Object::Handle(zone)),
temp_array_(Array::Handle(zone)),
temp_instance_(Instance::Handle(zone)),
temp_field_(Field::Handle(zone)),
temp_class_(Class::Handle(zone)),
temp_function_(Function::Handle(zone)),
+ temp_closure_(Closure::Handle(zone)),
+ temp_context_(Context::Handle(zone)),
temp_integer_(Integer::Handle(zone)) {}
// Reads the constant table from the binary.
@@ -1707,12 +1711,16 @@
Zone* zone_;
AbstractType& temp_type_;
TypeArguments& temp_type_arguments_;
+ TypeArguments& temp_type_arguments2_;
+ TypeArguments& temp_type_arguments3_;
Object& temp_object_;
Array& temp_array_;
Instance& temp_instance_;
Field& temp_field_;
Class& temp_class_;
Function& temp_function_;
+ Closure& temp_closure_;
+ Context& temp_context_;
Integer& temp_integer_;
};
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index a5521fc..e426f4d 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -149,8 +149,9 @@
kMapConstant = 5,
kListConstant = 6,
kInstanceConstant = 7,
- kTearOffConstant = 8,
- kTypeLiteralConstant = 9,
+ kPartialInstantiationConstant = 8,
+ kTearOffConstant = 9,
+ kTypeLiteralConstant = 10,
};
static const int SpecializedIntLiteralBias = 3;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c856133..f592c8c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -22765,6 +22765,16 @@
const Function& function,
const Context& context,
Heap::Space space) {
+ return Closure::New(instantiator_type_arguments, function_type_arguments,
+ Object::empty_type_arguments(), function, context, space);
+}
+
+RawClosure* Closure::New(const TypeArguments& instantiator_type_arguments,
+ const TypeArguments& function_type_arguments,
+ const TypeArguments& delayed_type_arguments,
+ const Function& function,
+ const Context& context,
+ Heap::Space space) {
Closure& result = Closure::Handle();
{
RawObject* raw =
@@ -22776,7 +22786,7 @@
result.StorePointer(&result.raw_ptr()->function_type_arguments_,
function_type_arguments.raw());
result.StorePointer(&result.raw_ptr()->delayed_type_arguments_,
- Object::empty_type_arguments().raw());
+ delayed_type_arguments.raw());
result.StorePointer(&result.raw_ptr()->function_, function.raw());
result.StorePointer(&result.raw_ptr()->context_, context.raw());
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index ea2c4d5..9b2c77e 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -8791,6 +8791,13 @@
const Context& context,
Heap::Space space = Heap::kNew);
+ static RawClosure* New(const TypeArguments& instantiator_type_arguments,
+ const TypeArguments& function_type_arguments,
+ const TypeArguments& delayed_type_arguments,
+ const Function& function,
+ const Context& context,
+ Heap::Space space = Heap::kNew);
+
RawFunction* GetInstantiatedSignature(Zone* zone) const;
private: