Version 2.15.0-39.0.dev
Merge commit '3238d433faa3e31df2c3a8b671be1e225526e7b0' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index e70c308..b347d13 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -265,6 +265,12 @@
"languageVersion": "2.12"
},
{
+ "name": "devtools_server",
+ "rootUri": "../third_party/devtools/devtools_server",
+ "packageUri": "lib/",
+ "languageVersion": "2.12"
+ },
+ {
"name": "devtools_shared",
"rootUri": "../third_party/devtools/devtools_shared",
"packageUri": "lib/",
diff --git a/.packages b/.packages
index b22e6a2..d5fdbc9 100644
--- a/.packages
+++ b/.packages
@@ -39,6 +39,7 @@
dartdoc:third_party/pkg/dartdoc/lib
dds:pkg/dds/lib
dev_compiler:pkg/dev_compiler/lib
+devtools_server:third_party/devtools/devtools_server/lib
devtools_shared:third_party/devtools/devtools_shared/lib
diagnostic:pkg/diagnostic/lib
expect:pkg/expect/lib
diff --git a/DEPS b/DEPS
index 402eae5..1e12e6a 100644
--- a/DEPS
+++ b/DEPS
@@ -106,7 +106,7 @@
"dart_style_rev": "14d9b6fd58cc4744676c12be3cc5eee2a779db82",
"dartdoc_rev" : "5f39ec674d81f5c199151d823fa4ecd01fc59eb2",
- "devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
+ "devtools_rev" : "2b47d9ed486479153ca2fd038000950674ed1beb",
"jsshell_tag": "version:88.0",
"ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb",
"fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
index 291ad67..7deaa33 100644
--- a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -33,9 +33,9 @@
'pub',
];
-Future<void> reportArtifactSize(String path, String name) async {
+void reportFileSize(String path, String name) {
try {
- final size = await File(path).length();
+ final size = File(path).lengthSync();
print('SDKArtifactSizes.$name(CodeSize): $size');
} on FileSystemException {
// Report dummy data for artifacts that don't exist for specific platforms.
@@ -43,43 +43,43 @@
}
}
-Future<void> main() async {
+void reportDirectorySize(String path, String name) async {
+ final dir = Directory(path);
+
+ try {
+ final size = dir
+ .listSync(recursive: true, followLinks: false)
+ .whereType<File>()
+ .map((file) => file.lengthSync())
+ .fold<int>(0, (a, b) => a + b);
+ print('SDKArtifactSizes.$name(CodeSize): $size');
+ } on FileSystemException {
+ // Report dummy data on errors.
+ print('SDKArtifactSizes.$name(CodeSize): 0');
+ }
+}
+
+void main() {
final topDirIndex =
Platform.resolvedExecutable.lastIndexOf(Platform.pathSeparator);
final rootDir = Platform.resolvedExecutable.substring(0, topDirIndex);
for (final executable in executables) {
final executablePath = '$rootDir/dart-sdk/bin/$executable';
- await reportArtifactSize(executablePath, executable);
+ reportFileSize(executablePath, executable);
}
for (final lib in libs) {
final libPath = '$rootDir/dart-sdk/lib/_internal/$lib';
- await reportArtifactSize(libPath, lib);
+ reportFileSize(libPath, lib);
}
for (final snapshot in snapshots) {
final snapshotPath =
'$rootDir/dart-sdk/bin/snapshots/$snapshot.dart.snapshot';
- await reportArtifactSize(snapshotPath, snapshot);
+ reportFileSize(snapshotPath, snapshot);
}
- // Measure the (compressed) sdk size.
- final tempDir = Directory.systemTemp.createTempSync('dartdev');
- final sdkArchive = compress(Directory('$rootDir/dart-sdk'), tempDir);
- await reportArtifactSize(sdkArchive?.path ?? '', 'sdk');
- tempDir.deleteSync(recursive: true);
-}
-
-File? compress(Directory sourceDir, Directory targetDir) {
- final outFile = File('${targetDir.path}/sdk.zip');
-
- if (Platform.isMacOS || Platform.isLinux) {
- Process.runSync(
- 'zip', ['-r', outFile.absolute.path, sourceDir.absolute.path]);
- } else {
- return null;
- }
-
- return outFile;
+ // Measure the sdk size.
+ reportDirectorySize('$rootDir/dart-sdk', 'sdk');
}
diff --git a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
index f5b7f05..71e5a48 100644
--- a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
@@ -35,9 +35,9 @@
'pub',
];
-Future<void> reportArtifactSize(String path, String name) async {
+void reportFileSize(String path, String name) {
try {
- final size = await File(path).length();
+ final size = File(path).lengthSync();
print('SDKArtifactSizes.$name(CodeSize): $size');
} on FileSystemException {
// Report dummy data for artifacts that don't exist for specific platforms.
@@ -45,43 +45,43 @@
}
}
-Future<void> main() async {
+void reportDirectorySize(String path, String name) async {
+ final dir = Directory(path);
+
+ try {
+ final size = dir
+ .listSync(recursive: true, followLinks: false)
+ .whereType<File>()
+ .map((file) => file.lengthSync())
+ .fold<int>(0, (a, b) => a + b);
+ print('SDKArtifactSizes.$name(CodeSize): $size');
+ } on FileSystemException {
+ // Report dummy data on errors.
+ print('SDKArtifactSizes.$name(CodeSize): 0');
+ }
+}
+
+void main() {
final topDirIndex =
Platform.resolvedExecutable.lastIndexOf(Platform.pathSeparator);
final rootDir = Platform.resolvedExecutable.substring(0, topDirIndex);
for (final executable in executables) {
final executablePath = '$rootDir/dart-sdk/bin/$executable';
- await reportArtifactSize(executablePath, executable);
+ reportFileSize(executablePath, executable);
}
for (final lib in libs) {
final libPath = '$rootDir/dart-sdk/lib/_internal/$lib';
- await reportArtifactSize(libPath, lib);
+ reportFileSize(libPath, lib);
}
for (final snapshot in snapshots) {
final snapshotPath =
'$rootDir/dart-sdk/bin/snapshots/$snapshot.dart.snapshot';
- await reportArtifactSize(snapshotPath, snapshot);
+ reportFileSize(snapshotPath, snapshot);
}
- // Measure the (compressed) sdk size.
- final tempDir = Directory.systemTemp.createTempSync('dartdev');
- final sdkArchive = compress(Directory('$rootDir/dart-sdk'), tempDir);
- await reportArtifactSize(sdkArchive?.path ?? '', 'sdk');
- tempDir.deleteSync(recursive: true);
-}
-
-File compress(Directory sourceDir, Directory targetDir) {
- final outFile = File('${targetDir.path}/sdk.zip');
-
- if (Platform.isMacOS || Platform.isLinux) {
- Process.runSync(
- 'zip', ['-r', outFile.absolute.path, sourceDir.absolute.path]);
- } else {
- return null;
- }
-
- return outFile;
+ // Measure the sdk size.
+ reportDirectorySize('$rootDir/dart-sdk', 'sdk');
}
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 1b7a17f..76b327e 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -405,6 +405,7 @@
CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT,
CompileTimeErrorCode.SWITCH_CASE_COMPLETES_NORMALLY,
CompileTimeErrorCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
+ CompileTimeErrorCode.TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS,
CompileTimeErrorCode.THROW_OF_INVALID_TYPE,
CompileTimeErrorCode.TOP_LEVEL_CYCLE,
CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
diff --git a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
index ac1868d..35706f4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
@@ -25,6 +25,17 @@
HintCode.SDK_VERSION_CONSTRUCTOR_TEAROFFS, node, []);
}
node.constructorName.accept(_resolver);
+ var element = node.constructorName.staticElement;
+ if (element != null &&
+ !element.isFactory &&
+ element.enclosingElement.isAbstract) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode
+ .TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS,
+ node,
+ [],
+ );
+ }
_inferArgumentTypes(node);
}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index cadf3c7..f48af7c 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -12550,6 +12550,17 @@
hasPublishedDocs: true);
/**
+ * No parameters.
+ */
+ static const CompileTimeErrorCode
+ TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS =
+ CompileTimeErrorCode(
+ 'TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS',
+ "A generative constructor of an abstract class can't be torn off",
+ correction: "Try tearing off a constructor of a concrete class, or a "
+ "non-generative constructor.");
+
+ /**
* Parameters:
* 0: the type that can't be thrown
*/
diff --git a/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart
index 21b86f7..5d29577 100644
--- a/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart
@@ -389,6 +389,85 @@
@reflectiveTest
class ConstructorReferenceResolutionTest extends PubPackageResolutionTest {
+ test_abstractClass_factory() async {
+ await assertNoErrorsInCode('''
+abstract class A {
+ factory A() => A2();
+}
+
+class A2 implements A {}
+
+foo() {
+ A.new;
+}
+''');
+
+ var classElement = findElement.class_('A');
+ assertConstructorReference(
+ findNode.constructorReference('A.new;'),
+ classElement.unnamedConstructor,
+ classElement,
+ 'A Function()',
+ expectedTypeNameType: 'A',
+ );
+ }
+
+ test_abstractClass_generative() async {
+ await assertErrorsInCode('''
+abstract class A {
+ A();
+}
+
+foo() {
+ A.new;
+}
+''', [
+ error(
+ CompileTimeErrorCode
+ .TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS,
+ 39,
+ 5),
+ ]);
+
+ var classElement = findElement.class_('A');
+ assertConstructorReference(
+ findNode.constructorReference('A.new;'),
+ classElement.unnamedConstructor,
+ classElement,
+ 'A Function()',
+ expectedTypeNameType: 'A',
+ );
+ }
+
+ test_abstractClass_redirecting() async {
+ await assertErrorsInCode('''
+abstract class A {
+ A(): this.two();
+
+ A.two();
+}
+
+foo() {
+ A.new;
+}
+''', [
+ error(
+ CompileTimeErrorCode
+ .TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS,
+ 63,
+ 5),
+ ]);
+
+ var classElement = findElement.class_('A');
+ assertConstructorReference(
+ findNode.constructorReference('A.new;'),
+ classElement.unnamedConstructor,
+ classElement,
+ 'A Function()',
+ expectedTypeNameType: 'A',
+ );
+ }
+
test_class_generic_inferFromContext_badTypeArgument() async {
await assertErrorsInCode('''
class A<T extends num> {
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 4947dab..c39a339 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -24,8 +24,8 @@
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_explicitReceiver_unknown_multipleProperties() async {
@@ -37,8 +37,8 @@
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_extensionGetter_extensionOverride() async {
@@ -57,8 +57,8 @@
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 67, 8),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(findNode.functionReference('foo<int>;'),
+ findElement.getter('foo'), 'dynamic');
}
test_extensionMethod() async {
@@ -173,8 +173,8 @@
error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 51, 3),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_extensionMethod_fromClassDeclaration() async {
@@ -210,8 +210,8 @@
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 66, 3),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'void Function(int)');
+ assertFunctionReference(findNode.functionReference('foo<int>;'),
+ findElement.getter('foo'), 'void Function(int)');
}
test_instanceGetter_explicitReceiver() async {
@@ -228,8 +228,8 @@
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 58, 5),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'void Function(int)');
+ assertFunctionReference(findNode.functionReference('foo<int>;'),
+ findElement.getter('foo'), 'void Function(int)');
}
test_instanceMethod() async {
@@ -279,8 +279,8 @@
}
''');
- var reference = findNode.functionReference('(a ?? b).foo<int>;');
- assertType(reference, 'void Function(int)');
+ assertFunctionReference(findNode.functionReference('(a ?? b).foo<int>;'),
+ findElement.method('foo'), 'void Function(int)');
}
test_instanceMethod_explicitReceiver_super() async {
@@ -311,8 +311,8 @@
error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 30, 3),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_instanceMethod_explicitReceiver_super_noSuper() async {
@@ -324,8 +324,8 @@
error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 10, 5),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_instanceMethod_explicitReceiver_this() async {
@@ -403,8 +403,8 @@
assertImportPrefix(
findNode.simple('prefix.'), findElement.prefix('prefix'));
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_instanceMethod_explicitReceiver_typeParameter() async {
@@ -416,8 +416,8 @@
error(CompileTimeErrorCode.UNDEFINED_GETTER, 15, 3),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_instanceMethod_explicitReceiver_variable() async {
@@ -481,8 +481,8 @@
error(CompileTimeErrorCode.UNDEFINED_METHOD, 24, 3),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_localFunction() async {
@@ -560,6 +560,7 @@
var reference = findNode.functionReference('(1 == 2 ? foo : bar)<int>;');
assertType(reference, 'void Function(int)');
+ // A ParenthesizedExpression has no element to assert on.
}
test_otherExpression_wrongNumberOfTypeArguments() async {
@@ -580,6 +581,7 @@
var reference =
findNode.functionReference('(1 == 2 ? foo : bar)<int, String>;');
assertType(reference, 'void Function(dynamic)');
+ // A ParenthesizedExpression has no element to assert on.
}
test_receiverIsDynamic() async {
@@ -592,8 +594,8 @@
19, 5),
]);
- var reference = findNode.functionReference('a.foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('a.foo<int>;'), null, 'dynamic');
}
test_staticMethod() async {
@@ -624,9 +626,8 @@
''');
assertClassRef(findNode.simple('A.'), findElement.class_('A'));
- var reference = findNode.functionReference('foo<int>;');
- assertElement(reference, findElement.method('foo'));
- assertType(reference, 'void Function(int)');
+ assertFunctionReference(findNode.functionReference('foo<int>;'),
+ findElement.method('foo'), 'void Function(int)');
}
test_staticMethod_explicitReceiver_importPrefix() async {
@@ -800,8 +801,8 @@
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 6),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_topLevelVariable_prefix_unknownIdentifier() async {
@@ -818,8 +819,8 @@
assertImportPrefix(
findNode.simple('prefix.'), findElement.prefix('prefix'));
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_typeAlias_function_unknownProperty() async {
@@ -831,8 +832,8 @@
error(CompileTimeErrorCode.UNDEFINED_GETTER, 42, 3),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_typeAlias_typeVariable_unknownProperty() async {
@@ -844,8 +845,8 @@
error(CompileTimeErrorCode.UNDEFINED_GETTER, 29, 3),
]);
- var reference = findNode.functionReference('foo<int>;');
- assertType(reference, 'dynamic');
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_unknownIdentifier() async {
@@ -856,6 +857,9 @@
''', [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 15, 3),
]);
+
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_unknownIdentifier_explicitReceiver() async {
@@ -870,6 +874,9 @@
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 41, 3),
]);
+
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
test_unknownIdentifier_importPrefix() async {
@@ -883,5 +890,8 @@
''', [
error(CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME, 40, 3),
]);
+
+ assertFunctionReference(
+ findNode.functionReference('foo<int>;'), null, 'dynamic');
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 514abe7..45fd9a6 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -364,7 +364,7 @@
}
void assertFunctionReference(
- FunctionReference node, Element expectedElement, String expectedType) {
+ FunctionReference node, Element? expectedElement, String expectedType) {
assertElement(node, expectedElement);
assertType(node, expectedType);
}
diff --git a/pkg/analyzer/test/src/diagnostics/tearoff_of_generative_constructor_of_abstract_class_test.dart b/pkg/analyzer/test/src/diagnostics/tearoff_of_generative_constructor_of_abstract_class_test.dart
new file mode 100644
index 0000000..39265e5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/tearoff_of_generative_constructor_of_abstract_class_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2021, 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.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(TearoffOfGenerativeConstructorOfAbstractClassTest);
+ });
+}
+
+@reflectiveTest
+class TearoffOfGenerativeConstructorOfAbstractClassTest
+ extends PubPackageResolutionTest {
+ test_abstractClass_factoryConstructor() async {
+ await assertNoErrorsInCode('''
+abstract class A {
+ factory A() => B();
+}
+
+class B implements A {}
+
+void foo() {
+ A.new;
+}
+''');
+ }
+
+ test_abstractClass_factoryConstructor_viaEquals() async {
+ await assertNoErrorsInCode('''
+abstract class A {
+ factory A() = B;
+}
+
+class B implements A {}
+
+void foo() {
+ A.new;
+}
+''');
+ }
+
+ test_abstractClass_generativeConstructor() async {
+ await assertErrorsInCode('''
+abstract class A {
+ A();
+}
+
+void foo() {
+ A.new;
+}
+''', [
+ error(
+ CompileTimeErrorCode
+ .TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS,
+ 44,
+ 5),
+ ]);
+ }
+
+ test_concreteClass_factoryConstructor() async {
+ await assertNoErrorsInCode('''
+class A {
+ factory A() => A.two();
+
+ A.two();
+}
+
+void foo() {
+ A.new;
+}
+''');
+ }
+
+ test_concreteClass_factoryConstructor_viaEquals() async {
+ await assertNoErrorsInCode('''
+class A {
+ factory A() = A.two;
+
+ A.two();
+}
+
+void foo() {
+ A.new;
+}
+''');
+ }
+
+ test_concreteClass_generativeConstructor() async {
+ await assertNoErrorsInCode('''
+class A {
+ A();
+}
+
+void foo() {
+ A.new;
+}
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 176cb48..2d3ff59 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -628,6 +628,8 @@
as switch_case_completes_normally;
import 'switch_expression_not_assignable_test.dart'
as switch_expression_not_assignable;
+import 'tearoff_of_generative_constructor_of_abstract_class_test.dart'
+ as tearoff_of_generative_constructor_of_abstract_class;
import 'throw_of_invalid_type_test.dart' as throw_of_invalid_type;
import 'todo_test.dart' as todo_test;
import 'top_level_cycle_test.dart' as top_level_cycle;
@@ -1129,6 +1131,7 @@
super_initializer_in_object.main();
switch_case_completes_normally.main();
switch_expression_not_assignable.main();
+ tearoff_of_generative_constructor_of_abstract_class.main();
throw_of_invalid_type.main();
todo_test.main();
top_level_cycle.main();
diff --git a/pkg/dartdev/.gitignore b/pkg/dartdev/.gitignore
index 0bd726b..493289d 100644
--- a/pkg/dartdev/.gitignore
+++ b/pkg/dartdev/.gitignore
@@ -4,10 +4,6 @@
.project
.settings/
build/
-pubspec.lock
# Directory created by dartdoc
doc/api/
-
-# Directory created by pub
-.dart_tool/
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 5895deb..fefffae 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -11,6 +11,7 @@
import 'package:cli_util/cli_logging.dart';
import 'package:dart_style/src/cli/format_command.dart';
import 'package:dartdev/src/commands/migrate.dart';
+import 'package:devtools_server/devtools_server.dart';
import 'package:meta/meta.dart';
import 'package:pedantic/pedantic.dart';
import 'package:pub/pub.dart';
@@ -27,6 +28,7 @@
import 'src/core.dart';
import 'src/events.dart';
import 'src/experiments.dart';
+import 'src/sdk.dart';
import 'src/utils.dart';
import 'src/vm_interop_handler.dart';
@@ -101,6 +103,13 @@
addCommand(AnalyzeCommand(verbose: verbose));
addCommand(CreateCommand(verbose: verbose));
addCommand(CompileCommand(verbose: verbose));
+ addCommand(DevToolsCommand(
+ verbose: verbose,
+ // TODO(devoncarew): Un-hide this command after a stabilization period
+ // likely before the next stable release (before Dart 2.15).
+ hidden: !verbose,
+ customDevToolsPath: sdk.devToolsBinaries,
+ ));
addCommand(FixCommand(verbose: verbose));
addCommand(FormatCommand(verbose: verbose));
addCommand(LanguageServerCommand(verbose: verbose));
@@ -116,6 +125,7 @@
@override
String get invocation =>
'dart ${verbose ? '[vm-options] ' : ''}<command|dart-file> [arguments]';
+
@override
String get usageFooter =>
'See https://dart.dev/tools/dart-tool for detailed documentation.';
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index 3887bdf..5f509c2 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -12,11 +12,12 @@
path: ../analysis_server_client
analyzer:
path: ../analyzer
- args: ^1.6.0
- cli_util: '>=0.1.4 <0.3.0'
+ args: any
+ cli_util: any
dart2native:
path: ../dart2native
dart_style: any
+ devtools_server: any
front_end:
path: ../front_end
intl: any
@@ -24,15 +25,15 @@
path: ../meta
nnbd_migration:
path: ../nnbd_migration
- path: ^1.0.0
- pedantic: ^1.9.0
+ path: any
+ pedantic: any
pub: any
telemetry:
path: ../telemetry
- usage: ^3.4.0
+ usage: any
dev_dependencies:
lints: any
pub_semver: any
- test: ^1.0.0
+ test: any
yaml: any
diff --git a/pkg/dartdev/test/commands/devtools_test.dart b/pkg/dartdev/test/commands/devtools_test.dart
new file mode 100644
index 0000000..37bc32e
--- /dev/null
+++ b/pkg/dartdev/test/commands/devtools_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2021, 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.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:test/test.dart';
+
+import '../utils.dart';
+
+void main() {
+ group('devtools', devtools, timeout: longTimeout);
+}
+
+void devtools() {
+ TestProject p;
+
+ tearDown(() => p?.dispose());
+
+ test('--help', () {
+ p = project();
+ var result = p.runSync(['devtools', '--help']);
+ expect(result.exitCode, 0);
+ expect(result.stderr, isEmpty);
+ expect(result.stdout, contains('Open DevTools'));
+ expect(result.stdout,
+ contains('Usage: dart devtools [arguments] [service protocol uri]'));
+
+ // Does not show verbose help.
+ expect(result.stdout.contains('--try-ports'), isFalse);
+ });
+
+ test('--help --verbose', () {
+ p = project();
+ var result = p.runSync(['devtools', '--help', '--verbose']);
+ expect(result.exitCode, 0);
+ expect(result.stderr, isEmpty);
+ expect(result.stdout, contains('Open DevTools'));
+ expect(result.stdout,
+ contains('Usage: dart devtools [arguments] [service protocol uri]'));
+
+ // Shows verbose help.
+ expect(result.stdout, contains('--try-ports'));
+ });
+
+ group('integration', () {
+ Process process;
+
+ tearDown(() {
+ process?.kill();
+ });
+
+ test('serves resources', () async {
+ p = project();
+
+ // start the devtools server
+ process = await p.start(['devtools', '--no-launch-browser', '--machine']);
+
+ final Stream<String> inStream = process.stdout
+ .transform<String>(utf8.decoder)
+ .transform<String>(const LineSplitter());
+
+ final line = await inStream.first;
+ final json = jsonDecode(line);
+
+ // {"event":"server.started","method":"server.started","params":{
+ // "host":"127.0.0.1","port":9100,"pid":93508,"protocolVersion":"1.1.0"
+ // }}
+ expect(json['event'], 'server.started');
+ expect(json['params'], isNotNull);
+
+ final host = json['params']['host'];
+ final port = json['params']['port'];
+ expect(host, isA<String>());
+ expect(port, isA<int>());
+
+ // Connect to the port and confirm we can load a devtools resource.
+ HttpClient client = HttpClient();
+ final httpRequest = await client.get(host, port, 'index.html');
+ final httpResponse = await httpRequest.close();
+
+ final contents =
+ (await httpResponse.transform(utf8.decoder).toList()).join();
+ client.close();
+
+ expect(contents, contains('DevTools'));
+
+ // kill the process
+ process.kill();
+ process = null;
+ });
+ });
+}
diff --git a/runtime/tests/vm/dart/isolates/long_regexp_process_oob_messages_test.dart b/runtime/tests/vm/dart/isolates/long_regexp_process_oob_messages_test.dart
new file mode 100644
index 0000000..404b978
--- /dev/null
+++ b/runtime/tests/vm/dart/isolates/long_regexp_process_oob_messages_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2021, 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.
+
+import 'dart:isolate';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+worker(SendPort sendPort) {
+ final re = RegExp(r'(x+)*y');
+ final s = 'x' * 100 + '';
+ sendPort.send('worker started');
+ print(re.allMatches(s).iterator.moveNext());
+}
+
+main() async {
+ asyncStart();
+ ReceivePort onExit = ReceivePort();
+ ReceivePort workerStarted = ReceivePort();
+ final isolate = await Isolate.spawn(worker, workerStarted.sendPort,
+ onExit: onExit.sendPort, errorsAreFatal: true);
+ await workerStarted.first;
+ print('worker started, now killing worker');
+ isolate.kill(priority: Isolate.immediate);
+ await onExit.first;
+ print('worker exited');
+ asyncEnd();
+}
diff --git a/runtime/tests/vm/dart_2/isolates/long_regexp_process_oob_messages_test.dart b/runtime/tests/vm/dart_2/isolates/long_regexp_process_oob_messages_test.dart
new file mode 100644
index 0000000..404b978
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolates/long_regexp_process_oob_messages_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2021, 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.
+
+import 'dart:isolate';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+worker(SendPort sendPort) {
+ final re = RegExp(r'(x+)*y');
+ final s = 'x' * 100 + '';
+ sendPort.send('worker started');
+ print(re.allMatches(s).iterator.moveNext());
+}
+
+main() async {
+ asyncStart();
+ ReceivePort onExit = ReceivePort();
+ ReceivePort workerStarted = ReceivePort();
+ final isolate = await Isolate.spawn(worker, workerStarted.sendPort,
+ onExit: onExit.sendPort, errorsAreFatal: true);
+ await workerStarted.first;
+ print('worker started, now killing worker');
+ isolate.kill(priority: Isolate.immediate);
+ await onExit.first;
+ print('worker exited');
+ asyncEnd();
+}
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 5d41659..f8b17ab 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -717,6 +717,13 @@
Dart_KernelCompilationVerbosityLevel verbosity) {
// Build the message for the Kernel isolate.
// tag is used to specify which operation the frontend should perform.
+ if (port_ == ILLEGAL_PORT) {
+ Dart_KernelCompilationResult result = {};
+ result.status = Dart_KernelCompilationStatus_Unknown;
+ result.error =
+ Utils::StrDup("Error Kernel Isolate : unable to create reply port");
+ return result;
+ }
Dart_CObject tag;
tag.type = Dart_CObject_kInt32;
tag.value.as_int32 = request_tag;
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index 708297a..dbd71e2 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -468,13 +468,13 @@
(regexp.num_bracket_expressions() + 1) * 2;
}
-static IrregexpInterpreter::IrregexpResult ExecRaw(const RegExp& regexp,
- const String& subject,
- intptr_t index,
- bool sticky,
- int32_t* output,
- intptr_t output_size,
- Zone* zone) {
+static ObjectPtr ExecRaw(const RegExp& regexp,
+ const String& subject,
+ intptr_t index,
+ bool sticky,
+ int32_t* output,
+ intptr_t output_size,
+ Zone* zone) {
bool is_one_byte =
subject.IsOneByteString() || subject.IsExternalOneByteString();
@@ -493,14 +493,16 @@
const TypedData& bytecode =
TypedData::Handle(zone, regexp.bytecode(is_one_byte, sticky));
ASSERT(!bytecode.IsNull());
- IrregexpInterpreter::IrregexpResult result =
- IrregexpInterpreter::Match(bytecode, subject, raw_output, index, zone);
+ const Object& result = Object::Handle(
+ zone,
+ IrregexpInterpreter::Match(bytecode, subject, raw_output, index, zone));
- if (result == IrregexpInterpreter::RE_SUCCESS) {
+ if (result.ptr() == Bool::True().ptr()) {
// Copy capture results to the start of the registers array.
memmove(output, raw_output, number_of_capture_registers * sizeof(int32_t));
}
- if (result == IrregexpInterpreter::RE_EXCEPTION) {
+ if (result.ptr() == Object::null()) {
+ // Exception during regexp processing
Thread* thread = Thread::Current();
auto isolate_group = thread->isolate_group();
const Instance& exception =
@@ -508,14 +510,14 @@
Exceptions::Throw(thread, exception);
UNREACHABLE();
}
- return result;
+ return result.ptr();
}
-InstancePtr BytecodeRegExpMacroAssembler::Interpret(const RegExp& regexp,
- const String& subject,
- const Smi& start_index,
- bool sticky,
- Zone* zone) {
+ObjectPtr BytecodeRegExpMacroAssembler::Interpret(const RegExp& regexp,
+ const String& subject,
+ const Smi& start_index,
+ bool sticky,
+ Zone* zone) {
intptr_t required_registers = Prepare(regexp, subject, sticky, zone);
if (required_registers < 0) {
// Compiling failed with an exception.
@@ -525,11 +527,10 @@
// V8 uses a shared copy on the isolate when smaller than some threshold.
int32_t* output_registers = zone->Alloc<int32_t>(required_registers);
- IrregexpInterpreter::IrregexpResult result =
- ExecRaw(regexp, subject, start_index.Value(), sticky, output_registers,
- required_registers, zone);
-
- if (result == IrregexpInterpreter::RE_SUCCESS) {
+ const Object& result =
+ Object::Handle(zone, ExecRaw(regexp, subject, start_index.Value(), sticky,
+ output_registers, required_registers, zone));
+ if (result.ptr() == Bool::True().ptr()) {
intptr_t capture_count = regexp.num_bracket_expressions();
intptr_t capture_register_count = (capture_count + 1) * 2;
ASSERT(required_registers >= capture_register_count);
@@ -553,10 +554,15 @@
return result.ptr();
}
- if (result == IrregexpInterpreter::RE_EXCEPTION) {
+ if (result.ptr() == Object::null()) {
+ // internal exception
UNREACHABLE();
}
- ASSERT(result == IrregexpInterpreter::RE_FAILURE);
+ if (result.IsError()) {
+ Exceptions::PropagateError(Error::Cast(result));
+ UNREACHABLE();
+ }
+ ASSERT(result.ptr() == Bool::False().ptr());
return Instance::null();
}
diff --git a/runtime/vm/regexp_assembler_bytecode.h b/runtime/vm/regexp_assembler_bytecode.h
index cdedaa1..6bb8f94 100644
--- a/runtime/vm/regexp_assembler_bytecode.h
+++ b/runtime/vm/regexp_assembler_bytecode.h
@@ -107,11 +107,11 @@
virtual void PrintBlocks() { UNIMPLEMENTED(); }
/////
- static InstancePtr Interpret(const RegExp& regexp,
- const String& str,
- const Smi& start_index,
- bool is_sticky,
- Zone* zone);
+ static ObjectPtr Interpret(const RegExp& regexp,
+ const String& str,
+ const Smi& start_index,
+ bool is_sticky,
+ Zone* zone);
private:
void Expand();
diff --git a/runtime/vm/regexp_interpreter.cc b/runtime/vm/regexp_interpreter.cc
index eb0a243..d9248ac 100644
--- a/runtime/vm/regexp_interpreter.cc
+++ b/runtime/vm/regexp_interpreter.cc
@@ -4,11 +4,12 @@
// A simple interpreter for the Irregexp byte code.
-#include "vm/regexp_interpreter.h"
-
#include <memory>
#include <utility>
+#include "heap/safepoint.h"
+#include "vm/regexp_interpreter.h"
+
#include "platform/unicode.h"
#include "vm/object.h"
#include "vm/regexp_assembler.h"
@@ -169,14 +170,16 @@
DISALLOW_COPY_AND_ASSIGN(BacktrackStack);
};
+// Returns True if success, False if failure, Null if internal exception,
+// Error if VM error needs to be propagated up the callchain.
template <typename Char>
-static IrregexpInterpreter::IrregexpResult RawMatch(const uint8_t* code_base,
- const String& subject,
- int32_t* registers,
- intptr_t current,
- uint32_t current_char,
- Zone* zone) {
- const uint8_t* pc = code_base;
+static ObjectPtr RawMatch(const TypedData& bytecode,
+ const String& subject,
+ int32_t* registers,
+ intptr_t current,
+ uint32_t current_char,
+ Zone* zone) {
+ const auto thread = Thread::Current();
// BacktrackStack ensures that the memory allocated for the backtracking stack
// is returned to the system or cached if there is no stack being cached at
// the moment.
@@ -196,482 +199,506 @@
OS::PrintErr("Start irregexp bytecode interpreter\n");
}
#endif
+ const uint8_t* code_base;
+ const uint8_t* pc;
+ {
+ NoSafepointScope no_safepoint;
+ code_base = reinterpret_cast<uint8_t*>(bytecode.DataAddr(0));
+ pc = code_base;
+ }
while (true) {
- int32_t insn = Load32Aligned(pc);
- switch (insn & BYTECODE_MASK) {
- BYTECODE(BREAK)
- UNREACHABLE();
- return IrregexpInterpreter::RE_FAILURE;
- BYTECODE(PUSH_CP)
- if (--backtrack_stack_space < 0) {
- return IrregexpInterpreter::RE_EXCEPTION;
+ if (UNLIKELY(thread->HasScheduledInterrupts())) {
+ intptr_t pc_offset = pc - code_base;
+ ErrorPtr error = thread->HandleInterrupts();
+ if (error != Object::null()) {
+ // Needs to be propagated to the Dart native invoking the
+ // regex matcher.
+ return error;
}
- *backtrack_sp++ = current;
- pc += BC_PUSH_CP_LENGTH;
- break;
- BYTECODE(PUSH_BT)
- if (--backtrack_stack_space < 0) {
- return IrregexpInterpreter::RE_EXCEPTION;
- }
- *backtrack_sp++ = Load32Aligned(pc + 4);
- pc += BC_PUSH_BT_LENGTH;
- break;
- BYTECODE(PUSH_REGISTER)
- if (--backtrack_stack_space < 0) {
- return IrregexpInterpreter::RE_EXCEPTION;
- }
- *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
- pc += BC_PUSH_REGISTER_LENGTH;
- break;
- BYTECODE(SET_REGISTER)
- registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
- pc += BC_SET_REGISTER_LENGTH;
- break;
- BYTECODE(ADVANCE_REGISTER)
- registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
- pc += BC_ADVANCE_REGISTER_LENGTH;
- break;
- BYTECODE(SET_REGISTER_TO_CP)
- registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
- pc += BC_SET_REGISTER_TO_CP_LENGTH;
- break;
- BYTECODE(SET_CP_TO_REGISTER)
- current = registers[insn >> BYTECODE_SHIFT];
- pc += BC_SET_CP_TO_REGISTER_LENGTH;
- break;
- BYTECODE(SET_REGISTER_TO_SP)
- registers[insn >> BYTECODE_SHIFT] =
- static_cast<int>(backtrack_sp - backtrack_stack_base);
- pc += BC_SET_REGISTER_TO_SP_LENGTH;
- break;
- BYTECODE(SET_SP_TO_REGISTER)
- backtrack_sp = backtrack_stack_base + registers[insn >> BYTECODE_SHIFT];
- backtrack_stack_space =
- backtrack_stack.max_size() -
- static_cast<int>(backtrack_sp - backtrack_stack_base);
- pc += BC_SET_SP_TO_REGISTER_LENGTH;
- break;
- BYTECODE(POP_CP)
- backtrack_stack_space++;
- --backtrack_sp;
- current = *backtrack_sp;
- pc += BC_POP_CP_LENGTH;
- break;
- BYTECODE(POP_BT)
- backtrack_stack_space++;
- --backtrack_sp;
- pc = code_base + *backtrack_sp;
- break;
- BYTECODE(POP_REGISTER)
- backtrack_stack_space++;
- --backtrack_sp;
- registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
- pc += BC_POP_REGISTER_LENGTH;
- break;
- BYTECODE(FAIL)
- return IrregexpInterpreter::RE_FAILURE;
- BYTECODE(SUCCEED)
- return IrregexpInterpreter::RE_SUCCESS;
- BYTECODE(ADVANCE_CP)
- current += insn >> BYTECODE_SHIFT;
- pc += BC_ADVANCE_CP_LENGTH;
- break;
- BYTECODE(GOTO)
- pc = code_base + Load32Aligned(pc + 4);
- break;
- BYTECODE(ADVANCE_CP_AND_GOTO)
- current += insn >> BYTECODE_SHIFT;
- pc = code_base + Load32Aligned(pc + 4);
- break;
- BYTECODE(CHECK_GREEDY)
- if (current == backtrack_sp[-1]) {
- backtrack_sp--;
+ NoSafepointScope no_safepoint;
+ code_base = reinterpret_cast<uint8_t*>(bytecode.DataAddr(0));
+ pc = code_base + pc_offset;
+ }
+ NoSafepointScope no_safepoint;
+ bool check_for_safepoint_now = false;
+ while (!check_for_safepoint_now) {
+ int32_t insn = Load32Aligned(pc);
+ switch (insn & BYTECODE_MASK) {
+ BYTECODE(BREAK)
+ UNREACHABLE();
+ return Bool::False().ptr();
+ BYTECODE(PUSH_CP)
+ if (--backtrack_stack_space < 0) {
+ return Object::null();
+ }
+ *backtrack_sp++ = current;
+ pc += BC_PUSH_CP_LENGTH;
+ break;
+ BYTECODE(PUSH_BT)
+ if (--backtrack_stack_space < 0) {
+ return Object::null();
+ }
+ *backtrack_sp++ = Load32Aligned(pc + 4);
+ pc += BC_PUSH_BT_LENGTH;
+ break;
+ BYTECODE(PUSH_REGISTER)
+ if (--backtrack_stack_space < 0) {
+ return Object::null();
+ }
+ *backtrack_sp++ = registers[insn >> BYTECODE_SHIFT];
+ pc += BC_PUSH_REGISTER_LENGTH;
+ break;
+ BYTECODE(SET_REGISTER)
+ registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
+ pc += BC_SET_REGISTER_LENGTH;
+ break;
+ BYTECODE(ADVANCE_REGISTER)
+ registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
+ pc += BC_ADVANCE_REGISTER_LENGTH;
+ break;
+ BYTECODE(SET_REGISTER_TO_CP)
+ registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
+ pc += BC_SET_REGISTER_TO_CP_LENGTH;
+ break;
+ BYTECODE(SET_CP_TO_REGISTER)
+ current = registers[insn >> BYTECODE_SHIFT];
+ pc += BC_SET_CP_TO_REGISTER_LENGTH;
+ break;
+ BYTECODE(SET_REGISTER_TO_SP)
+ registers[insn >> BYTECODE_SHIFT] =
+ static_cast<int>(backtrack_sp - backtrack_stack_base);
+ pc += BC_SET_REGISTER_TO_SP_LENGTH;
+ break;
+ BYTECODE(SET_SP_TO_REGISTER)
+ backtrack_sp = backtrack_stack_base + registers[insn >> BYTECODE_SHIFT];
+ backtrack_stack_space =
+ backtrack_stack.max_size() -
+ static_cast<int>(backtrack_sp - backtrack_stack_base);
+ pc += BC_SET_SP_TO_REGISTER_LENGTH;
+ break;
+ BYTECODE(POP_CP)
backtrack_stack_space++;
+ --backtrack_sp;
+ current = *backtrack_sp;
+ pc += BC_POP_CP_LENGTH;
+ break;
+ BYTECODE(POP_BT)
+ backtrack_stack_space++;
+ --backtrack_sp;
+ pc = code_base + *backtrack_sp;
+ // This should match check cadence in JIT irregexp implementation.
+ check_for_safepoint_now = true;
+ break;
+ BYTECODE(POP_REGISTER)
+ backtrack_stack_space++;
+ --backtrack_sp;
+ registers[insn >> BYTECODE_SHIFT] = *backtrack_sp;
+ pc += BC_POP_REGISTER_LENGTH;
+ break;
+ BYTECODE(FAIL)
+ return Bool::False().ptr();
+ BYTECODE(SUCCEED)
+ return Bool::True().ptr();
+ BYTECODE(ADVANCE_CP)
+ current += insn >> BYTECODE_SHIFT;
+ pc += BC_ADVANCE_CP_LENGTH;
+ break;
+ BYTECODE(GOTO)
pc = code_base + Load32Aligned(pc + 4);
- } else {
- pc += BC_CHECK_GREEDY_LENGTH;
- }
- break;
- BYTECODE(LOAD_CURRENT_CHAR) {
- int pos = current + (insn >> BYTECODE_SHIFT);
- if (pos < 0 || pos >= subject_length) {
+ break;
+ BYTECODE(ADVANCE_CP_AND_GOTO)
+ current += insn >> BYTECODE_SHIFT;
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ BYTECODE(CHECK_GREEDY)
+ if (current == backtrack_sp[-1]) {
+ backtrack_sp--;
+ backtrack_stack_space++;
pc = code_base + Load32Aligned(pc + 4);
} else {
- current_char = subject.CharAt(pos);
- pc += BC_LOAD_CURRENT_CHAR_LENGTH;
+ pc += BC_CHECK_GREEDY_LENGTH;
}
break;
- }
- BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
- int pos = current + (insn >> BYTECODE_SHIFT);
- current_char = subject.CharAt(pos);
- pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
- break;
- }
- BYTECODE(LOAD_2_CURRENT_CHARS) {
- int pos = current + (insn >> BYTECODE_SHIFT);
- if (pos + 2 > subject_length) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
+ BYTECODE(LOAD_CURRENT_CHAR) {
+ int pos = current + (insn >> BYTECODE_SHIFT);
+ if (pos < 0 || pos >= subject_length) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ current_char = subject.CharAt(pos);
+ pc += BC_LOAD_CURRENT_CHAR_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
+ int pos = current + (insn >> BYTECODE_SHIFT);
+ current_char = subject.CharAt(pos);
+ pc += BC_LOAD_CURRENT_CHAR_UNCHECKED_LENGTH;
+ break;
+ }
+ BYTECODE(LOAD_2_CURRENT_CHARS) {
+ int pos = current + (insn >> BYTECODE_SHIFT);
+ if (pos + 2 > subject_length) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ Char next = subject.CharAt(pos + 1);
+ current_char =
+ subject.CharAt(pos) | (next << (kBitsPerByte * sizeof(Char)));
+ pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
+ int pos = current + (insn >> BYTECODE_SHIFT);
Char next = subject.CharAt(pos + 1);
current_char =
subject.CharAt(pos) | (next << (kBitsPerByte * sizeof(Char)));
- pc += BC_LOAD_2_CURRENT_CHARS_LENGTH;
+ pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
+ break;
}
- break;
- }
- BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
- int pos = current + (insn >> BYTECODE_SHIFT);
- Char next = subject.CharAt(pos + 1);
- current_char =
- subject.CharAt(pos) | (next << (kBitsPerByte * sizeof(Char)));
- pc += BC_LOAD_2_CURRENT_CHARS_UNCHECKED_LENGTH;
- break;
- }
- BYTECODE(LOAD_4_CURRENT_CHARS) {
- ASSERT(sizeof(Char) == 1);
- int pos = current + (insn >> BYTECODE_SHIFT);
- if (pos + 4 > subject_length) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
+ BYTECODE(LOAD_4_CURRENT_CHARS) {
+ ASSERT(sizeof(Char) == 1);
+ int pos = current + (insn >> BYTECODE_SHIFT);
+ if (pos + 4 > subject_length) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ Char next1 = subject.CharAt(pos + 1);
+ Char next2 = subject.CharAt(pos + 2);
+ Char next3 = subject.CharAt(pos + 3);
+ current_char = (subject.CharAt(pos) | (next1 << 8) | (next2 << 16) |
+ (next3 << 24));
+ pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
+ ASSERT(sizeof(Char) == 1);
+ int pos = current + (insn >> BYTECODE_SHIFT);
Char next1 = subject.CharAt(pos + 1);
Char next2 = subject.CharAt(pos + 2);
Char next3 = subject.CharAt(pos + 3);
current_char = (subject.CharAt(pos) | (next1 << 8) | (next2 << 16) |
(next3 << 24));
- pc += BC_LOAD_4_CURRENT_CHARS_LENGTH;
+ pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
+ break;
}
- break;
- }
- BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
- ASSERT(sizeof(Char) == 1);
- int pos = current + (insn >> BYTECODE_SHIFT);
- Char next1 = subject.CharAt(pos + 1);
- Char next2 = subject.CharAt(pos + 2);
- Char next3 = subject.CharAt(pos + 3);
- current_char = (subject.CharAt(pos) | (next1 << 8) | (next2 << 16) |
- (next3 << 24));
- pc += BC_LOAD_4_CURRENT_CHARS_UNCHECKED_LENGTH;
- break;
- }
- BYTECODE(CHECK_4_CHARS) {
- uint32_t c = Load32Aligned(pc + 4);
- if (c == current_char) {
+ BYTECODE(CHECK_4_CHARS) {
+ uint32_t c = Load32Aligned(pc + 4);
+ if (c == current_char) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_CHECK_4_CHARS_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_CHAR) {
+ uint32_t c = (insn >> BYTECODE_SHIFT);
+ if (c == current_char) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ pc += BC_CHECK_CHAR_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_NOT_4_CHARS) {
+ uint32_t c = Load32Aligned(pc + 4);
+ if (c != current_char) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_CHECK_NOT_4_CHARS_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_NOT_CHAR) {
+ uint32_t c = (insn >> BYTECODE_SHIFT);
+ if (c != current_char) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ pc += BC_CHECK_NOT_CHAR_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(AND_CHECK_4_CHARS) {
+ uint32_t c = Load32Aligned(pc + 4);
+ if (c == (current_char & Load32Aligned(pc + 8))) {
+ pc = code_base + Load32Aligned(pc + 12);
+ } else {
+ pc += BC_AND_CHECK_4_CHARS_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(AND_CHECK_CHAR) {
+ uint32_t c = (insn >> BYTECODE_SHIFT);
+ if (c == (current_char & Load32Aligned(pc + 4))) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_AND_CHECK_CHAR_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(AND_CHECK_NOT_4_CHARS) {
+ uint32_t c = Load32Aligned(pc + 4);
+ if (c != (current_char & Load32Aligned(pc + 8))) {
+ pc = code_base + Load32Aligned(pc + 12);
+ } else {
+ pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(AND_CHECK_NOT_CHAR) {
+ uint32_t c = (insn >> BYTECODE_SHIFT);
+ if (c != (current_char & Load32Aligned(pc + 4))) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
+ uint32_t c = (insn >> BYTECODE_SHIFT);
+ uint32_t minus = Load16Aligned(pc + 4);
+ uint32_t mask = Load16Aligned(pc + 6);
+ if (c != ((current_char - minus) & mask)) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_CHAR_IN_RANGE) {
+ uint32_t from = Load16Aligned(pc + 4);
+ uint32_t to = Load16Aligned(pc + 6);
+ if (from <= current_char && current_char <= to) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_CHECK_CHAR_IN_RANGE_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_CHAR_NOT_IN_RANGE) {
+ uint32_t from = Load16Aligned(pc + 4);
+ uint32_t to = Load16Aligned(pc + 6);
+ if (from > current_char || current_char > to) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_CHECK_CHAR_NOT_IN_RANGE_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_BIT_IN_TABLE) {
+ int mask = RegExpMacroAssembler::kTableMask;
+ uint8_t b = pc[8 + ((current_char & mask) >> kBitsPerByteLog2)];
+ int bit = (current_char & (kBitsPerByte - 1));
+ if ((b & (1 << bit)) != 0) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ pc += BC_CHECK_BIT_IN_TABLE_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_LT) {
+ uint32_t limit = (insn >> BYTECODE_SHIFT);
+ if (current_char < limit) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ pc += BC_CHECK_LT_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_GT) {
+ uint32_t limit = (insn >> BYTECODE_SHIFT);
+ if (current_char > limit) {
+ pc = code_base + Load32Aligned(pc + 4);
+ } else {
+ pc += BC_CHECK_GT_LENGTH;
+ }
+ break;
+ }
+ BYTECODE(CHECK_REGISTER_LT)
+ if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
pc = code_base + Load32Aligned(pc + 8);
} else {
- pc += BC_CHECK_4_CHARS_LENGTH;
+ pc += BC_CHECK_REGISTER_LT_LENGTH;
}
break;
- }
- BYTECODE(CHECK_CHAR) {
- uint32_t c = (insn >> BYTECODE_SHIFT);
- if (c == current_char) {
+ BYTECODE(CHECK_REGISTER_GE)
+ if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
+ pc = code_base + Load32Aligned(pc + 8);
+ } else {
+ pc += BC_CHECK_REGISTER_GE_LENGTH;
+ }
+ break;
+ BYTECODE(CHECK_REGISTER_EQ_POS)
+ if (registers[insn >> BYTECODE_SHIFT] == current) {
pc = code_base + Load32Aligned(pc + 4);
} else {
- pc += BC_CHECK_CHAR_LENGTH;
+ pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
}
break;
- }
- BYTECODE(CHECK_NOT_4_CHARS) {
- uint32_t c = Load32Aligned(pc + 4);
- if (c != current_char) {
+ BYTECODE(CHECK_NOT_REGS_EQUAL)
+ if (registers[insn >> BYTECODE_SHIFT] ==
+ registers[Load32Aligned(pc + 4)]) {
+ pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
+ } else {
pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_CHECK_NOT_4_CHARS_LENGTH;
}
break;
- }
- BYTECODE(CHECK_NOT_CHAR) {
- uint32_t c = (insn >> BYTECODE_SHIFT);
- if (c != current_char) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
- pc += BC_CHECK_NOT_CHAR_LENGTH;
- }
- break;
- }
- BYTECODE(AND_CHECK_4_CHARS) {
- uint32_t c = Load32Aligned(pc + 4);
- if (c == (current_char & Load32Aligned(pc + 8))) {
- pc = code_base + Load32Aligned(pc + 12);
- } else {
- pc += BC_AND_CHECK_4_CHARS_LENGTH;
- }
- break;
- }
- BYTECODE(AND_CHECK_CHAR) {
- uint32_t c = (insn >> BYTECODE_SHIFT);
- if (c == (current_char & Load32Aligned(pc + 4))) {
- pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_AND_CHECK_CHAR_LENGTH;
- }
- break;
- }
- BYTECODE(AND_CHECK_NOT_4_CHARS) {
- uint32_t c = Load32Aligned(pc + 4);
- if (c != (current_char & Load32Aligned(pc + 8))) {
- pc = code_base + Load32Aligned(pc + 12);
- } else {
- pc += BC_AND_CHECK_NOT_4_CHARS_LENGTH;
- }
- break;
- }
- BYTECODE(AND_CHECK_NOT_CHAR) {
- uint32_t c = (insn >> BYTECODE_SHIFT);
- if (c != (current_char & Load32Aligned(pc + 4))) {
- pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_AND_CHECK_NOT_CHAR_LENGTH;
- }
- break;
- }
- BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
- uint32_t c = (insn >> BYTECODE_SHIFT);
- uint32_t minus = Load16Aligned(pc + 4);
- uint32_t mask = Load16Aligned(pc + 6);
- if (c != ((current_char - minus) & mask)) {
- pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_MINUS_AND_CHECK_NOT_CHAR_LENGTH;
- }
- break;
- }
- BYTECODE(CHECK_CHAR_IN_RANGE) {
- uint32_t from = Load16Aligned(pc + 4);
- uint32_t to = Load16Aligned(pc + 6);
- if (from <= current_char && current_char <= to) {
- pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_CHECK_CHAR_IN_RANGE_LENGTH;
- }
- break;
- }
- BYTECODE(CHECK_CHAR_NOT_IN_RANGE) {
- uint32_t from = Load16Aligned(pc + 4);
- uint32_t to = Load16Aligned(pc + 6);
- if (from > current_char || current_char > to) {
- pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_CHECK_CHAR_NOT_IN_RANGE_LENGTH;
- }
- break;
- }
- BYTECODE(CHECK_BIT_IN_TABLE) {
- int mask = RegExpMacroAssembler::kTableMask;
- uint8_t b = pc[8 + ((current_char & mask) >> kBitsPerByteLog2)];
- int bit = (current_char & (kBitsPerByte - 1));
- if ((b & (1 << bit)) != 0) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
- pc += BC_CHECK_BIT_IN_TABLE_LENGTH;
- }
- break;
- }
- BYTECODE(CHECK_LT) {
- uint32_t limit = (insn >> BYTECODE_SHIFT);
- if (current_char < limit) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
- pc += BC_CHECK_LT_LENGTH;
- }
- break;
- }
- BYTECODE(CHECK_GT) {
- uint32_t limit = (insn >> BYTECODE_SHIFT);
- if (current_char > limit) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
- pc += BC_CHECK_GT_LENGTH;
- }
- break;
- }
- BYTECODE(CHECK_REGISTER_LT)
- if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
- pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_CHECK_REGISTER_LT_LENGTH;
- }
- break;
- BYTECODE(CHECK_REGISTER_GE)
- if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
- pc = code_base + Load32Aligned(pc + 8);
- } else {
- pc += BC_CHECK_REGISTER_GE_LENGTH;
- }
- break;
- BYTECODE(CHECK_REGISTER_EQ_POS)
- if (registers[insn >> BYTECODE_SHIFT] == current) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
- pc += BC_CHECK_REGISTER_EQ_POS_LENGTH;
- }
- break;
- BYTECODE(CHECK_NOT_REGS_EQUAL)
- if (registers[insn >> BYTECODE_SHIFT] ==
- registers[Load32Aligned(pc + 4)]) {
- pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
- } else {
- pc = code_base + Load32Aligned(pc + 8);
- }
- break;
- BYTECODE(CHECK_NOT_BACK_REF) {
- int from = registers[insn >> BYTECODE_SHIFT];
- int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
- if (from < 0 || len <= 0) {
+ BYTECODE(CHECK_NOT_BACK_REF) {
+ int from = registers[insn >> BYTECODE_SHIFT];
+ int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+ if (from < 0 || len <= 0) {
+ pc += BC_CHECK_NOT_BACK_REF_LENGTH;
+ break;
+ }
+ if (current + len > subject_length) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ } else {
+ int i;
+ for (i = 0; i < len; i++) {
+ if (subject.CharAt(from + i) != subject.CharAt(current + i)) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ }
+ }
+ if (i < len) break;
+ current += len;
+ }
pc += BC_CHECK_NOT_BACK_REF_LENGTH;
break;
}
- if (current + len > subject_length) {
- pc = code_base + Load32Aligned(pc + 4);
- break;
- } else {
- int i;
- for (i = 0; i < len; i++) {
- if (subject.CharAt(from + i) != subject.CharAt(current + i)) {
+ BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE)
+ FALL_THROUGH;
+ BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
+ const bool unicode =
+ (insn & BYTECODE_MASK) == BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE;
+ int from = registers[insn >> BYTECODE_SHIFT];
+ int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+ if (from < 0 || len <= 0) {
+ pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
+ break;
+ }
+ if (current + len > subject_length) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ } else {
+ if (BackRefMatchesNoCase<Char>(&canonicalize, from, current, len,
+ subject, unicode)) {
+ current += len;
+ pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
+ } else {
pc = code_base + Load32Aligned(pc + 4);
- break;
}
}
- if (i < len) break;
- current += len;
- }
- pc += BC_CHECK_NOT_BACK_REF_LENGTH;
- break;
- }
- BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE)
- FALL_THROUGH;
- BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
- const bool unicode =
- (insn & BYTECODE_MASK) == BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE;
- int from = registers[insn >> BYTECODE_SHIFT];
- int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
- if (from < 0 || len <= 0) {
- pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
break;
}
- if (current + len > subject_length) {
- pc = code_base + Load32Aligned(pc + 4);
- break;
- } else {
- if (BackRefMatchesNoCase<Char>(&canonicalize, from, current, len,
- subject, unicode)) {
- current += len;
- pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH;
- } else {
- pc = code_base + Load32Aligned(pc + 4);
+ BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
+ const int from = registers[insn >> BYTECODE_SHIFT];
+ const int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+ if (from < 0 || len <= 0) {
+ pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
+ break;
}
- }
- break;
- }
- BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
- const int from = registers[insn >> BYTECODE_SHIFT];
- const int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
- if (from < 0 || len <= 0) {
+ if ((current - len) < 0) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ } else {
+ // When looking behind, the string to match (if it is there) lies
+ // before the current position, so we will check the [len]
+ // characters before the current position, excluding the current
+ // position itself.
+ const int start = current - len;
+ int i;
+ for (i = 0; i < len; i++) {
+ if (subject.CharAt(from + i) != subject.CharAt(start + i)) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ }
+ }
+ if (i < len) break;
+ current -= len;
+ }
pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
break;
}
- if ((current - len) < 0) {
- pc = code_base + Load32Aligned(pc + 4);
- break;
- } else {
- // When looking behind, the string to match (if it is there) lies
- // before the current position, so we will check the [len] characters
- // before the current position, excluding the current position itself.
- const int start = current - len;
- int i;
- for (i = 0; i < len; i++) {
- if (subject.CharAt(from + i) != subject.CharAt(start + i)) {
+ BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD)
+ FALL_THROUGH;
+ BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
+ bool unicode = (insn & BYTECODE_MASK) ==
+ BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD;
+ int from = registers[insn >> BYTECODE_SHIFT];
+ int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+ if (from < 0 || len <= 0) {
+ pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
+ break;
+ }
+ if (current < len) {
+ pc = code_base + Load32Aligned(pc + 4);
+ break;
+ } else {
+ if (BackRefMatchesNoCase<Char>(&canonicalize, from, current - len,
+ len, subject, unicode)) {
+ current -= len;
+ pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
+ } else {
pc = code_base + Load32Aligned(pc + 4);
- break;
}
}
- if (i < len) break;
- current -= len;
- }
- pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
- break;
- }
- BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD)
- FALL_THROUGH;
- BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
- bool unicode = (insn & BYTECODE_MASK) ==
- BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD;
- int from = registers[insn >> BYTECODE_SHIFT];
- int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
- if (from < 0 || len <= 0) {
- pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
break;
}
- if (current < len) {
+ BYTECODE(CHECK_AT_START)
+ if (current == 0) {
pc = code_base + Load32Aligned(pc + 4);
- break;
} else {
- if (BackRefMatchesNoCase<Char>(&canonicalize, from, current - len,
- len, subject, unicode)) {
- current -= len;
- pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
+ pc += BC_CHECK_AT_START_LENGTH;
+ }
+ break;
+ BYTECODE(CHECK_NOT_AT_START) {
+ const int32_t cp_offset = insn >> BYTECODE_SHIFT;
+ if (current + cp_offset == 0) {
+ pc += BC_CHECK_NOT_AT_START_LENGTH;
} else {
pc = code_base + Load32Aligned(pc + 4);
}
+ break;
}
- break;
- }
- BYTECODE(CHECK_AT_START)
- if (current == 0) {
- pc = code_base + Load32Aligned(pc + 4);
- } else {
- pc += BC_CHECK_AT_START_LENGTH;
- }
- break;
- BYTECODE(CHECK_NOT_AT_START) {
- const int32_t cp_offset = insn >> BYTECODE_SHIFT;
- if (current + cp_offset == 0) {
- pc += BC_CHECK_NOT_AT_START_LENGTH;
- } else {
- pc = code_base + Load32Aligned(pc + 4);
+ BYTECODE(SET_CURRENT_POSITION_FROM_END) {
+ int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
+ if (subject_length - current > by) {
+ current = subject_length - by;
+ current_char = subject.CharAt(current - 1);
+ }
+ pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
+ break;
}
- break;
+ default:
+ UNREACHABLE();
+ break;
}
- BYTECODE(SET_CURRENT_POSITION_FROM_END) {
- int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
- if (subject_length - current > by) {
- current = subject_length - by;
- current_char = subject.CharAt(current - 1);
- }
- pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
- break;
- }
- default:
- UNREACHABLE();
- break;
}
}
}
-IrregexpInterpreter::IrregexpResult IrregexpInterpreter::Match(
- const TypedData& bytecode,
- const String& subject,
- int32_t* registers,
- intptr_t start_position,
- Zone* zone) {
- NoSafepointScope no_safepoint;
- const uint8_t* code_base = reinterpret_cast<uint8_t*>(bytecode.DataAddr(0));
-
+// Returns True if success, False if failure, Null if internal exception,
+// Error if VM error needs to be propagated up the callchain.
+ObjectPtr IrregexpInterpreter::Match(const TypedData& bytecode,
+ const String& subject,
+ int32_t* registers,
+ intptr_t start_position,
+ Zone* zone) {
uint16_t previous_char = '\n';
if (start_position != 0) {
previous_char = subject.CharAt(start_position - 1);
}
if (subject.IsOneByteString() || subject.IsExternalOneByteString()) {
- return RawMatch<uint8_t>(code_base, subject, registers, start_position,
+ return RawMatch<uint8_t>(bytecode, subject, registers, start_position,
previous_char, zone);
} else if (subject.IsTwoByteString() || subject.IsExternalTwoByteString()) {
- return RawMatch<uint16_t>(code_base, subject, registers, start_position,
+ return RawMatch<uint16_t>(bytecode, subject, registers, start_position,
previous_char, zone);
} else {
UNREACHABLE();
- return IrregexpInterpreter::RE_FAILURE;
+ return Bool::False().ptr();
}
}
diff --git a/runtime/vm/regexp_interpreter.h b/runtime/vm/regexp_interpreter.h
index 9e4e567..f451a40 100644
--- a/runtime/vm/regexp_interpreter.h
+++ b/runtime/vm/regexp_interpreter.h
@@ -15,13 +15,14 @@
class IrregexpInterpreter : public AllStatic {
public:
- enum IrregexpResult { RE_FAILURE = 0, RE_SUCCESS = 1, RE_EXCEPTION = -1 };
-
- static IrregexpResult Match(const TypedData& bytecode,
- const String& subject,
- int32_t* captures,
- intptr_t start_position,
- Zone* zone);
+ // Returns True in case of a success, False in case of a failure,
+ // Null in case of internal exception,
+ // Error in case VM error has to propagated up to the caller.
+ static ObjectPtr Match(const TypedData& bytecode,
+ const String& subject,
+ int32_t* captures,
+ intptr_t start_position,
+ Zone* zone);
};
} // namespace dart
diff --git a/third_party/devtools/README b/third_party/devtools/README
deleted file mode 100644
index d35a323..0000000
--- a/third_party/devtools/README
+++ /dev/null
@@ -1,14 +0,0 @@
-This folder contains a pre-built Dart DevTools instance which can be served
-as a web application, as well as the package:devtools_server and package:devtools_shared
-from the same revision, used to host and launch DevTools from a Dart process.
-
-First, ensure Flutter is installed and on your path (see https://flutter.dev/docs/get-started/install/linux#install-flutter-manually).
-
-With `flutter` on your path, do the following:
-
-- Run ./update.sh <revision> to build DevTools at a given revision and upload it
- to CIPD. The uploaded CIPD entry will be tagged with `revision:<revision>`
-- Update DEPS to point to the newly updated DevTools by providing "revision:<revision>"
- as the version entry for "third_party/devtools"
-
-DevTools CIPD packages are located at https://chrome-infra-packages.appspot.com/p/dart/third_party/flutter/devtools/+/.
diff --git a/third_party/devtools/README.md b/third_party/devtools/README.md
new file mode 100644
index 0000000..6011569
--- /dev/null
+++ b/third_party/devtools/README.md
@@ -0,0 +1,13 @@
+This folder contains a pre-built Dart DevTools instance which can be served
+as a web application, as well as the package:devtools_server and package:devtools_shared
+packages from the same revision, used to host and launch DevTools from a Dart process.
+
+To build DevTools and update the CIPD resources, do the following:
+
+- Run ./update.sh <revision> to build DevTools at a given revision and upload it
+ to CIPD. The uploaded CIPD entry will be tagged with `revision:<revision>`
+- Update DEPS to point to the newly updated DevTools by providing "revision:<revision>"
+ as the version entry for "third_party/devtools"
+
+DevTools CIPD packages are located at
+https://chrome-infra-packages.appspot.com/p/dart/third_party/flutter/devtools/+/.
diff --git a/third_party/devtools/update.sh b/third_party/devtools/update.sh
index 90533c5..92d6f2d 100755
--- a/third_party/devtools/update.sh
+++ b/third_party/devtools/update.sh
@@ -24,6 +24,7 @@
cd devtools
git checkout -b cipd_release $1
+./tool/update_flutter_sdk.sh
./tool/build_release.sh
# Copy the build output as well as the devtools packages needed
@@ -31,6 +32,7 @@
mkdir cipd_package
cp -R packages/devtools/build/ cipd_package/web
cp -r packages/devtools_shared cipd_package
+cp -r packages/devtools_server cipd_package
cipd create \
-name dart/third_party/flutter/devtools \
diff --git a/tools/VERSION b/tools/VERSION
index dfd5a96..66d255d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 38
+PRERELEASE 39
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 882c827..066eb2c 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -57,6 +57,7 @@
packageDirectory(
'runtime/observatory_2/tests/service_2/observatory_test_package_2'),
packageDirectory('sdk/lib/_internal/sdk_library_metadata'),
+ packageDirectory('third_party/devtools/devtools_server'),
packageDirectory('third_party/devtools/devtools_shared'),
packageDirectory('third_party/pkg/protobuf/protobuf'),
packageDirectory('third_party/pkg/webdev/frontend_server_client'),