Version 2.1.0-dev.9.4
Cherry-pick e23acaaf90996b84548ea23af14730ff1a21d826 to dev
Cherry-pick e6d3a45b6a98ea36581ac375ec5cdd63dd829004 to dev
Cherry-pick a40fd6a976d3d3bc341cd2e0f7fb290b7819a52a to dev
Cherry-pick 9eb1d748819530bb3eb2f78699e0968de8b638fe to dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 54bc2bc..6ef0c56 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+# 2.1.0-dev.9.4
+
+Cherry-pick e23acaaf90996b84548ea23af14730ff1a21d826 to dev
+
+Cherry-pick e6d3a45b6a98ea36581ac375ec5cdd63dd829004 to dev
+
+Cherry-pick a40fd6a976d3d3bc341cd2e0f7fb290b7819a52a to dev
+
+Cherry-pick 9eb1d748819530bb3eb2f78699e0968de8b638fe to dev
+
# 2.1.0-dev.9.3
Cherry-pick 65951ef5080bcfa7d8862685e96f75c2c5d17841 to dev
diff --git a/pkg/vm/bin/dump_kernel.dart b/pkg/vm/bin/dump_kernel.dart
index f49a332..6a6b448 100644
--- a/pkg/vm/bin/dump_kernel.dart
+++ b/pkg/vm/bin/dump_kernel.dart
@@ -16,7 +16,6 @@
show ProcedureAttributesMetadataRepository;
import 'package:vm/metadata/unreachable.dart'
show UnreachableNodeMetadataRepository;
-
import 'package:vm/metadata/call_site_attributes.dart'
show CallSiteAttributesMetadataRepository;
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 31cf8b6..03c4a51 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -37,6 +37,8 @@
as no_dynamic_invocations_annotator show transformComponent;
import 'transformations/type_flow/transformer.dart' as globalTypeFlow
show transformComponent;
+import 'transformations/obfuscation_prohibitions_annotator.dart'
+ as obfuscationProhibitions;
/// Generates a kernel representation of the program whose main library is in
/// the given [source]. Intended for whole program (non-modular) compilation.
@@ -140,6 +142,10 @@
devirtualization.transformComponent(coreTypes, component);
no_dynamic_invocations_annotator.transformComponent(component);
}
+
+ // We don't know yet whether gen_snapshot will want to do obfuscation, but if
+ // it does it will need the obfuscation prohibitions.
+ obfuscationProhibitions.transformComponent(component, coreTypes);
}
/// Runs given [action] with [CompilerContext]. This is needed to
diff --git a/pkg/vm/lib/metadata/obfuscation_prohibitions.dart b/pkg/vm/lib/metadata/obfuscation_prohibitions.dart
new file mode 100644
index 0000000..f2b71e8
--- /dev/null
+++ b/pkg/vm/lib/metadata/obfuscation_prohibitions.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.metadata.obfuscation_prohibitions;
+
+import 'package:kernel/ast.dart';
+
+class ObfuscationProhibitionsMetadata {
+ final Set<String> protectedNames = Set<String>();
+
+ ObfuscationProhibitionsMetadata();
+
+ @override
+ String toString() => protectedNames.toString();
+}
+
+/// Repository for [ObfuscationProhibitionsMetadata].
+class ObfuscationProhibitionsMetadataRepository
+ extends MetadataRepository<ObfuscationProhibitionsMetadata> {
+ static final repositoryTag = 'vm.obfuscation-prohibitions.metadata';
+
+ @override
+ final String tag = repositoryTag;
+
+ @override
+ final Map<TreeNode, ObfuscationProhibitionsMetadata> mapping =
+ <TreeNode, ObfuscationProhibitionsMetadata>{};
+
+ @override
+ void writeToBinary(
+ ObfuscationProhibitionsMetadata metadata, Node node, BinarySink sink) {
+ sink.writeUInt32(metadata.protectedNames.length);
+ for (String name in metadata.protectedNames) {
+ sink.writeStringReference(name);
+ }
+ }
+
+ @override
+ ObfuscationProhibitionsMetadata readFromBinary(
+ Node node, BinarySource source) {
+ final metadata = ObfuscationProhibitionsMetadata();
+ int length = source.readUint32();
+ for (int i = 0; i < length; ++i) {
+ metadata.protectedNames.add(source.readStringReference());
+ }
+ return metadata;
+ }
+}
diff --git a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
new file mode 100644
index 0000000..8ff744d
--- /dev/null
+++ b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.transformations.obfuscation_prohibitions_annotator;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart' show CoreTypes;
+
+import '../metadata/obfuscation_prohibitions.dart';
+import 'pragma.dart';
+
+void transformComponent(Component component, CoreTypes coreTypes) {
+ final repo = new ObfuscationProhibitionsMetadataRepository();
+ component.addMetadataRepository(repo);
+ final visitor =
+ ObfuscationProhibitionsVisitor(ConstantPragmaAnnotationParser(coreTypes));
+ visitor.visitComponent(component);
+ repo.mapping[component] = visitor.metadata;
+}
+
+class ObfuscationProhibitionsVisitor extends RecursiveVisitor {
+ final PragmaAnnotationParser parser;
+ final metadata = ObfuscationProhibitionsMetadata();
+
+ ObfuscationProhibitionsVisitor(this.parser);
+
+ void _addIfEntryPoint(
+ List<Expression> annotations, String name, TreeNode node) {
+ for (var ann in annotations) {
+ ParsedPragma pragma = parser.parsePragma(ann);
+ if (pragma is ParsedEntryPointPragma) {
+ metadata.protectedNames.add(name);
+ if (node is Field) {
+ metadata.protectedNames.add(name + "=");
+ }
+ final parent = node.parent;
+ if (parent is Class) {
+ metadata.protectedNames.add(parent.name);
+ }
+ break;
+ }
+ }
+ }
+
+ @override
+ visitClass(Class klass) {
+ _addIfEntryPoint(klass.annotations, klass.name, klass);
+ klass.visitChildren(this);
+ }
+
+ @override
+ visitProcedure(Procedure proc) {
+ _addIfEntryPoint(proc.annotations, proc.name.name, proc);
+ }
+
+ @override
+ visitField(Field field) {
+ _addIfEntryPoint(field.annotations, field.name.name, field);
+ }
+}
diff --git a/pkg/vm/lib/transformations/pragma.dart b/pkg/vm/lib/transformations/pragma.dart
new file mode 100644
index 0000000..3252cc3
--- /dev/null
+++ b/pkg/vm/lib/transformations/pragma.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.transformations.pragma;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart' show CoreTypes;
+
+const kEntryPointPragmaName = "vm:entry-point";
+const kExactResultTypePragmaName = "vm:exact-result-type";
+
+abstract class ParsedPragma {}
+
+enum PragmaEntryPointType { Always, GetterOnly, SetterOnly }
+
+class ParsedEntryPointPragma extends ParsedPragma {
+ final PragmaEntryPointType type;
+ ParsedEntryPointPragma(this.type);
+}
+
+class ParsedResultTypeByTypePragma extends ParsedPragma {
+ final DartType type;
+ ParsedResultTypeByTypePragma(this.type);
+}
+
+class ParsedResultTypeByPathPragma extends ParsedPragma {
+ final String path;
+ ParsedResultTypeByPathPragma(this.path);
+}
+
+abstract class PragmaAnnotationParser {
+ /// May return 'null' if the annotation does not represent a recognized
+ /// @pragma.
+ ParsedPragma parsePragma(Expression annotation);
+}
+
+class ConstantPragmaAnnotationParser extends PragmaAnnotationParser {
+ final CoreTypes coreTypes;
+
+ ConstantPragmaAnnotationParser(this.coreTypes);
+
+ ParsedPragma parsePragma(Expression annotation) {
+ InstanceConstant pragmaConstant;
+ if (annotation is ConstantExpression) {
+ Constant constant = annotation.constant;
+ if (constant is InstanceConstant) {
+ if (constant.classReference.node == coreTypes.pragmaClass) {
+ pragmaConstant = constant;
+ }
+ }
+ }
+ if (pragmaConstant == null) return null;
+
+ String pragmaName;
+ Constant name = pragmaConstant.fieldValues[coreTypes.pragmaName.reference];
+ if (name is StringConstant) {
+ pragmaName = name.value;
+ } else {
+ return null;
+ }
+
+ Constant options =
+ pragmaConstant.fieldValues[coreTypes.pragmaOptions.reference];
+ assert(options != null);
+
+ switch (pragmaName) {
+ case kEntryPointPragmaName:
+ PragmaEntryPointType type;
+ if (options is NullConstant) {
+ type = PragmaEntryPointType.Always;
+ } else if (options is BoolConstant && options.value == true) {
+ type = PragmaEntryPointType.Always;
+ } else if (options is StringConstant) {
+ if (options.value == "get") {
+ type = PragmaEntryPointType.GetterOnly;
+ } else if (options.value == "set") {
+ type = PragmaEntryPointType.SetterOnly;
+ } else {
+ throw "Error: string directive to @pragma('$kEntryPointPragmaName', ...) "
+ "must be either 'get' or 'set'.";
+ }
+ }
+ return type != null ? new ParsedEntryPointPragma(type) : null;
+ case kExactResultTypePragmaName:
+ if (options == null) return null;
+ if (options is TypeLiteralConstant) {
+ return new ParsedResultTypeByTypePragma(options.type);
+ } else if (options is StringConstant) {
+ return new ParsedResultTypeByPathPragma(options.value);
+ }
+ throw "ERROR: Unsupported option to '$kExactResultTypePragmaName' "
+ "pragma: $options";
+ default:
+ return null;
+ }
+ }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 903431c..a7dc830 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -22,6 +22,7 @@
import 'summary_collector.dart';
import 'types.dart';
import 'utils.dart';
+import '../pragma.dart';
// TODO(alexmarkov)
// Unordered list of various improvements in type flow analysis,
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index 8497461..cb6b7ce 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -8,12 +8,12 @@
import 'dart:core' hide Type;
import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'calls.dart';
import 'types.dart';
import 'utils.dart';
+import '../pragma.dart';
abstract class EntryPointsListener {
/// Add call by the given selector with arbitrary ('raw') arguments.
@@ -33,96 +33,6 @@
void recordMemberCalledViaThis(Member target);
}
-abstract class ParsedPragma {}
-
-enum PragmaEntryPointType { Always, GetterOnly, SetterOnly }
-
-class ParsedEntryPointPragma extends ParsedPragma {
- final PragmaEntryPointType type;
- ParsedEntryPointPragma(this.type);
-}
-
-class ParsedResultTypeByTypePragma extends ParsedPragma {
- final DartType type;
- ParsedResultTypeByTypePragma(this.type);
-}
-
-class ParsedResultTypeByPathPragma extends ParsedPragma {
- final String path;
- ParsedResultTypeByPathPragma(this.path);
-}
-
-const kEntryPointPragmaName = "vm:entry-point";
-const kExactResultTypePragmaName = "vm:exact-result-type";
-
-abstract class PragmaAnnotationParser {
- /// May return 'null' if the annotation does not represent a recognized
- /// @pragma.
- ParsedPragma parsePragma(Expression annotation);
-}
-
-class ConstantPragmaAnnotationParser extends PragmaAnnotationParser {
- final CoreTypes coreTypes;
-
- ConstantPragmaAnnotationParser(this.coreTypes);
-
- ParsedPragma parsePragma(Expression annotation) {
- InstanceConstant pragmaConstant;
- if (annotation is ConstantExpression) {
- Constant constant = annotation.constant;
- if (constant is InstanceConstant) {
- if (constant.classReference.node == coreTypes.pragmaClass) {
- pragmaConstant = constant;
- }
- }
- }
- if (pragmaConstant == null) return null;
-
- String pragmaName;
- Constant name = pragmaConstant.fieldValues[coreTypes.pragmaName.reference];
- if (name is StringConstant) {
- pragmaName = name.value;
- } else {
- return null;
- }
-
- Constant options =
- pragmaConstant.fieldValues[coreTypes.pragmaOptions.reference];
- assertx(options != null);
-
- switch (pragmaName) {
- case kEntryPointPragmaName:
- PragmaEntryPointType type;
- if (options is NullConstant) {
- type = PragmaEntryPointType.Always;
- } else if (options is BoolConstant && options.value == true) {
- type = PragmaEntryPointType.Always;
- } else if (options is StringConstant) {
- if (options.value == "get") {
- type = PragmaEntryPointType.GetterOnly;
- } else if (options.value == "set") {
- type = PragmaEntryPointType.SetterOnly;
- } else {
- throw "Error: string directive to @pragma('$kEntryPointPragmaName', ...) "
- "must be either 'get' or 'set'.";
- }
- }
- return type != null ? new ParsedEntryPointPragma(type) : null;
- case kExactResultTypePragmaName:
- if (options == null) return null;
- if (options is TypeLiteralConstant) {
- return new ParsedResultTypeByTypePragma(options.type);
- } else if (options is StringConstant) {
- return new ParsedResultTypeByPathPragma(options.value);
- }
- throw "ERROR: Unsupported option to '$kExactResultTypePragmaName' "
- "pragma: $options";
- default:
- return null;
- }
- }
-}
-
class PragmaEntryPointsVisitor extends RecursiveVisitor {
final EntryPointsListener entryPoints;
final NativeCodeOracle nativeCodeOracle;
@@ -145,13 +55,15 @@
@override
visitClass(Class klass) {
- var type = _annotationsDefineRoot(klass.annotations);
- if (type != null) {
- if (type != PragmaEntryPointType.Always) {
- throw "Error: pragma entry-point definition on a class must evaluate "
- "to null, true or false. See entry_points_pragma.md.";
+ if (!klass.isAbstract) {
+ var type = _annotationsDefineRoot(klass.annotations);
+ if (type != null) {
+ if (type != PragmaEntryPointType.Always) {
+ throw "Error: pragma entry-point definition on a class must evaluate "
+ "to null, true or false. See entry_points_pragma.md.";
+ }
+ entryPoints.addAllocatedClass(klass);
}
- entryPoints.addAllocatedClass(klass);
}
currentClass = klass;
klass.visitChildren(this);
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index bc6bb28..0937ab8 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -15,11 +15,11 @@
import 'package:kernel/type_environment.dart';
import 'analysis.dart';
-import 'native_code.dart';
import 'calls.dart';
import 'summary_collector.dart';
import 'types.dart';
import 'utils.dart';
+import '../pragma.dart';
import '../devirtualization.dart' show Devirtualization;
import '../../metadata/direct_call.dart';
import '../../metadata/inferred_type.dart';
diff --git a/pkg/vm/test/transformations/type_flow/annotation_matcher.dart b/pkg/vm/test/transformations/type_flow/annotation_matcher.dart
index cd3e21c..1b959c5 100644
--- a/pkg/vm/test/transformations/type_flow/annotation_matcher.dart
+++ b/pkg/vm/test/transformations/type_flow/annotation_matcher.dart
@@ -4,8 +4,8 @@
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
-import 'package:vm/transformations/type_flow/native_code.dart';
import 'package:vm/transformations/type_flow/utils.dart';
+import 'package:vm/transformations/pragma.dart';
// Since we don't run the constants transformation in this test, we can't
// recognize all pragma annotations precisely. Instead, we pattern match on
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 7141c73..a9b3637 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -60,6 +60,7 @@
new _RandomAccessFileOpsImpl(pointer);
}
+@pragma("vm:entry-point")
class _RandomAccessFileOpsImpl extends NativeFieldWrapperClass1
implements _RandomAccessFileOps {
_RandomAccessFileOpsImpl._();
diff --git a/runtime/bin/namespace_patch.dart b/runtime/bin/namespace_patch.dart
index 0b85a14..488aaf5 100644
--- a/runtime/bin/namespace_patch.dart
+++ b/runtime/bin/namespace_patch.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+@pragma("vm:entry-point")
class _NamespaceImpl extends NativeFieldWrapperClass1 implements _Namespace {
_NamespaceImpl._();
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index 432b42c..5d61f88 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -18,6 +18,7 @@
}
@patch
+@pragma("vm:entry-point")
class X509Certificate {
@patch
@pragma("vm:entry-point")
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 366ee58..a4b8956 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -373,6 +373,12 @@
}
await new Future<Null>.delayed(const Duration(seconds: 1));
}
+ if (_service.isExiting) {
+ serverPrint('Observatory HTTP server exiting before listening as '
+ 'vm service has received exit request\n');
+ await shutdown(true);
+ return this;
+ }
_server.listen(_requestHandler, cancelOnError: true);
serverPrint('Observatory listening on $serverAddress');
if (Platform.isFuchsia) {
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 96ed0ac..4f53173 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -148,6 +148,7 @@
}
@patch
+@pragma("vm:entry-point")
class UnsupportedError {
static _throwNew(String msg) {
throw new UnsupportedError(msg);
@@ -205,6 +206,7 @@
// The compiler emits a call to _throwNew when it cannot resolve a static
// method at compile time. The receiver is actually the literal class of the
// unresolved method.
+ @pragma("vm:entry-point")
static void _throwNew(Object receiver, String memberName, int invocation_type,
Object typeArguments, List arguments, List argumentNames) {
throw new NoSuchMethodError._withType(receiver, memberName, invocation_type,
diff --git a/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart b/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
index b40c5a9..fbe62fa 100644
--- a/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
+++ b/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
@@ -9,14 +9,17 @@
import "package:expect/expect.dart";
class A {
+ @pragma("vm:entry-point") // Prevent obfuscation
void foo() {
Expect.fail('A.foo should not be reachable');
}
+ @pragma("vm:entry-point") // Prevent obfuscation
dynamic get bar {
Expect.fail('A.bar should not be reachable');
}
+ @pragma("vm:entry-point") // Prevent obfuscation
set bazz(int x) {
Expect.fail('A.bazz should not be reachable');
}
diff --git a/runtime/tests/vm/dart/inline_stack_frame_test.dart b/runtime/tests/vm/dart/inline_stack_frame_test.dart
index 673d4c9..68c8584 100644
--- a/runtime/tests/vm/dart/inline_stack_frame_test.dart
+++ b/runtime/tests/vm/dart/inline_stack_frame_test.dart
@@ -17,6 +17,7 @@
// func2 is not inlined as func1 has not been optimized.
class Test {
+ @pragma("vm:entry-point")
String func1(var k) {
try {
for (var i = 0; i <= 50; i++) {
@@ -29,6 +30,7 @@
}
}
+ @pragma("vm:entry-point")
int func2(var i) {
var result = 0;
for (var k = 0; k <= 10; k++) {
@@ -37,6 +39,7 @@
return result;
}
+ @pragma("vm:entry-point")
int func3(var i) {
var result = 0;
for (var l = 0; l <= 1; l++) {
@@ -45,6 +48,7 @@
return result;
}
+ @pragma("vm:entry-point")
int func4(var i) {
var result = 0;
for (var j = 0; j <= 10; j++) {
@@ -53,6 +57,7 @@
return result;
}
+ @pragma("vm:entry-point")
int func5(var i) {
if (i >= 520) throw "show me inlined functions";
return i;
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index d4ed053..cfd49dc 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -355,3 +355,7 @@
[ ($runtime == vm || $runtime == dart_precompiled) && !$preview_dart_2 ]
*:SkipByDesign # Deprecating all Dart1 modes of execution
+
+[ $builder_tag == obfuscated && $compiler == dartkp ]
+dart/optimized_stacktrace_line_and_column_test: SkipByDesign # Looks for filenames in stacktrace output
+dart/optimized_stacktrace_line_test: SkipByDesign # Looks for filenames in stacktrace output
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 484dcd5..37d6578 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -90,8 +90,13 @@
return ApiError::New(msg, Heap::kOld);
}
kernel::KernelLoader loader(program);
+
Isolate* isolate = thread->isolate();
+ if (isolate->obfuscate()) {
+ loader.ReadObfuscationProhibitions();
+ }
+
// Load the bootstrap libraries in order (see object_store.h).
Library& library = Library::Handle(zone);
String& dart_name = String::Handle(zone);
diff --git a/runtime/vm/compiler/aot/entry_points_pragma.md b/runtime/vm/compiler/aot/entry_points_pragma.md
index 363bea3..dfdecfe 100644
--- a/runtime/vm/compiler/aot/entry_points_pragma.md
+++ b/runtime/vm/compiler/aot/entry_points_pragma.md
@@ -15,11 +15,16 @@
methods which call into Dart, the entry points are required for the correctness
of compilation.
+In addition, when obfuscation is enabled, the precompiler needs to know which
+symbols need to be preserved to ensure they can be resolved from native code.
+
# Pragma annotation
The annotation `@pragma("vm:entry-point", ...)` can be placed on a class or
-member to indicate that it may be allocated or invoked directly from native or
-VM code. The allowed uses of the annotation are as follows.
+member to indicate that it may be resolved, allocated or invoked directly from
+native or VM code.
+
+The allowed uses of the annotation are as follows.
## Classes
@@ -35,6 +40,10 @@
If the second parameter is missing, `null` or `true`, the class will be
available for allocation directly from native or VM code.
+Note that `@pragma("vm:entry-point")` may be added to abstract classes -- in
+this case, their name will survive obfuscation, but they won't have any
+allocation stubs.
+
## Procedures
Any one of the following forms may be attached to a procedure (including
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index ea575f2..c272742 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2565,10 +2565,6 @@
}
void Obfuscator::InitializeRenamingMap(Isolate* isolate) {
- // Prevent renaming of classes and method names mentioned in the
- // entry points lists.
- PreventRenaming(isolate->embedder_entry_points());
-
// Prevent renaming of all pseudo-keywords and operators.
// Note: not all pseudo-keywords are mentioned in DART_KEYWORD_LIST
// (for example 'hide', 'show' and async related keywords are omitted).
@@ -2674,25 +2670,6 @@
return renamed_.raw();
}
-void Obfuscator::PreventRenaming(Dart_QualifiedFunctionName entry_points[]) {
- for (intptr_t i = 0; entry_points[i].function_name != NULL; i++) {
- const char* class_name = entry_points[i].class_name;
- const char* function_name = entry_points[i].function_name;
-
- const size_t class_name_len = strlen(class_name);
- if (strncmp(function_name, class_name, class_name_len) == 0 &&
- function_name[class_name_len] == '.') {
- const char* ctor_name = function_name + class_name_len + 1;
- if (ctor_name[0] != '\0') {
- PreventRenaming(ctor_name);
- }
- } else {
- PreventRenaming(function_name);
- }
- PreventRenaming(class_name);
- }
-}
-
static const char* const kGetterPrefix = "get:";
static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
static const char* const kSetterPrefix = "set:";
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index c07ff41..a884b26 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -9,6 +9,7 @@
#include "vm/hash_map.h"
#include "vm/hash_table.h"
#include "vm/object.h"
+#include "vm/symbols.h"
namespace dart {
@@ -439,13 +440,13 @@
// Serialize renaming map as a malloced array of strings.
static const char** SerializeMap(Thread* thread);
+ void PreventRenaming(const char* name);
+ void PreventRenaming(const String& name) { state_->PreventRenaming(name); }
+
private:
// Populate renaming map with names that should have identity renaming.
// (or in other words: with those names that should not be renamed).
void InitializeRenamingMap(Isolate* isolate);
- void PreventRenaming(Dart_QualifiedFunctionName* entry_points);
- void PreventRenaming(const char* name);
- void PreventRenaming(const String& name) { state_->PreventRenaming(name); }
// ObjectStore::obfuscation_map() is an Array with two elements:
// first element is the last used rename and the second element is
@@ -562,6 +563,7 @@
return name.raw();
}
+ void PreventRenaming(const String& name) {}
static void ObfuscateSymbolInstance(Thread* thread,
const Instance& instance) {}
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 548ec56..cd8350c 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1793,9 +1793,9 @@
break;
}
- if ((kSmiBits < 32) && (unboxed == kTagged) && phi->Type()->IsInt() &&
+ if ((unboxed == kTagged) && phi->Type()->IsInt() &&
RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt64)) {
- // On 32-bit platforms conservatively unbox phis that:
+ // Conservatively unbox phis that:
// - are proven to be of type Int;
// - fit into 64bits range;
// - have either constants or Box() operations as inputs;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 4240758..f3d72fb 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -320,8 +320,7 @@
if (destination.IsRegister()) {
if (representation() == kUnboxedInt32 ||
representation() == kUnboxedInt64) {
- const int64_t value = value_.IsSmi() ? Smi::Cast(value_).Value()
- : Mint::Cast(value_).value();
+ const int64_t value = Integer::Cast(value_).AsInt64Value();
__ LoadImmediate(destination.reg(), value);
} else {
ASSERT(representation() == kTagged);
@@ -346,9 +345,12 @@
ASSERT(destination.IsStackSlot());
ASSERT(tmp != kNoRegister);
const intptr_t dest_offset = destination.ToStackSlotOffset();
- if (value_.IsSmi() && representation() == kUnboxedInt32) {
- __ LoadImmediate(tmp, static_cast<int32_t>(Smi::Cast(value_).Value()));
+ if (representation() == kUnboxedInt32 ||
+ representation() == kUnboxedInt64) {
+ const int64_t value = Integer::Cast(value_).AsInt64Value();
+ __ LoadImmediate(tmp, value);
} else {
+ ASSERT(representation() == kTagged);
__ LoadObject(tmp, value_);
}
__ StoreToOffset(tmp, destination.base_reg(), dest_offset);
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 4f02fbd..a4709d6 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -291,8 +291,7 @@
if (destination.IsRegister()) {
if (representation() == kUnboxedInt32 ||
representation() == kUnboxedInt64) {
- const int64_t value = value_.IsSmi() ? Smi::Cast(value_).Value()
- : Mint::Cast(value_).value();
+ const int64_t value = Integer::Cast(value_).AsInt64Value();
if (value == 0) {
__ xorl(destination.reg(), destination.reg());
} else {
@@ -322,10 +321,12 @@
__ movsd(destination.ToStackSlotAddress(), XMM0);
} else {
ASSERT(destination.IsStackSlot());
- if (value_.IsSmi() && representation() == kUnboxedInt32) {
- __ movl(destination.ToStackSlotAddress(),
- Immediate(Smi::Cast(value_).Value()));
+ if (representation() == kUnboxedInt32 ||
+ representation() == kUnboxedInt64) {
+ const int64_t value = Integer::Cast(value_).AsInt64Value();
+ __ movq(destination.ToStackSlotAddress(), Immediate(value));
} else {
+ ASSERT(representation() == kTagged);
__ StoreObject(destination.ToStackSlotAddress(), value_);
}
}
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 28eb035..988d0834 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -223,6 +223,7 @@
INVOKE_PASS(TypePropagation);
INVOKE_PASS(ApplyClassIds);
INVOKE_PASS(TypePropagation);
+ INVOKE_PASS(ApplyICData);
INVOKE_PASS(Canonicalize);
INVOKE_PASS(BranchSimplify);
INVOKE_PASS(IfConvert);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index d5676ab..df8096b 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -1422,12 +1422,12 @@
Reader reader(H.metadata_mappings());
reader.set_offset(mappings_offset);
- intptr_t prev_node_offset = 0;
+ intptr_t prev_node_offset = -1;
for (intptr_t i = 0; i < mappings_num; ++i) {
intptr_t node_offset = reader.ReadUInt32();
intptr_t md_offset = reader.ReadUInt32();
- ASSERT((node_offset > 0) && (md_offset >= 0));
+ ASSERT((node_offset >= 0) && (md_offset >= 0));
ASSERT(node_offset > prev_node_offset);
prev_node_offset = node_offset;
}
@@ -1715,6 +1715,28 @@
return metadata;
}
+ObfuscationProhibitionsMetadataHelper::ObfuscationProhibitionsMetadataHelper(
+ KernelReaderHelper* helper)
+ : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
+
+void ObfuscationProhibitionsMetadataHelper::ReadMetadata(intptr_t node_offset) {
+ intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
+ if (md_offset < 0) {
+ return;
+ }
+
+ AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
+ md_offset);
+ Obfuscator O(Thread::Current(), String::Handle());
+
+ intptr_t len = helper_->ReadUInt32();
+ for (int i = 0; i < len; ++i) {
+ StringIndex name = helper_->ReadStringReference();
+ O.PreventRenaming(translation_helper_.DartSymbolPlain(name));
+ }
+ return;
+}
+
CallSiteAttributesMetadataHelper::CallSiteAttributesMetadataHelper(
KernelReaderHelper* helper,
TypeTranslator* type_translator)
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index cb7dc87..949c0b5 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -903,6 +903,20 @@
DISALLOW_COPY_AND_ASSIGN(ProcedureAttributesMetadataHelper);
};
+class ObfuscationProhibitionsMetadataHelper : public MetadataHelper {
+ public:
+ static const char* tag() { return "vm.obfuscation-prohibitions.metadata"; }
+
+ explicit ObfuscationProhibitionsMetadataHelper(KernelReaderHelper* helper);
+
+ void ReadProhibitions() { ReadMetadata(0); }
+
+ private:
+ void ReadMetadata(intptr_t node_offset);
+
+ DISALLOW_COPY_AND_ASSIGN(ObfuscationProhibitionsMetadataHelper);
+};
+
struct CallSiteAttributesMetadata {
const AbstractType* receiver_type = nullptr;
};
@@ -1065,6 +1079,7 @@
friend class TypeParameterHelper;
friend class TypeTranslator;
friend class VariableDeclarationHelper;
+ friend class ObfuscationProhibitionsMetadataHelper;
friend bool NeedsDynamicInvocationForwarder(const Function& function);
private:
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a658ab7..92e7895 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5029,6 +5029,14 @@
RETURN_TYPE_ERROR(Z, library, Library);
}
+static void CheckIsEntryPoint(const Class& klass) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ // This is not a completely thorough check that the class is an entry-point,
+ // but it catches most missing annotations.
+ RELEASE_ASSERT(klass.has_pragma());
+#endif
+}
+
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
Dart_Handle class_name) {
DARTSCOPE(Thread::Current());
@@ -5047,6 +5055,7 @@
return Api::NewError("Class '%s' not found in library '%s'.",
cls_name.ToCString(), lib_name.ToCString());
}
+ CheckIsEntryPoint(cls);
return Api::NewHandle(T, cls.RareType());
}
@@ -5075,6 +5084,7 @@
return Api::NewError("Type '%s' not found in library '%s'.",
name_str.ToCString(), lib_name.ToCString());
}
+ CheckIsEntryPoint(cls);
if (cls.NumTypeArguments() == 0) {
if (number_of_type_arguments != 0) {
return Api::NewError(
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 36aead1..2a5ed7e 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -122,6 +122,8 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ ASSERT(!function.IsNull());
+
// Get the entrypoint corresponding to the function specified, this
// will result in a compilation of the function if it is not already
// compiled.
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 92c0a87..c1c1adf 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -203,6 +203,11 @@
InitializeFields();
}
+void KernelLoader::ReadObfuscationProhibitions() {
+ ObfuscationProhibitionsMetadataHelper helper(&helper_);
+ helper.ReadProhibitions();
+}
+
Object& KernelLoader::LoadEntireProgram(Program* program,
bool process_pending_classes) {
Thread* thread = Thread::Current();
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index bb4a16b..b8a99fd 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -174,6 +174,8 @@
static void FinishLoading(const Class& klass);
+ void ReadObfuscationProhibitions();
+
const Array& ReadConstantTable();
// Check for the presence of a (possibly const) constructor for the
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 015c414..e569785 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -493,6 +493,7 @@
* This [Error] is thrown when an instance cannot implement one of the methods
* in its signature.
*/
+@pragma("vm:entry-point")
class UnsupportedError extends Error {
final String message;
@pragma("vm:entry-point")
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index d782b67..74870cb 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -49,6 +49,7 @@
* An [OSError] object holds information about an error from the
* operating system.
*/
+@pragma("vm:entry-point")
class OSError {
/** Constant used to indicate that no OS error code is available. */
static const int noErrorCode = -1;
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index 2fc0930..2f141cb 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -111,6 +111,7 @@
* a tutorial about writing command-line apps, includes information about
* files and directories.
*/
+@pragma("vm:entry-point")
abstract class Directory implements FileSystemEntity {
/**
* Gets the path of this directory.
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 6fe447f..a7f4c66 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -237,6 +237,7 @@
* a tutorial about writing command-line apps, includes information about
* files and directories.
*/
+@pragma("vm:entry-point")
abstract class File implements FileSystemEntity {
/**
* Creates a [File] object.
@@ -956,6 +957,7 @@
/**
* Exception thrown when a file operation fails.
*/
+@pragma("vm:entry-point")
class FileSystemException implements IOException {
/**
* Message describing the error. This does not include any detailed
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 45cfc29..01b1d67 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -8,6 +8,7 @@
* [Link] objects are references to filesystem links.
*
*/
+@pragma("vm:entry-point")
abstract class Link implements FileSystemEntity {
/**
* Creates a Link object.
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index eb3504f..787762b 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -377,6 +377,7 @@
* X509Certificate represents an SSL certificate, with accessors to
* get the fields of the certificate.
*/
+@pragma("vm:entry-point")
abstract class X509Certificate {
@pragma("vm:entry-point")
external factory X509Certificate._();
@@ -1288,6 +1289,7 @@
* An exception that happens in the handshake phase of establishing
* a secure network connection.
*/
+@pragma("vm:entry-point")
class HandshakeException extends TlsException {
@pragma("vm:entry-point")
const HandshakeException([String message = "", OSError osError = null])
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index e8a5600..2cccb59 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -204,6 +204,9 @@
/// Collection of currently running isolates.
RunningIsolates runningIsolates = new RunningIsolates();
+ /// Flag to indicate VM service is exiting.
+ bool isExiting = false;
+
/// A port used to receive events from the VM.
final RawReceivePort eventPort;
@@ -323,6 +326,8 @@
}
Future _exit() async {
+ isExiting = true;
+
// Stop the server.
if (VMServiceEmbedderHooks.serverStop != null) {
await VMServiceEmbedderHooks.serverStop();
@@ -342,6 +347,7 @@
if (VMServiceEmbedderHooks.cleanup != null) {
await VMServiceEmbedderHooks.cleanup();
}
+
// Notify the VM that we have exited.
_onExit();
}
diff --git a/tests/corelib_2/apply_test.dart b/tests/corelib_2/apply_test.dart
index 9a3e94b..01f2e1c 100644
--- a/tests/corelib_2/apply_test.dart
+++ b/tests/corelib_2/apply_test.dart
@@ -31,7 +31,6 @@
main() {
testMap(res, func, map) {
- map = symbolMapToStringMap(map);
Expect.equals(res, Function.apply(func, null, map));
Expect.equals(res, Function.apply(func, [], map));
}
@@ -45,17 +44,16 @@
testListTyped(res, Function func, list) => testList(res, func, list);
test(res, func, list, map) {
- map = symbolMapToStringMap(map);
Expect.equals(res, Function.apply(func, list, map));
}
testList(42, test0, null);
testList(42, test0, []);
- testMap(42, test0a, {"a": 5});
+ testMap(42, test0a, {#a: 5});
testList(42, test1, [41]);
- test(42, test1a, [20], {"a": 22});
+ test(42, test1a, [20], {#a: 22});
testList(42, test2, [20, 22]);
- test(42, test2a, [10, 15], {"a": 17});
+ test(42, test2a, [10, 15], {#a: 17});
// Test that "this" is correct when calling closurized functions.
var cfoo = new C().foo;
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 8291f39..2723fd2 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -132,6 +132,12 @@
[ $arch == x64 && $system == windows ]
stopwatch_test: Skip # Flaky test due to expected performance behaviour.
+[ $builder_tag == obfuscated && $runtime == dart_precompiled ]
+apply_generic_function_test: SkipByDesign # Function.apply with named args
+apply_test: Skip # Uses new Symbol via symbolMapToStringMap helper
+dynamic_nosuchmethod_test: SkipByDesign # Expects names in NSM
+error_stack_trace1_test: SkipByDesign # Expects unobfuscated stack trace
+
# All static_tests have expected compile-time errors.
[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $compiler != fasta && $strong ]
core_runtime_types_static_test: MissingCompileTimeError
@@ -310,10 +316,6 @@
[ $mode == release && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
bigint_parse_radix_test: Crash
-[ $runtime == dart_precompiled && $minified ]
-apply_test: Skip # Uses new Symbol via symbolMapToStringMap helper
-error_stack_trace1_test: Skip # Expects unobfuscated stack trace
-
[ $runtime != none && ($compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk) ]
bit_twiddling_test/int64: RuntimeError, OK # Requires fixed-size int64 support.
compare_to2_test: RuntimeError, OK # Requires fixed-size int64 support.
diff --git a/tests/kernel/kernel.status b/tests/kernel/kernel.status
index fd35205..bb0a776 100644
--- a/tests/kernel/kernel.status
+++ b/tests/kernel/kernel.status
@@ -11,6 +11,9 @@
[ !$fasta ]
unsorted/loop_test: Skip # This test uses optional new/const.
+[ $builder_tag == obfuscated && $runtime == dart_precompiled ]
+unsorted/symbol_literal_test: RuntimeError # Issue 34911
+
[ $compiler != app_jitk && $compiler != dart2js && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $runtime != none ]
unsorted/types_test: RuntimeError
@@ -29,8 +32,5 @@
[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp && !$strong ]
unsorted/invocation_errors_test/00: MissingCompileTimeError # This test has been tuned for dart 2.
-[ $runtime == dart_precompiled && $minified ]
-unsorted/symbol_literal_test: Skip # Expects unobfuscated Symbol.toString.
-
[ !$preview_dart_2 && ($runtime == dart_precompiled || $runtime == vm) ]
*: SkipByDesign # Deprecating all Dart1 modes of execution
diff --git a/tests/language_2/cyclic_type_test.dart b/tests/language_2/cyclic_type_test.dart
index ada6b6e..3031f62 100644
--- a/tests/language_2/cyclic_type_test.dart
+++ b/tests/language_2/cyclic_type_test.dart
@@ -6,25 +6,33 @@
import "package:expect/expect.dart";
+@pragma("vm:entry-point") // Prevent obfuscation
class Base<T> {
get t => T;
}
// Derived<T> is contractive.
+@pragma("vm:entry-point") // Prevent obfuscation
class Derived<T> extends Base<Derived<T>> {} // //# 00: ok
// Derived<T> is contractive.
+@pragma("vm:entry-point") // Prevent obfuscation
class Derived<T> extends Base<Derived<Derived<int>>> {} // //# 01: ok
// Derived<T> is non-contractive.
+@pragma("vm:entry-point") // Prevent obfuscation
class Derived<T> extends Base<Derived<Derived<T>>> {} // //# 02: ok
// Derived1<U> and Derived2<V> are contractive.
+@pragma("vm:entry-point") // Prevent obfuscation
class Derived1<U> extends Base<Derived2<U>> {} // //# 03: ok
+@pragma("vm:entry-point") // Prevent obfuscation
class Derived2<V> extends Base<Derived1<V>> {} // //# 03: ok
// Derived1<U> and Derived2<V> are non-contractive.
+@pragma("vm:entry-point") // Prevent obfuscation
class Derived1<U> extends Base<Derived2<U>> {} // //# 04: ok
+@pragma("vm:entry-point") // Prevent obfuscation
class Derived2<V> extends Base<Derived1<Derived2<V>>> {} // //# 04: ok
main() {
diff --git a/tests/language_2/f_bounded_quantification5_test.dart b/tests/language_2/f_bounded_quantification5_test.dart
index e496ff9..412cc95 100644
--- a/tests/language_2/f_bounded_quantification5_test.dart
+++ b/tests/language_2/f_bounded_quantification5_test.dart
@@ -6,8 +6,10 @@
import "package:expect/expect.dart";
+@pragma("vm:entry-point")
class A<T extends B<dynamic>> {}
+@pragma("vm:entry-point")
class B<T extends Object> {}
main() {
diff --git a/tests/language_2/full_stacktrace1_test.dart b/tests/language_2/full_stacktrace1_test.dart
index 65c89be..42963f2 100644
--- a/tests/language_2/full_stacktrace1_test.dart
+++ b/tests/language_2/full_stacktrace1_test.dart
@@ -4,14 +4,17 @@
import "package:expect/expect.dart";
+@pragma("vm:entry-point") // Prevents obfuscation
void func1() {
throw new Exception("Test full stacktrace");
}
+@pragma("vm:entry-point") // Prevents obfuscation
void func2() {
func1();
}
+@pragma("vm:entry-point") // Prevents obfuscation
void func3() {
try {
func2();
@@ -27,16 +30,19 @@
}
}
+@pragma("vm:entry-point") // Prevents obfuscation
int func4() {
func3();
return 1;
}
+@pragma("vm:entry-point") // Prevents obfuscation
int func5() {
func4();
return 1;
}
+@pragma("vm:entry-point") // Prevents obfuscation
int func6() {
func5();
return 1;
diff --git a/tests/language_2/full_stacktrace2_test.dart b/tests/language_2/full_stacktrace2_test.dart
index 8b7dfb2..fc15d54 100644
--- a/tests/language_2/full_stacktrace2_test.dart
+++ b/tests/language_2/full_stacktrace2_test.dart
@@ -4,14 +4,17 @@
import "package:expect/expect.dart";
+@pragma("vm:entry-point") // Prevent obfuscation.
void func1() {
throw new Exception("Test full stacktrace");
}
+@pragma("vm:entry-point") // Prevent obfuscation.
void func2() {
func1();
}
+@pragma("vm:entry-point") // Prevent obfuscation.
void func3() {
try {
func2();
@@ -30,11 +33,13 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation.
int func4() {
func3();
return 1;
}
+@pragma("vm:entry-point") // Prevent obfuscation.
int func5() {
try {
func4();
@@ -52,11 +57,13 @@
return 1;
}
+@pragma("vm:entry-point") // Prevent obfuscation.
int func6() {
func5();
return 1;
}
+@pragma("vm:entry-point") // Prevent obfuscation.
int func7() {
func6();
return 1;
diff --git a/tests/language_2/full_stacktrace3_test.dart b/tests/language_2/full_stacktrace3_test.dart
index 2475f37..f6b28a3 100644
--- a/tests/language_2/full_stacktrace3_test.dart
+++ b/tests/language_2/full_stacktrace3_test.dart
@@ -4,14 +4,17 @@
import "package:expect/expect.dart";
+@pragma("vm:entry-point") // Prevent obfuscation
void func1() {
throw new Exception("Test full stacktrace");
}
+@pragma("vm:entry-point") // Prevent obfuscation
void func2() {
func1();
}
+@pragma("vm:entry-point") // Prevent obfuscation
void func3() {
try {
func2();
@@ -29,11 +32,13 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
int func4() {
func3();
return 1;
}
+@pragma("vm:entry-point") // Prevent obfuscation
int func5() {
try {
func4();
@@ -51,11 +56,13 @@
return 1;
}
+@pragma("vm:entry-point") // Prevent obfuscation
int func6() {
func5();
return 1;
}
+@pragma("vm:entry-point") // Prevent obfuscation
int func7() {
func6();
return 1;
diff --git a/tests/language_2/generic_function_dcall_test.dart b/tests/language_2/generic_function_dcall_test.dart
index e05fcc2..6de579f 100644
--- a/tests/language_2/generic_function_dcall_test.dart
+++ b/tests/language_2/generic_function_dcall_test.dart
@@ -53,5 +53,5 @@
testCallsToGenericFn();
testGenericFnAsArg();
testGenericFnAsGenericFnArg();
- testGenericFnTypeToString();
+ testGenericFnTypeToString(); //# 01: ok
}
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 4fd51d6..a99dd0f 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -251,7 +251,7 @@
full_stacktrace2_test: RuntimeError # Issue 12698
full_stacktrace3_test: RuntimeError # Issue 12698
generalized_void_syntax_test: CompileTimeError # Issue #30176.
-generic_function_dcall_test: Crash # Unsupported operation: Unsupported type parameter type node T.
+generic_function_dcall_test/01: Crash # Unsupported operation: Unsupported type parameter type node T.
generic_tearoff_test: Crash # Unsupported operation: Unsupported type parameter type node T.
generic_typedef_test: RuntimeError
identical_closure2_test: RuntimeError # non JS number semantics
@@ -505,7 +505,7 @@
full_stacktrace3_test: RuntimeError # Issue 12698
function_subtype_inline2_test: RuntimeError
generic_function_bounds_test: RuntimeError
-generic_function_dcall_test: RuntimeError
+generic_function_dcall_test/01: RuntimeError
generic_instanceof2_test: RuntimeError
generic_is_check_test: RuntimeError
generic_methods_bounds_test/02: MissingRuntimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 75d0043..9bb75b0 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -238,6 +238,26 @@
vm/debug_break_enabled_vm_test/none: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
vm/regress_27201_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
+[ $builder_tag == obfuscated && $compiler == dartkp ]
+generic_function_dcall_test/01: SkipByDesign # Prints type names
+invocation_mirror_test: RuntimeError # Issue 34911
+many_named_arguments_test: SkipByDesign # Checks names of arguments
+mixin_generic_test: SkipByDesign # Prints type names
+mixin_mixin3_test: SkipByDesign # Prints type names
+mixin_mixin5_test: SkipByDesign # Prints type names
+mixin_mixin6_test: SkipByDesign # Prints type names
+mixin_mixin_bound2_test: SkipByDesign # Prints type names
+no_such_method_native_test: RuntimeError # Compares symbol #foobar with string "foobar" in noSuchMethod
+recursive_generic_test: RuntimeError # Compares a (dynamic) toString call to 'C<D>'
+symbol_literal_test/02: SkipByDesign # We don't obfuscate const Symbol constructor
+tearoff_dynamic_test: RuntimeError # Compares call to "foo" (noSuchMethod) with string "foo"
+type_literal_test: SkipByDesign # Uses lots of strings with type names in them
+vm/bool_check_stack_traces_test: SkipByDesign # Looks for filenames in stacktrace output
+vm/no_such_args_error_message_vm_test: SkipByDesign # Looks for function name in error message
+vm/no_such_method_error_message_callable_vm_test: SkipByDesign # Expects unobfuscated method names
+vm/no_such_method_error_message_vm_test: SkipByDesign # Looks for unobfuscated name in error message
+vm/regress_28325_test: SkipByDesign # Looks for filename in stack trace
+
[ $compiler == app_jitk && $mode == product ]
vm/causal_async_exception_stack2_test: RuntimeError
vm/causal_async_exception_stack_test: RuntimeError
@@ -630,11 +650,6 @@
[ $compiler == dartkp && $system == windows ]
disassemble_test: Pass, Slow
-[ $compiler == dartkp && $minified ]
-no_such_method_native_test: RuntimeError # Compares symbol #foobar with string "foobar" in noSuchMethod
-recursive_generic_test: RuntimeError # Compares a (dynamic) toString call to 'C<D>'
-tearoff_dynamic_test: RuntimeError # Compares call to "foo" (noSuchMethod) with string "foo"
-
[ $compiler == fasta && $strong ]
compile_time_constant_static4_test/02: MissingCompileTimeError
compile_time_constant_static4_test/03: MissingCompileTimeError
diff --git a/tests/language_2/mixin_mixin_type_arguments_test.dart b/tests/language_2/mixin_mixin_type_arguments_test.dart
index 55d796f..08a3d9c 100644
--- a/tests/language_2/mixin_mixin_type_arguments_test.dart
+++ b/tests/language_2/mixin_mixin_type_arguments_test.dart
@@ -4,34 +4,45 @@
import 'package:expect/expect.dart' show Expect;
+@pragma("vm:entry-point") // Prevent obfuscation
class A {}
+@pragma("vm:entry-point") // Prevent obfuscation
class B {}
+@pragma("vm:entry-point") // Prevent obfuscation
class C {}
+@pragma("vm:entry-point") // Prevent obfuscation
class D {}
+@pragma("vm:entry-point") // Prevent obfuscation
class E {}
+@pragma("vm:entry-point") // Prevent obfuscation
class F {}
+@pragma("vm:entry-point") // Prevent obfuscation
class M1<Tm1> {
m1() => "M1<$Tm1>";
}
+@pragma("vm:entry-point") // Prevent obfuscation
class M2<Tm2> {
m2() => "M2<$Tm2>";
}
+@pragma("vm:entry-point") // Prevent obfuscation
class M3<Tm3> {
m3() => "M3<$Tm3>";
}
+@pragma("vm:entry-point") // Prevent obfuscation
class M4<Tm4> {
m4() => "M4<$Tm4>";
}
+@pragma("vm:entry-point") // Prevent obfuscation
class M5<Tm5> {
m5() => "M5<$Tm5>";
}
diff --git a/tests/language_2/mock_writable_final_field_test.dart b/tests/language_2/mock_writable_final_field_test.dart
index 6105a58..88919a9 100644
--- a/tests/language_2/mock_writable_final_field_test.dart
+++ b/tests/language_2/mock_writable_final_field_test.dart
@@ -9,12 +9,14 @@
class Mock {
noSuchMethod(Invocation i) {
var expected = i.isGetter ? #x : const Symbol("x=");
- Expect.equals(expected, i.memberName);
+ Expect.equals(expected.toString(), i.memberName.toString());
values.add(i.positionalArguments[0]);
}
}
class Foo {
+ // Prevent obfuscation of 'x'.
+ @pragma("vm:entry-point")
int x;
}
diff --git a/tests/language_2/mock_writable_final_private_field_test.dart b/tests/language_2/mock_writable_final_private_field_test.dart
index afb337c..c592878 100644
--- a/tests/language_2/mock_writable_final_private_field_test.dart
+++ b/tests/language_2/mock_writable_final_private_field_test.dart
@@ -16,6 +16,8 @@
}
class Foo {
+ // Prevent obfuscation of '_x'.
+ @pragma("vm:entry-point")
int _x;
}
diff --git a/tests/language_2/no_such_method_dispatcher_test.dart b/tests/language_2/no_such_method_dispatcher_test.dart
index 0228b65..d0042dc 100644
--- a/tests/language_2/no_such_method_dispatcher_test.dart
+++ b/tests/language_2/no_such_method_dispatcher_test.dart
@@ -27,7 +27,7 @@
Expect.equals(posArgs[i], m.positionalArguments[i]);
}
for (var k in namedArgs.keys) {
- Expect.equals(namedArgs[k], m.namedArguments[new Symbol(k)]);
+ Expect.equals(namedArgs[k], m.namedArguments[k]);
}
return 123;
}
@@ -55,7 +55,7 @@
}
// Test named and positional arguments.
- var c = new C(1, 2, [100], {"n1": 101, "n2": 102}) as dynamic;
+ var c = new C(1, 2, [100], {#n1: 101, #n2: 102}) as dynamic;
for (var i = 0; i < 20; ++i) {
Expect.equals(123, c.bar(100, n1: 101, n2: 102));
Expect.equals(123, c.bar(100, n2: 102, n1: 101));
diff --git a/tests/language_2/regress_21795_test.dart b/tests/language_2/regress_21795_test.dart
index c264ef3..2ca18a3 100644
--- a/tests/language_2/regress_21795_test.dart
+++ b/tests/language_2/regress_21795_test.dart
@@ -4,6 +4,7 @@
// Regression test for issue 21795.
+@pragma("vm:entry-point") // Prevent obfuscation
foo(t) {
try {
if (t == 123) throw 42;
diff --git a/tests/language_2/stack_trace_test.dart b/tests/language_2/stack_trace_test.dart
index 1cf429e..5e4d7c6 100644
--- a/tests/language_2/stack_trace_test.dart
+++ b/tests/language_2/stack_trace_test.dart
@@ -87,6 +87,7 @@
class RethrowStacktraceTest {
var config = 0;
+ @pragma("vm:entry-point") // Prevent obfuscation
issue12940() {
throw "Progy";
}
diff --git a/tests/language_2/stacktrace_rethrow_error_test.dart b/tests/language_2/stacktrace_rethrow_error_test.dart
index ef3116a..4cdbaa6 100644
--- a/tests/language_2/stacktrace_rethrow_error_test.dart
+++ b/tests/language_2/stacktrace_rethrow_error_test.dart
@@ -8,6 +8,7 @@
// == Rethrow, skipping through typed handlers. ==
+@pragma("vm:entry-point") // Prevent obfuscation
aa1() {
try {
bb1();
@@ -21,8 +22,10 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
bb1() => cc1();
+@pragma("vm:entry-point") // Prevent obfuscation
cc1() {
try {
dd1();
@@ -33,8 +36,10 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
dd1() => ee1();
+@pragma("vm:entry-point") // Prevent obfuscation
ee1() {
try {
ff1();
@@ -43,12 +48,15 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
ff1() => gg1();
+@pragma("vm:entry-point") // Prevent obfuscation
gg1() => throw new SubclassOfError();
// == Rethrow, rethrow again in typed handler. ==
+@pragma("vm:entry-point") // Prevent obfuscation
aa2() {
try {
bb2();
@@ -62,8 +70,10 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
bb2() => cc2();
+@pragma("vm:entry-point") // Prevent obfuscation
cc2() {
try {
dd2();
@@ -74,8 +84,10 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
dd2() => ee2();
+@pragma("vm:entry-point") // Prevent obfuscation
ee2() {
try {
ff2();
@@ -84,12 +96,15 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
ff2() => gg2();
+@pragma("vm:entry-point") // Prevent obfuscation
gg2() => throw new SubclassOfError();
// == Rethrow, with intervening catch without a trace parameter.
+@pragma("vm:entry-point") // Prevent obfuscation
aa3() {
try {
bb3();
@@ -103,8 +118,10 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
bb3() => cc3();
+@pragma("vm:entry-point") // Prevent obfuscation
cc3() {
try {
dd3();
@@ -113,8 +130,10 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
dd3() => ee3();
+@pragma("vm:entry-point") // Prevent obfuscation
ee3() {
try {
ff3();
@@ -123,8 +142,10 @@
}
}
+@pragma("vm:entry-point") // Prevent obfuscation
ff3() => gg3();
+@pragma("vm:entry-point") // Prevent obfuscation
gg3() => throw new SubclassOfError();
expectTrace(functionNames, stacktrace) {
diff --git a/tests/language_2/stacktrace_rethrow_nonerror_test.dart b/tests/language_2/stacktrace_rethrow_nonerror_test.dart
index 57c8a15..304d591 100644
--- a/tests/language_2/stacktrace_rethrow_nonerror_test.dart
+++ b/tests/language_2/stacktrace_rethrow_nonerror_test.dart
@@ -8,6 +8,7 @@
// == Rethrow, skipping through typed handlers. ==
+@pragma("vm:entry-point")
aa1() {
try {
bb1();
@@ -17,8 +18,10 @@
}
}
+@pragma("vm:entry-point")
bb1() => cc1();
+@pragma("vm:entry-point")
cc1() {
try {
dd1();
@@ -29,8 +32,10 @@
}
}
+@pragma("vm:entry-point")
dd1() => ee1();
+@pragma("vm:entry-point")
ee1() {
try {
ff1();
@@ -39,12 +44,15 @@
}
}
+@pragma("vm:entry-point")
ff1() => gg1();
+@pragma("vm:entry-point")
gg1() => throw new NotASubclassOfError();
// == Rethrow, rethrow again in typed handler. ==
+@pragma("vm:entry-point")
aa2() {
try {
bb2();
@@ -54,8 +62,10 @@
}
}
+@pragma("vm:entry-point")
bb2() => cc2();
+@pragma("vm:entry-point")
cc2() {
try {
dd2();
@@ -66,8 +76,10 @@
}
}
+@pragma("vm:entry-point")
dd2() => ee2();
+@pragma("vm:entry-point")
ee2() {
try {
ff2();
@@ -76,12 +88,15 @@
}
}
+@pragma("vm:entry-point")
ff2() => gg2();
+@pragma("vm:entry-point")
gg2() => throw new NotASubclassOfError();
// == Rethrow, with intervening catch without a trace parameter.
+@pragma("vm:entry-point")
aa3() {
try {
bb3();
@@ -91,8 +106,10 @@
}
}
+@pragma("vm:entry-point")
bb3() => cc3();
+@pragma("vm:entry-point")
cc3() {
try {
dd3();
@@ -101,8 +118,10 @@
}
}
+@pragma("vm:entry-point")
dd3() => ee3();
+@pragma("vm:entry-point")
ee3() {
try {
ff3();
@@ -111,8 +130,10 @@
}
}
+@pragma("vm:entry-point")
ff3() => gg3();
+@pragma("vm:entry-point")
gg3() => throw new NotASubclassOfError();
expectTrace(functionNames, stacktrace) {
diff --git a/tests/language_2/symbol_literal_test.dart b/tests/language_2/symbol_literal_test.dart
index f111da8..aa89fef 100644
--- a/tests/language_2/symbol_literal_test.dart
+++ b/tests/language_2/symbol_literal_test.dart
@@ -24,15 +24,19 @@
}
main() {
- check(const Symbol("a"), #a);
- check(const Symbol("a"), #a);
- check(const Symbol("ab"), #ab);
- check(const Symbol("ab"), #ab);
- check(const Symbol("a.b"), #a.b);
- check(const Symbol("a.b"), #a.b);
- check(const Symbol("=="), #==);
- check(const Symbol("=="), #==);
- check(const Symbol("a.toString"), #a.toString);
+ bool doChecks = false;
+ doChecks = true; //# 02: ok
+ if (doChecks) {
+ check(const Symbol("a"), #a);
+ check(const Symbol("a"), #a);
+ check(const Symbol("ab"), #ab);
+ check(const Symbol("ab"), #ab);
+ check(const Symbol("a.b"), #a.b);
+ check(const Symbol("a.b"), #a.b);
+ check(const Symbol("=="), #==);
+ check(const Symbol("=="), #==);
+ check(const Symbol("a.toString"), #a.toString);
+ }
Expect.equals(1, testSwitch(#abc));
diff --git a/tests/language_2/vm/regress_flutter_23879_test.dart b/tests/language_2/vm/regress_flutter_23879_test.dart
new file mode 100644
index 0000000..102493e
--- /dev/null
+++ b/tests/language_2/vm/regress_flutter_23879_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Bug in unboxed int spilling (https://github.com/flutter/flutter/issues/23879).
+//
+// VMOptions=--deterministic
+
+import "package:expect/expect.dart";
+
+List<int> list = new List<int>(10);
+
+List<int> expected_values = [null, 152, 168, 184, 200, 216, 232, 248, 264, 280];
+
+int count = 0;
+
+bool getNext() {
+ return ++count <= 9;
+}
+
+int foo() {
+ int a = 1;
+ int b = 2;
+ int c = 3;
+ int d = 4;
+ int e = 5;
+ int f = 6;
+ int g = 7;
+ int h = 8;
+ int i = 9;
+ int j = 10;
+ int k = 11;
+ int l = 12;
+ int m = 13;
+ int n = 14;
+ int o = 15;
+ int p = 16;
+ count = 0;
+ int componentIndex = 1;
+ while (getNext()) {
+ // Make spilling likely.
+ a++;
+ b++;
+ c++;
+ d++;
+ e++;
+ f++;
+ g++;
+ h++;
+ i++;
+ j++;
+ k++;
+ l++;
+ m++;
+ n++;
+ o++;
+ p++;
+ list[componentIndex] =
+ a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p;
+ componentIndex++;
+ }
+ return componentIndex;
+}
+
+void main() {
+ int x = foo();
+ Expect.equals(10, x);
+ Expect.equals(10, count);
+ for (int i = 0; i < 10; i++) {
+ Expect.equals(expected_values[i], list[i]);
+ }
+}
diff --git a/tests/language_2/vm/tree_shake_type_args_in_constant_test.dart b/tests/language_2/vm/tree_shake_type_args_in_constant_test.dart
index 09b9197..b1d9f88 100644
--- a/tests/language_2/vm/tree_shake_type_args_in_constant_test.dart
+++ b/tests/language_2/vm/tree_shake_type_args_in_constant_test.dart
@@ -7,6 +7,7 @@
import "package:expect/expect.dart";
+@pragma("vm:entry-point") // Prevent obfuscation
abstract class A {}
class B<T> {
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index fe15c91..081f26e 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -57,6 +57,9 @@
[ $arch == x64 && $mode == debug && $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439.
+[ $builder_tag == obfuscated && $compiler == dartkp ]
+collection/list_test: RuntimeError # Issue 34911
+
[ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
isolate/unresolved_ports_test: CompileTimeError, Pass, Timeout # Fails to compile on opt counter builder (#31838)
mirrors/invocation_fuzz_test/emptyarray: Pass, Crash, RuntimeError # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
diff --git a/tools/VERSION b/tools/VERSION
index fe36fde..5361581 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 1
PATCH 0
PRERELEASE 9
-PRERELEASE_PATCH 3
+PRERELEASE_PATCH 4