[vm/tfa] Infer concrete class of string literals in TFA
Depending on a value of a string literal, it is possible to determine
concrete class at compile time (either _OneByteString or _TwoByteString).
Change-Id: Ied696b328021e9a61f1ad14d02b88681a9ed4fed
Reviewed-on: https://dart-review.googlesource.com/76260
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index d2b11a3..3a1ae91 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -200,6 +200,8 @@
Class concreteMapLiteralClass(CoreTypes coreTypes) => null;
Class concreteConstMapLiteralClass(CoreTypes coreTypes) => null;
+
+ Class concreteStringLiteralClass(CoreTypes coreTypes, String value) => null;
}
class NoneTarget extends Target {
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 8b75174..a62c3c5 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -24,6 +24,8 @@
Class _immutableList;
Class _internalLinkedHashMap;
Class _immutableMap;
+ Class _oneByteString;
+ Class _twoByteString;
VmTarget(this.flags);
@@ -321,4 +323,17 @@
return _immutableMap ??=
coreTypes.index.getClass('dart:core', '_ImmutableMap');
}
+
+ @override
+ Class concreteStringLiteralClass(CoreTypes coreTypes, String value) {
+ const int maxLatin1 = 0xff;
+ for (int i = 0; i < value.length; ++i) {
+ if (value.codeUnitAt(i) > maxLatin1) {
+ return _twoByteString ??=
+ coreTypes.index.getClass('dart:core', '_TwoByteString');
+ }
+ }
+ return _oneByteString ??=
+ coreTypes.index.getClass('dart:core', '_OneByteString');
+ }
}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 984521d..72b616b 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -554,6 +554,14 @@
Class get _superclass => _environment.thisType.classNode.superclass;
+ Type _stringLiteralType(String value) {
+ Class concreteClass =
+ target.concreteStringLiteralClass(_environment.coreTypes, value);
+ return concreteClass != null
+ ? _entryPointsListener.addAllocatedClass(concreteClass)
+ : _stringType;
+ }
+
void _handleNestedFunctionNode(FunctionNode node) {
var oldReturn = _returnValue;
var oldVariables = _variables;
@@ -892,7 +900,7 @@
@override
TypeExpr visitStringLiteral(StringLiteral node) {
- return _stringType;
+ return _stringLiteralType(node.value);
}
@override
@@ -1244,7 +1252,7 @@
@override
Type visitStringConstant(StringConstant constant) {
- return summaryCollector._stringType;
+ return summaryCollector._stringLiteralType(constant.value);
}
@override
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
index 35081b4..770e1df 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
@@ -1,4 +1,4 @@
------------ #lib::main ------------
%args = _Parameter #0 [_T (dart.core::List<dynamic>)+?]
-t1 = _Call direct [dart.core::print] (_T (dart.core::String)+)
+t1 = _Call direct [dart.core::print] (_T (dart.core::_OneByteString))
RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index e158e50..e25e859 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -12,7 +12,7 @@
;
operator [](core::int i) → core::double
return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int?] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=int] this.{self::_Vector::_offset}));
- operator []=([@vm.inferred-type.metadata=!] core::int i, core::double value) → void {
+ operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int i, core::double value) → void {
let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements} in let dynamic #t2 = i in let dynamic #t3 = [@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=int] this.{self::_Vector::_offset} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
}
operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector a) → core::double {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index 0e43e97..aebe06c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -48,7 +48,7 @@
static method callerA4([@vm.inferred-type.metadata=#lib::D?] self::A aa) → void {
[@vm.direct-call.metadata=#lib::C::foo??] aa.{self::A::foo}();
}
-static method callerE1([@vm.inferred-type.metadata=!] dynamic x) → void {
+static method callerE1([@vm.inferred-type.metadata=dart.core::_OneByteString] dynamic x) → void {
[@vm.direct-call.metadata=dart.core::_StringBase::toString] x.{core::Object::toString}();
}
static method callerE2([@vm.inferred-type.metadata=#lib::E?] dynamic x) → void {