Version 2.14.0-191.0.dev
Merge commit 'db17c490f8147b9b0b104b8b4ad9dfb2bc2f1a4f' into 'dev'
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index 38def2f..4c24110 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -139,6 +139,37 @@
expect(testTargets[0].kind, ElementKind.LIBRARY);
}
+ Future<void> test_importUri_configurations() async {
+ final ioFile = newFile(join(testFolder, 'io.dart'));
+ final htmlFile = newFile(join(testFolder, 'html.dart'));
+ addTestFile('''
+import 'foo.dart'
+ if (dart.library.io) 'io.dart'
+ if (dart.library.html) 'html.dart';
+
+main() {
+}''');
+ await waitForTasksFinished();
+
+ // Request navigations for 'io.dart'
+ await _getNavigation(testFile, 41, 9);
+ expect(regions, hasLength(1));
+ assertHasRegionString("'io.dart'");
+ expect(testTargets, hasLength(1));
+ var target = testTargets.first;
+ expect(target.kind, ElementKind.LIBRARY);
+ expect(targetFiles[target.fileIndex], equals(ioFile.path));
+
+ // Request navigations for 'html.dart'
+ await _getNavigation(testFile, 76, 11);
+ expect(regions, hasLength(1));
+ assertHasRegionString("'html.dart'");
+ expect(testTargets, hasLength(1));
+ target = testTargets.first;
+ expect(target.kind, ElementKind.LIBRARY);
+ expect(targetFiles[target.fileIndex], equals(htmlFile.path));
+ }
+
Future<void> test_invalidFilePathFormat_notAbsolute() async {
var request = _createGetNavigationRequest('test.dart', 0, 0);
var response = await waitResponse(request);
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index e96926c..13c0f9b 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -68,9 +68,7 @@
return;
}
// Discard elements that don't span the offset/range given (if provided).
- if (requestedOffset != null &&
- (offset > requestedOffset! + (requestedLength ?? 0) ||
- offset + length < requestedOffset!)) {
+ if (!_isWithinRequestedRange(offset, length)) {
return;
}
var converter = AnalyzerConverter();
@@ -154,6 +152,26 @@
offset: codeOffset, length: codeLength);
}
+ /// Checks if offset/length intersect with the range the user requested
+ /// navigation regions for.
+ ///
+ /// If the request did not specify a range, always returns true.
+ bool _isWithinRequestedRange(int offset, int length) {
+ final requestedOffset = this.requestedOffset;
+ if (requestedOffset == null) {
+ return true;
+ }
+ if (offset > requestedOffset + (requestedLength ?? 0)) {
+ // Starts after the requested range.
+ return false;
+ }
+ if (offset + length < requestedOffset) {
+ // Ends before the requested range.
+ return false;
+ }
+ return true;
+ }
+
static ElementDeclarationResult? _parsedDeclaration(Element element) {
var session = element.session;
if (session == null) {
@@ -243,11 +261,13 @@
// TODO(brianwilkerson) If the analyzer ever resolves the URI to a
// library, use that library element to create the region.
var uriNode = node.uri;
- computer.collector.addRegion(
- uriNode.offset,
- uriNode.length,
- protocol.ElementKind.LIBRARY,
- protocol.Location(source.fullName, 0, 0, 0, 0, 0, 0));
+ if (computer._isWithinRequestedRange(uriNode.offset, uriNode.length)) {
+ computer.collector.addRegion(
+ uriNode.offset,
+ uriNode.length,
+ protocol.ElementKind.LIBRARY,
+ protocol.Location(source.fullName, 0, 0, 0, 0, 0, 0));
+ }
}
}
super.visitConfiguration(node);
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index cf67f91..c0a9c24 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -92,6 +92,13 @@
/// the browser.
final bool emitDebugMetadata;
+ /// Whether to emit the debug symbols
+ ///
+ /// Debugger uses this information about to construct mapping between
+ /// dart and js objecys that otherwise requires expensive communication with
+ /// the browser.
+ final bool emitDebugSymbols;
+
final Map<String, String> summaryModules;
final List<ModuleFormat> moduleFormats;
@@ -123,6 +130,7 @@
this.enableAsserts = true,
this.replCompile = false,
this.emitDebugMetadata = false,
+ this.emitDebugSymbols = false,
this.emitFullCompiledKernel = false,
this.summaryModules = const {},
this.moduleFormats = const [],
@@ -140,6 +148,7 @@
enableAsserts: args['enable-asserts'] as bool,
replCompile: args['repl-compile'] as bool,
emitDebugMetadata: args['experimental-emit-debug-metadata'] as bool,
+ emitDebugSymbols: args['emit-debug-symbols'] as bool,
emitFullCompiledKernel:
args['experimental-output-compiled-kernel'] as bool,
summaryModules:
@@ -195,6 +204,11 @@
'Output a metadata file for debug tools next to the .js output.',
defaultsTo: false,
hide: true)
+ ..addFlag('emit-debug-symbols',
+ help: 'Experimental option for compiler development.\n'
+ 'Output a symbols file for debug tools next to the .js output.',
+ defaultsTo: false,
+ hide: true)
..addFlag('experimental-output-compiled-kernel',
help: 'Experimental option for compiler development.\n'
'Output a full kernel file for currently compiled module next to '
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 8ddd4dc..2bac27d 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -11,6 +11,7 @@
import 'package:args/args.dart';
import 'package:build_integration/file_system/multi_root.dart';
import 'package:cli_util/cli_util.dart' show getSdkPath;
+import 'package:dev_compiler/src/kernel/module_symbols.dart';
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
import 'package:kernel/class_hierarchy.dart';
@@ -443,11 +444,13 @@
buildSourceMap: options.sourceMap,
inlineSourceMap: options.inlineSourceMap,
emitDebugMetadata: options.emitDebugMetadata,
+ emitDebugSymbols: options.emitDebugSymbols,
jsUrl: p.toUri(output).toString(),
mapUrl: mapUrl,
fullDillUri: fullDillUri,
customScheme: options.multiRootScheme,
multiRootOutputPath: multiRootOutputPath,
+ compiler: compiler,
component: compiledLibraries);
outFiles.add(file.writeAsString(jsCode.code));
@@ -459,6 +462,11 @@
outFiles.add(
File('$output.metadata').writeAsString(json.encode(jsCode.metadata)));
}
+
+ if (jsCode.symbols != null) {
+ outFiles.add(
+ File('$output.symbols').writeAsString(json.encode(jsCode.symbols)));
+ }
}
if (recordUsedInputs) {
@@ -635,7 +643,13 @@
/// see: https://goto.google.com/dart-web-debugger-metadata
final ModuleMetadata metadata;
- JSCode(this.code, this.sourceMap, {this.metadata});
+ /// Module debug symbols.
+ ///
+ /// The [symbols] is a contract between compiler and the debugger,
+ /// helping the debugger map between dart and JS objects.
+ final ModuleSymbols symbols;
+
+ JSCode(this.code, this.sourceMap, {this.symbols, this.metadata});
}
/// Converts [moduleTree] to [JSCode], using [format].
@@ -646,12 +660,14 @@
{bool buildSourceMap = false,
bool inlineSourceMap = false,
bool emitDebugMetadata = false,
+ bool emitDebugSymbols = false,
String jsUrl,
String mapUrl,
String fullDillUri,
String sourceMapBase,
String customScheme,
String multiRootOutputPath,
+ ProgramCompiler compiler,
Component component}) {
var opts = js_ast.JavaScriptPrintingOptions(
allowKeywordsInProperties: true, allowSingleLineIfStatements: true);
@@ -666,8 +682,8 @@
}
var tree = transformModuleFormat(format, moduleTree);
- tree.accept(
- js_ast.Printer(opts, printer, localNamer: js_ast.TemporaryNamer(tree)));
+ var namer = js_ast.TemporaryNamer(tree);
+ tree.accept(js_ast.Printer(opts, printer, localNamer: namer));
Map builtMap;
if (buildSourceMap && sourceMap != null) {
@@ -710,7 +726,15 @@
? _emitMetadata(moduleTree, component, mapUrl, jsUrl, fullDillUri)
: null;
- return JSCode(text, builtMap, metadata: debugMetadata);
+ var debugSymbols =
+ emitDebugSymbols ? _emitSymbols(compiler, component) : null;
+
+ return JSCode(text, builtMap, symbols: debugSymbols, metadata: debugMetadata);
+}
+
+ModuleSymbols _emitSymbols(ProgramCompiler compiler, Component component) {
+ // TODO(annagrin): collect module symbols.
+ return ModuleSymbols();
}
ModuleMetadata _emitMetadata(js_ast.Program program, Component component,
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
index 7f79898..7300029 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
@@ -152,8 +152,10 @@
inlineSourceMap: true,
buildSourceMap: true,
emitDebugMetadata: true,
+ emitDebugSymbols: true,
jsUrl: '$output',
mapUrl: '$output.map',
+ compiler: kernel2jsCompiler,
component: component,
);
metadata = code.metadata;
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
index 8cda5d8..7141bb4 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
@@ -769,6 +769,7 @@
config.testModule3.jsPath.toFilePath(),
'--source-map',
'--experimental-emit-debug-metadata',
+ '--emit-debug-symbols',
'--experimental-output-compiled-kernel',
'--dart-sdk-summary',
config.sdkSummaryPath.path,
@@ -797,6 +798,7 @@
config.testModule2.jsPath.toFilePath(),
'--source-map',
'--experimental-emit-debug-metadata',
+ '--emit-debug-symbols',
'--experimental-output-compiled-kernel',
'--dart-sdk-summary',
config.sdkSummaryPath.path,
@@ -827,6 +829,7 @@
config.testModule.jsPath.toFilePath(),
'--source-map',
'--experimental-emit-debug-metadata',
+ '--emit-debug-symbols',
'--experimental-output-compiled-kernel',
'--dart-sdk-summary',
config.sdkSummaryPath.path,
@@ -859,6 +862,7 @@
config.mainModule.jsPath.toFilePath(),
'--source-map',
'--experimental-emit-debug-metadata',
+ '--emit-debug-symbols',
'--experimental-output-compiled-kernel',
'--dart-sdk-summary',
config.sdkSummaryPath.path,
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 5881625..4ba6641 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -168,6 +168,8 @@
..addFlag('experimental-emit-debug-metadata',
help: 'Emit module and library metadata for the debugger',
defaultsTo: false)
+ ..addFlag('emit-debug-symbols',
+ help: 'Emit debug symbols for the debugger', defaultsTo: false)
..addOption('dartdevc-module-format',
help: 'The module format to use on for the dartdevc compiler',
defaultsTo: 'amd')
@@ -324,7 +326,8 @@
this.unsafePackageSerialization,
this.incrementalSerialization: true,
this.useDebuggerModuleNames: false,
- this.emitDebugMetadata: false}) {
+ this.emitDebugMetadata: false,
+ this.emitDebugSymbols: false}) {
_outputStream ??= stdout;
printerFactory ??= new BinaryPrinterFactory();
}
@@ -335,6 +338,7 @@
bool incrementalSerialization;
bool useDebuggerModuleNames;
bool emitDebugMetadata;
+ bool emitDebugSymbols;
bool _printIncrementalDependencies;
CompilerOptions _compilerOptions;
@@ -625,6 +629,7 @@
final File manifestFile = File('$filename.json');
final File sourceMapsFile = File('$filename.map');
final File metadataFile = File('$filename.metadata');
+ final File symbolsFile = File('$filename.symbols');
if (!sourceFile.parent.existsSync()) {
sourceFile.parent.createSync(recursive: true);
}
@@ -632,6 +637,7 @@
component, strongComponents, fileSystemScheme, packageConfig,
useDebuggerModuleNames: useDebuggerModuleNames,
emitDebugMetadata: emitDebugMetadata,
+ emitDebugSymbols: emitDebugSymbols,
moduleFormat: moduleFormat,
soundNullSafety: soundNullSafety);
final sourceFileSink = sourceFile.openWrite();
@@ -639,6 +645,7 @@
final sourceMapsFileSink = sourceMapsFile.openWrite();
final metadataFileSink =
emitDebugMetadata ? metadataFile.openWrite() : null;
+ final symbolsFileSink = emitDebugSymbols ? symbolsFile.openWrite() : null;
final kernel2JsCompilers = await _bundler.compile(
results.classHierarchy,
results.coreTypes,
@@ -646,7 +653,8 @@
sourceFileSink,
manifestFileSink,
sourceMapsFileSink,
- metadataFileSink);
+ metadataFileSink,
+ symbolsFileSink);
cachedProgramCompilers.addAll(kernel2JsCompilers);
await Future.wait([
sourceFileSink.close(),
@@ -1346,7 +1354,8 @@
unsafePackageSerialization: options["unsafe-package-serialization"],
incrementalSerialization: options["incremental-serialization"],
useDebuggerModuleNames: options['debugger-module-names'],
- emitDebugMetadata: options['experimental-emit-debug-metadata']);
+ emitDebugMetadata: options['experimental-emit-debug-metadata'],
+ emitDebugSymbols: options['emit-debug-symbols']);
if (options.rest.isNotEmpty) {
return await compiler.compile(options.rest[0], options,
diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart
index 9829c57..a989fb1 100644
--- a/pkg/frontend_server/lib/src/javascript_bundle.dart
+++ b/pkg/frontend_server/lib/src/javascript_bundle.dart
@@ -27,6 +27,7 @@
this._fileSystemScheme, this._packageConfig,
{this.useDebuggerModuleNames = false,
this.emitDebugMetadata = false,
+ this.emitDebugSymbols = false,
this.soundNullSafety = false,
String moduleFormat})
: _moduleFormat = parseModuleFormat(moduleFormat ?? 'amd') {
@@ -63,6 +64,7 @@
final PackageConfig _packageConfig;
final bool useDebuggerModuleNames;
final bool emitDebugMetadata;
+ final bool emitDebugSymbols;
final ModuleFormat _moduleFormat;
final bool soundNullSafety;
@@ -74,16 +76,19 @@
/// Compile each component into a single JavaScript module.
Future<Map<String, ProgramCompiler>> compile(
- ClassHierarchy classHierarchy,
- CoreTypes coreTypes,
- Set<Library> loadedLibraries,
- IOSink codeSink,
- IOSink manifestSink,
- IOSink sourceMapsSink,
- IOSink metadataSink) async {
+ ClassHierarchy classHierarchy,
+ CoreTypes coreTypes,
+ Set<Library> loadedLibraries,
+ IOSink codeSink,
+ IOSink manifestSink,
+ IOSink sourceMapsSink,
+ IOSink metadataSink,
+ IOSink symbolsSink,
+ ) async {
var codeOffset = 0;
var sourceMapOffset = 0;
var metadataOffset = 0;
+ var symbolsOffset = 0;
final manifest = <String, Map<String, List<int>>>{};
final Set<Uri> visited = <Uri>{};
final Map<String, ProgramCompiler> kernel2JsCompilers = {};
@@ -135,6 +140,7 @@
sourceMap: true,
summarizeApi: false,
emitDebugMetadata: emitDebugMetadata,
+ emitDebugSymbols: emitDebugSymbols,
moduleName: moduleName,
soundNullSafety: soundNullSafety,
),
@@ -145,10 +151,6 @@
final jsModule = compiler.emitModule(summaryComponent);
- // TODO:(annagrin): create symbol tables and pass to expression compiler
- // so it can map dart symbols to js symbols
- // [issue 40273](https://github.com/dart-lang/sdk/issues/40273)
-
// Save program compiler to reuse for expression evaluation.
kernel2JsCompilers[moduleName] = compiler;
@@ -168,22 +170,29 @@
inlineSourceMap: true,
buildSourceMap: true,
emitDebugMetadata: emitDebugMetadata,
+ emitDebugSymbols: emitDebugSymbols,
jsUrl: '$moduleUrl.lib.js',
mapUrl: '$moduleUrl.lib.js.map',
sourceMapBase: sourceMapBase,
customScheme: _fileSystemScheme,
+ compiler: compiler,
component: summaryComponent,
);
final codeBytes = utf8.encode(code.code);
final sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
final metadataBytes =
emitDebugMetadata ? utf8.encode(json.encode(code.metadata)) : null;
+ final symbolsBytes =
+ emitDebugSymbols ? utf8.encode(json.encode(code.symbols)) : null;
codeSink.add(codeBytes);
sourceMapsSink.add(sourceMapBytes);
if (emitDebugMetadata) {
metadataSink.add(metadataBytes);
}
+ if (emitDebugSymbols) {
+ symbolsSink.add(symbolsBytes);
+ }
final String moduleKey = _moduleImportForSummary[moduleUri];
manifest[moduleKey] = {
'code': <int>[codeOffset, codeOffset += codeBytes.length],
@@ -196,6 +205,11 @@
metadataOffset,
metadataOffset += metadataBytes.length
],
+ if (emitDebugSymbols)
+ 'symbols': <int>[
+ symbolsOffset,
+ symbolsOffset += symbolsBytes.length,
+ ],
};
}
manifestSink.add(utf8.encode(json.encode(manifest)));
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index ee69ecb..8205380 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -1979,12 +1979,14 @@
var manifestFile = File('${dillFile.path}.json');
var sourceMapsFile = File('${dillFile.path}.map');
var metadataFile = File('${dillFile.path}.metadata');
+ var symbolsFile = File('${dillFile.path}.symbols');
expect(dillFile.existsSync(), false);
expect(sourceFile.existsSync(), false);
expect(manifestFile.existsSync(), false);
expect(sourceMapsFile.existsSync(), false);
expect(metadataFile.existsSync(), false);
+ expect(symbolsFile.existsSync(), false);
final List<String> args = <String>[
'--sdk-root=${sdkRoot.toFilePath()}',
@@ -1994,6 +1996,7 @@
'--target=dartdevc',
'--packages=${package_config.path}',
'--experimental-emit-debug-metadata',
+ '--emit-debug-symbols',
];
final StreamController<List<int>> streamController =
@@ -2022,6 +2025,7 @@
expect(manifestFile.existsSync(), equals(true));
expect(sourceMapsFile.existsSync(), equals(true));
expect(metadataFile.existsSync(), equals(true));
+ expect(symbolsFile.existsSync(), equals(true));
expect(result.filename, dillFile.path);
streamController.add('accept\n'.codeUnits);
outputParser.expectSources = false;
diff --git a/pkg/frontend_server/test/src/javascript_bundle_test.dart b/pkg/frontend_server/test/src/javascript_bundle_test.dart
index 898cbcc..d927f82 100644
--- a/pkg/frontend_server/test/src/javascript_bundle_test.dart
+++ b/pkg/frontend_server/test/src/javascript_bundle_test.dart
@@ -111,16 +111,19 @@
final codeSink = _MemorySink();
final sourcemapSink = _MemorySink();
final metadataSink = _MemorySink();
+ final symbolsSink = _MemorySink();
final coreTypes = CoreTypes(testComponent);
final compilers = await javaScriptBundler.compile(
- ClassHierarchy(testComponent, coreTypes),
- coreTypes,
- {},
- codeSink,
- manifestSink,
- sourcemapSink,
- metadataSink);
+ ClassHierarchy(testComponent, coreTypes),
+ coreTypes,
+ {},
+ codeSink,
+ manifestSink,
+ sourcemapSink,
+ metadataSink,
+ symbolsSink,
+ );
final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
final String code = utf8.decode(codeSink.buffer);
@@ -162,10 +165,19 @@
final codeSink = _MemorySink();
final sourcemapSink = _MemorySink();
final metadataSink = _MemorySink();
+ final symbolsSink = _MemorySink();
final coreTypes = CoreTypes(testComponent);
- await javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes),
- coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink);
+ await javaScriptBundler.compile(
+ ClassHierarchy(testComponent, coreTypes),
+ coreTypes,
+ {},
+ codeSink,
+ manifestSink,
+ sourcemapSink,
+ metadataSink,
+ symbolsSink,
+ );
final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
final String code = utf8.decode(codeSink.buffer);
@@ -204,10 +216,19 @@
final codeSink = _MemorySink();
final sourcemapSink = _MemorySink();
final metadataSink = _MemorySink();
+ final symbolsSink = _MemorySink();
final coreTypes = CoreTypes(testComponent);
- await javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes),
- coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink);
+ await javaScriptBundler.compile(
+ ClassHierarchy(testComponent, coreTypes),
+ coreTypes,
+ {},
+ codeSink,
+ manifestSink,
+ sourcemapSink,
+ metadataSink,
+ symbolsSink,
+ );
final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
final String code = utf8.decode(codeSink.buffer);
@@ -256,10 +277,19 @@
final codeSink = _MemorySink();
final sourcemapSink = _MemorySink();
final metadataSink = _MemorySink();
+ final symbolsSink = _MemorySink();
final coreTypes = CoreTypes(testComponent);
- javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes),
- coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink);
+ javaScriptBundler.compile(
+ ClassHierarchy(testComponent, coreTypes),
+ coreTypes,
+ {},
+ codeSink,
+ manifestSink,
+ sourcemapSink,
+ metadataSink,
+ symbolsSink,
+ );
final code = utf8.decode(codeSink.buffer);
final manifest = json.decode(utf8.decode(manifestSink.buffer));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
index 084a1d5..4720666 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
@@ -27,8 +27,8 @@
} =>#t1;
final typ::Uint8List* buffer = [@vm.direct-call.metadata=protobuf::GeneratedMessage.writeToBuffer] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] foo.{pro::GeneratedMessage::writeToBuffer}(){() →* typ::Uint8List*};
core::print("List<int> buffer = <int>[");
- for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=dart.typed_data::_TypedList.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*}) {
- final core::String* numbers = [@vm.direct-call.metadata=dart.typed_data::_TypedListBase.join] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=dart.typed_data::__Uint8List&_TypedList&_IntListMixin&_TypedIntListMixin.sublist] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] buffer.{typ::Uint8List::sublist}(i, [@vm.inferred-type.metadata=int] math::min<core::int*>([@vm.direct-call.metadata=dart.typed_data::_TypedList.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}, [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*})){(core::int*, [core::int*]) →* typ::Uint8List*}.{core::Iterable::join}(", "){([core::String*]) →* core::String*};
+ for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*}) {
+ final core::String* numbers = [@vm.direct-call.metadata=dart.typed_data::_TypedListBase.join] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=dart.typed_data::__Uint8List&_TypedList&_IntListMixin&_TypedIntListMixin.sublist] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] buffer.{typ::Uint8List::sublist}(i, [@vm.inferred-type.metadata=int] math::min<core::int*>([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}, [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*})){(core::int*, [core::int*]) →* typ::Uint8List*}.{core::Iterable::join}(", "){([core::String*]) →* core::String*};
core::print(" ${numbers},${[@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i =={core::num::==}{(core::Object*) →* core::bool*} 0 ?{core::String*} " //" : ""}");
}
core::print("];");
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 93b086d..129caeb 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -114,11 +114,23 @@
const Class& cls = Class::Handle(left.clazz());
if (cls.IsClosureClass()) {
- // TODO(vegorov): provide faster implementation for closure classes.
+ const Function& left_function =
+ Function::Handle(zone, Closure::Cast(left).function());
+ const Function& right_function =
+ Function::Handle(zone, Closure::Cast(right).function());
+ if (left_function.signature() == right_function.signature() &&
+ Closure::Cast(left).function_type_arguments() ==
+ Closure::Cast(right).function_type_arguments() &&
+ Closure::Cast(left).delayed_type_arguments() ==
+ Closure::Cast(right).delayed_type_arguments() &&
+ Closure::Cast(left).instantiator_type_arguments() ==
+ Closure::Cast(right).instantiator_type_arguments()) {
+ return Bool::True().ptr();
+ }
const AbstractType& left_type =
- AbstractType::Handle(left.GetType(Heap::kNew));
+ AbstractType::Handle(zone, left.GetType(Heap::kNew));
const AbstractType& right_type =
- AbstractType::Handle(right.GetType(Heap::kNew));
+ AbstractType::Handle(zone, right.GetType(Heap::kNew));
return Bool::Get(
left_type.IsEquivalent(right_type, TypeEquality::kSyntactical))
.ptr();
@@ -132,9 +144,9 @@
return Bool::True().ptr();
}
const TypeArguments& left_type_arguments =
- TypeArguments::Handle(left.GetTypeArguments());
+ TypeArguments::Handle(zone, left.GetTypeArguments());
const TypeArguments& right_type_arguments =
- TypeArguments::Handle(right.GetTypeArguments());
+ TypeArguments::Handle(zone, right.GetTypeArguments());
const intptr_t num_type_args = cls.NumTypeArguments();
const intptr_t num_type_params = cls.NumTypeParameters();
return Bool::Get(left_type_arguments.IsSubvectorEquivalent(
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 4e1fc80..996d92d 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -322,57 +322,28 @@
intptr_t start = start_obj.Value();
intptr_t end = end_obj.Value();
if (start < 0) {
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, start_obj);
- Exceptions::ThrowByType(Exceptions::kArgument, args);
+ Exceptions::ThrowArgumentError(start_obj);
}
intptr_t length = end - start;
if (length < 0) {
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, end_obj);
- Exceptions::ThrowByType(Exceptions::kArgument, args);
+ Exceptions::ThrowArgumentError(end_obj);
}
ASSERT(length >= 0);
Heap::Space space = Heap::kNew;
- if (list.IsTypedData()) {
- const TypedData& array = TypedData::Cast(list);
- if (end > array.LengthInBytes()) {
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, end_obj);
- Exceptions::ThrowByType(Exceptions::kArgument, args);
+ if (list.IsTypedDataBase()) {
+ const TypedDataBase& array = TypedDataBase::Cast(list);
+ if (array.ElementType() != kUint8ArrayElement) {
+ Exceptions::ThrowArgumentError(list);
+ }
+ if (end > array.Length()) {
+ Exceptions::ThrowArgumentError(end_obj);
}
return OneByteString::New(array, start, length, space);
- } else if (list.IsExternalTypedData()) {
- const ExternalTypedData& array = ExternalTypedData::Cast(list);
- if (end > array.LengthInBytes()) {
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, end_obj);
- Exceptions::ThrowByType(Exceptions::kArgument, args);
- }
- return OneByteString::New(array, start, length, space);
- } else if (list.IsTypedDataView()) {
- const auto& view = TypedDataView::Cast(list);
- if (end > Smi::Value(view.length())) {
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, end_obj);
- Exceptions::ThrowByType(Exceptions::kArgument, args);
- }
- const Instance& data_obj = Instance::Handle(view.typed_data());
- intptr_t data_offset = Smi::Value(view.offset_in_bytes());
- if (data_obj.IsTypedData()) {
- const TypedData& array = TypedData::Cast(data_obj);
- return OneByteString::New(array, data_offset + start, length, space);
- } else if (data_obj.IsExternalTypedData()) {
- const ExternalTypedData& array = ExternalTypedData::Cast(data_obj);
- return OneByteString::New(array, data_offset + start, length, space);
- }
} else if (list.IsArray()) {
const Array& array = Array::Cast(list);
if (end > array.Length()) {
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, end_obj);
- Exceptions::ThrowByType(Exceptions::kArgument, args);
+ Exceptions::ThrowArgumentError(end_obj);
}
String& string = String::Handle(OneByteString::New(length, space));
for (int i = 0; i < length; i++) {
@@ -383,9 +354,7 @@
} else if (list.IsGrowableObjectArray()) {
const GrowableObjectArray& array = GrowableObjectArray::Cast(list);
if (end > array.Length()) {
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, end_obj);
- Exceptions::ThrowByType(Exceptions::kArgument, args);
+ Exceptions::ThrowArgumentError(end_obj);
}
String& string = String::Handle(OneByteString::New(length, space));
for (int i = 0; i < length; i++) {
@@ -434,8 +403,8 @@
}
Heap::Space space = Heap::kNew;
- if (list.IsTypedData()) {
- const TypedData& array = TypedData::Cast(list);
+ if (list.IsTypedDataBase()) {
+ const TypedDataBase& array = TypedDataBase::Cast(list);
if (array.ElementType() != kUint16ArrayElement) {
Exceptions::ThrowArgumentError(list);
}
@@ -443,35 +412,6 @@
Exceptions::ThrowArgumentError(end_obj);
}
return TwoByteString::New(array, start * sizeof(uint16_t), length, space);
- } else if (list.IsExternalTypedData()) {
- const ExternalTypedData& array = ExternalTypedData::Cast(list);
- if (array.ElementType() != kUint16ArrayElement) {
- Exceptions::ThrowArgumentError(list);
- }
- if (end > array.Length()) {
- Exceptions::ThrowArgumentError(end_obj);
- }
- return TwoByteString::New(array, start * sizeof(uint16_t), length, space);
- } else if (IsTypedDataViewClassId(list.GetClassId())) {
- const auto& view = TypedDataView::Cast(list);
- const intptr_t cid = list.GetClassId();
- if (cid != kTypedDataUint16ArrayViewCid) {
- Exceptions::ThrowArgumentError(list);
- }
- if (end > Smi::Value(view.length())) {
- Exceptions::ThrowArgumentError(end_obj);
- }
- const auto& data_obj = Instance::Handle(zone, view.typed_data());
- const intptr_t data_offset = Smi::Value(view.offset_in_bytes());
- if (data_obj.IsTypedData()) {
- const TypedData& array = TypedData::Cast(data_obj);
- return TwoByteString::New(array, data_offset + start * sizeof(uint16_t),
- length, space);
- } else if (data_obj.IsExternalTypedData()) {
- const ExternalTypedData& array = ExternalTypedData::Cast(data_obj);
- return TwoByteString::New(array, data_offset + start * sizeof(uint16_t),
- length, space);
- }
} else if (list.IsArray()) {
const Array& array = Array::Cast(list);
if (end > array.Length()) {
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index 28d9331..eb21c47 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -47,20 +47,9 @@
}
}
-DEFINE_NATIVE_ENTRY(TypedData_length, 0, 1) {
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
- if (instance.IsTypedData()) {
- const TypedData& array = TypedData::Cast(instance);
- return Smi::New(array.Length());
- }
- if (instance.IsExternalTypedData()) {
- const ExternalTypedData& array = ExternalTypedData::Cast(instance);
- return Smi::New(array.Length());
- }
- const String& error = String::Handle(String::NewFormatted(
- "Expected a TypedData object but found %s", instance.ToCString()));
- Exceptions::ThrowArgumentError(error);
- return Integer::null();
+DEFINE_NATIVE_ENTRY(TypedDataBase_length, 0, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, array, arguments->NativeArgAt(0));
+ return Smi::New(array.Length());
}
DEFINE_NATIVE_ENTRY(TypedDataView_offsetInBytes, 0, 1) {
@@ -70,13 +59,6 @@
return TypedDataView::Cast(instance).offset_in_bytes();
}
-DEFINE_NATIVE_ENTRY(TypedDataView_length, 0, 1) {
- // "this" is either a _*ArrayView class or _ByteDataView.
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
- ASSERT(instance.IsTypedDataView());
- return TypedDataView::Cast(instance).length();
-}
-
DEFINE_NATIVE_ENTRY(TypedDataView_typedData, 0, 1) {
// "this" is either a _*ArrayView class or _ByteDataView.
GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
@@ -84,15 +66,12 @@
return TypedDataView::Cast(instance).typed_data();
}
-template <typename DstType, typename SrcType>
-static BoolPtr CopyData(const Instance& dst,
- const Instance& src,
+static BoolPtr CopyData(const TypedDataBase& dst_array,
+ const TypedDataBase& src_array,
const Smi& dst_start,
const Smi& src_start,
const Smi& length,
bool clamped) {
- const DstType& dst_array = DstType::Cast(dst);
- const SrcType& src_array = SrcType::Cast(src);
const intptr_t dst_offset_in_bytes = dst_start.Value();
const intptr_t src_offset_in_bytes = src_start.Value();
const intptr_t length_in_bytes = length.Value();
@@ -101,12 +80,11 @@
ASSERT(Utils::RangeCheck(dst_offset_in_bytes, length_in_bytes,
dst_array.LengthInBytes()));
if (clamped) {
- TypedData::ClampedCopy<DstType, SrcType>(dst_array, dst_offset_in_bytes,
- src_array, src_offset_in_bytes,
- length_in_bytes);
+ TypedData::ClampedCopy(dst_array, dst_offset_in_bytes, src_array,
+ src_offset_in_bytes, length_in_bytes);
} else {
- TypedData::Copy<DstType, SrcType>(dst_array, dst_offset_in_bytes, src_array,
- src_offset_in_bytes, length_in_bytes);
+ TypedData::Copy(dst_array, dst_offset_in_bytes, src_array,
+ src_offset_in_bytes, length_in_bytes);
}
return Bool::True().ptr();
}
@@ -136,13 +114,13 @@
}
}
-DEFINE_NATIVE_ENTRY(TypedData_setRange, 0, 7) {
- const Instance& dst =
- Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(TypedDataBase_setRange, 0, 7) {
+ const TypedDataBase& dst =
+ TypedDataBase::CheckedHandle(zone, arguments->NativeArgAt(0));
const Smi& dst_start = Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
const Smi& length = Smi::CheckedHandle(zone, arguments->NativeArgAt(2));
- const Instance& src =
- Instance::CheckedHandle(zone, arguments->NativeArgAt(3));
+ const TypedDataBase& src =
+ TypedDataBase::CheckedHandle(zone, arguments->NativeArgAt(3));
const Smi& src_start = Smi::CheckedHandle(zone, arguments->NativeArgAt(4));
const Smi& to_cid_smi = Smi::CheckedHandle(zone, arguments->NativeArgAt(5));
const Smi& from_cid_smi = Smi::CheckedHandle(zone, arguments->NativeArgAt(6));
@@ -156,25 +134,7 @@
const intptr_t from_cid = from_cid_smi.Value();
const bool needs_clamping = IsClamped(to_cid) && !IsUint8(from_cid);
- if (dst.IsTypedData()) {
- if (src.IsTypedData()) {
- return CopyData<TypedData, TypedData>(dst, src, dst_start, src_start,
- length, needs_clamping);
- } else if (src.IsExternalTypedData()) {
- return CopyData<TypedData, ExternalTypedData>(
- dst, src, dst_start, src_start, length, needs_clamping);
- }
- } else if (dst.IsExternalTypedData()) {
- if (src.IsTypedData()) {
- return CopyData<ExternalTypedData, TypedData>(
- dst, src, dst_start, src_start, length, needs_clamping);
- } else if (src.IsExternalTypedData()) {
- return CopyData<ExternalTypedData, ExternalTypedData>(
- dst, src, dst_start, src_start, length, needs_clamping);
- }
- }
- UNREACHABLE();
- return Bool::False().ptr();
+ return CopyData(dst, src, dst_start, src_start, length, needs_clamping);
}
// Native methods for typed data allocation are recognized and implemented
@@ -203,19 +163,26 @@
// into a _Smi.
//
// Argument 0 is type arguments and is ignored.
+static InstancePtr NewTypedDataView(intptr_t cid,
+ intptr_t element_size,
+ Zone* zone,
+ NativeArguments* arguments) {
+ GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, typed_data,
+ arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, offset, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, len, arguments->NativeArgAt(3));
+ const intptr_t backing_length = typed_data.LengthInBytes();
+ const intptr_t offset_in_bytes = offset.Value();
+ const intptr_t length = len.Value();
+ AlignmentCheck(offset_in_bytes, element_size);
+ LengthCheck(offset_in_bytes + length * element_size, backing_length);
+ return TypedDataView::New(cid, typed_data, offset_in_bytes, length);
+}
+
#define TYPED_DATA_VIEW_NEW(native_name, cid) \
DEFINE_NATIVE_ENTRY(native_name, 0, 4) { \
- GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, typed_data, \
- arguments->NativeArgAt(1)); \
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, offset, arguments->NativeArgAt(2)); \
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, len, arguments->NativeArgAt(3)); \
- const intptr_t backing_length = typed_data.LengthInBytes(); \
- const intptr_t offset_in_bytes = offset.Value(); \
- const intptr_t length = len.Value(); \
- const intptr_t element_size = TypedDataBase::ElementSizeInBytes(cid); \
- AlignmentCheck(offset_in_bytes, element_size); \
- LengthCheck(offset_in_bytes + length * element_size, backing_length); \
- return TypedDataView::New(cid, typed_data, offset_in_bytes, length); \
+ return NewTypedDataView(cid, TypedDataBase::ElementSizeInBytes(cid), zone, \
+ arguments); \
}
#define TYPED_DATA_NEW_NATIVE(name) \
@@ -228,53 +195,27 @@
#define TYPED_DATA_GETTER(getter, object, ctor, access_size) \
DEFINE_NATIVE_ENTRY(TypedData_##getter, 0, 2) { \
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, \
+ GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, array, \
arguments->NativeArgAt(0)); \
GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, \
arguments->NativeArgAt(1)); \
- if (instance.IsTypedData()) { \
- const TypedData& array = TypedData::Cast(instance); \
- RangeCheck(offsetInBytes.Value(), access_size, array.LengthInBytes(), \
- access_size); \
- return object::ctor(array.getter(offsetInBytes.Value())); \
- } \
- if (instance.IsExternalTypedData()) { \
- const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
- RangeCheck(offsetInBytes.Value(), access_size, array.LengthInBytes(), \
- access_size); \
- return object::ctor(array.getter(offsetInBytes.Value())); \
- } \
- const String& error = String::Handle(String::NewFormatted( \
- "Expected a TypedData object but found %s", instance.ToCString())); \
- Exceptions::ThrowArgumentError(error); \
- return object::null(); \
+ RangeCheck(offsetInBytes.Value(), access_size, array.LengthInBytes(), \
+ access_size); \
+ return object::ctor(array.getter(offsetInBytes.Value())); \
}
#define TYPED_DATA_SETTER(setter, object, get_object_value, access_size, \
access_type) \
DEFINE_NATIVE_ENTRY(TypedData_##setter, 0, 3) { \
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, \
+ GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, array, \
arguments->NativeArgAt(0)); \
GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, \
arguments->NativeArgAt(1)); \
GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \
- if (instance.IsTypedData()) { \
- const TypedData& array = TypedData::Cast(instance); \
- RangeCheck(offsetInBytes.Value(), access_size, array.LengthInBytes(), \
- access_size); \
- array.setter(offsetInBytes.Value(), \
- static_cast<access_type>(value.get_object_value())); \
- } else if (instance.IsExternalTypedData()) { \
- const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
- RangeCheck(offsetInBytes.Value(), access_size, array.LengthInBytes(), \
- access_size); \
- array.setter(offsetInBytes.Value(), \
- static_cast<access_type>(value.get_object_value())); \
- } else { \
- const String& error = String::Handle(String::NewFormatted( \
- "Expected a TypedData object but found %s", instance.ToCString())); \
- Exceptions::ThrowArgumentError(error); \
- } \
+ RangeCheck(offsetInBytes.Value(), access_size, array.LengthInBytes(), \
+ access_size); \
+ array.setter(offsetInBytes.Value(), \
+ static_cast<access_type>(value.get_object_value())); \
return Object::null(); \
}
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 5237e60..359d482 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -190,8 +190,8 @@
V(TypedData_Float32x4Array_new, 2) \
V(TypedData_Int32x4Array_new, 2) \
V(TypedData_Float64x2Array_new, 2) \
- V(TypedData_length, 1) \
- V(TypedData_setRange, 7) \
+ V(TypedDataBase_length, 1) \
+ V(TypedDataBase_setRange, 7) \
V(TypedData_GetInt8, 2) \
V(TypedData_SetInt8, 3) \
V(TypedData_GetUint8, 2) \
@@ -233,7 +233,6 @@
V(TypedDataView_Float32x4ArrayView_new, 4) \
V(TypedDataView_Int32x4ArrayView_new, 4) \
V(TypedDataView_Float64x2ArrayView_new, 4) \
- V(TypedDataView_length, 1) \
V(TypedDataView_offsetInBytes, 1) \
V(TypedDataView_typedData, 1) \
V(Float32x4_fromDoubles, 4) \
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index 2cfe3ad..f41c51d 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -1198,6 +1198,14 @@
kIfNotInRange, target);
}
+static void JumpIfType(Assembler* assembler,
+ Register cid,
+ Register tmp,
+ Label* target) {
+ RangeCheck(assembler, cid, tmp, kTypeCid, kFunctionTypeCid, kIfInRange,
+ target);
+}
+
static void JumpIfNotType(Assembler* assembler,
Register cid,
Register tmp,
@@ -1272,7 +1280,7 @@
Register cid1,
Register cid2,
Register scratch) {
- Label different_cids, not_integer;
+ Label different_cids, not_integer, not_integer_or_string;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ CompareImmediate(cid1, kClosureCid);
@@ -1295,7 +1303,7 @@
__ b(equal);
// Class ids are different. Check if we are comparing two string types (with
- // different representations) or two integer types.
+ // different representations) or two integer types or two type types.
__ Bind(&different_cids);
__ CompareImmediate(cid1, kNumPredefinedCids);
__ b(not_equal, HI);
@@ -1304,20 +1312,29 @@
JumpIfNotInteger(assembler, cid1, scratch, ¬_integer);
// First type is an integer. Check if the second is an integer too.
- // Otherwise types are unequiv because only integers have the same runtime
- // type as other integers.
JumpIfInteger(assembler, cid2, scratch, equal);
+ // Integer types are only equivalent to other integer types.
__ b(not_equal);
__ Bind(¬_integer);
- // Check if the first type is String. If it is not then types are not
- // equivalent because they have different class ids and they are not strings
- // or integers.
- JumpIfNotString(assembler, cid1, scratch, not_equal);
+ // Check if both are String types.
+ JumpIfNotString(assembler, cid1, scratch, ¬_integer_or_string);
+
// First type is String. Check if the second is a string too.
JumpIfString(assembler, cid2, scratch, equal);
// String types are only equivalent to other String types.
__ b(not_equal);
+
+ __ Bind(¬_integer_or_string);
+ // Check if the first type is a Type. If it is not then types are not
+ // equivalent because they have different class ids and they are not String
+ // or integer or Type.
+ JumpIfNotType(assembler, cid1, scratch, not_equal);
+
+ // First type is a Type. Check if the second is a Type too.
+ JumpIfType(assembler, cid2, scratch, equal);
+ // Type types are only equivalent to other Type types.
+ __ b(not_equal);
}
void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index cf58e60..5749365 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -1340,6 +1340,14 @@
kIfNotInRange, target);
}
+static void JumpIfType(Assembler* assembler,
+ Register cid,
+ Register tmp,
+ Label* target) {
+ RangeCheck(assembler, cid, tmp, kTypeCid, kFunctionTypeCid, kIfInRange,
+ target);
+}
+
static void JumpIfNotType(Assembler* assembler,
Register cid,
Register tmp,
@@ -1418,7 +1426,7 @@
Register cid1,
Register cid2,
Register scratch) {
- Label different_cids, not_integer;
+ Label different_cids, not_integer, not_integer_or_string;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ CompareImmediate(cid1, kClosureCid);
@@ -1442,7 +1450,7 @@
__ b(equal);
// Class ids are different. Check if we are comparing two string types (with
- // different representations) or two integer types.
+ // different representations) or two integer types or two type types.
__ Bind(&different_cids);
__ CompareImmediate(cid1, kNumPredefinedCids);
__ b(not_equal, HI);
@@ -1451,20 +1459,28 @@
JumpIfNotInteger(assembler, cid1, scratch, ¬_integer);
// First type is an integer. Check if the second is an integer too.
- // Otherwise types are unequiv because only integers have the same runtime
- // type as other integers.
JumpIfInteger(assembler, cid2, scratch, equal);
+ // Integer types are only equivalent to other integer types.
__ b(not_equal);
__ Bind(¬_integer);
- // Check if the first type is String. If it is not then types are not
- // equivalent because they have different class ids and they are not strings
- // or integers.
- JumpIfNotString(assembler, cid1, scratch, not_equal);
+ // Check if both are String types.
+ JumpIfNotString(assembler, cid1, scratch, ¬_integer_or_string);
+
// First type is String. Check if the second is a string too.
JumpIfString(assembler, cid2, scratch, equal);
// String types are only equivalent to other String types.
- // Fall-through to the not equal case.
+ __ b(not_equal);
+
+ __ Bind(¬_integer_or_string);
+ // Check if the first type is a Type. If it is not then types are not
+ // equivalent because they have different class ids and they are not String
+ // or integer or Type.
+ JumpIfNotType(assembler, cid1, scratch, not_equal);
+
+ // First type is a Type. Check if the second is a Type too.
+ JumpIfType(assembler, cid2, scratch, equal);
+ // Type types are only equivalent to other Type types.
__ b(not_equal);
}
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index a52f0ab..5909eab 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -1281,6 +1281,10 @@
kIfNotInRange, target);
}
+static void JumpIfType(Assembler* assembler, Register cid, Label* target) {
+ RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfInRange, target);
+}
+
static void JumpIfNotType(Assembler* assembler, Register cid, Label* target) {
RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfNotInRange, target);
}
@@ -1362,7 +1366,7 @@
Register cid1,
Register cid2,
Register scratch) {
- Label different_cids, not_integer;
+ Label different_cids, not_integer, not_integer_or_string;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ cmpl(cid1, Immediate(kClosureCid));
@@ -1381,11 +1385,11 @@
__ movzxw(scratch,
FieldAddress(scratch, target::Class::num_type_arguments_offset()));
__ cmpl(scratch, Immediate(0));
- __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
+ __ j(NOT_EQUAL, normal_ir_body);
__ jmp(equal);
// Class ids are different. Check if we are comparing two string types (with
- // different representations) or two integer types.
+ // different representations) or two integer types or two type types.
__ Bind(&different_cids);
__ cmpl(cid1, Immediate(kNumPredefinedCids));
__ j(ABOVE_EQUAL, not_equal);
@@ -1395,20 +1399,29 @@
JumpIfNotInteger(assembler, scratch, ¬_integer);
// First type is an integer. Check if the second is an integer too.
- // Otherwise types are unequiv because only integers have the same runtime
- // type as other integers.
JumpIfInteger(assembler, cid2, equal);
+ // Integer types are only equivalent to other integer types.
__ jmp(not_equal);
__ Bind(¬_integer);
- // Check if the first type is String. If it is not then types are not
- // equivalent because they have different class ids and they are not strings
- // or integers.
- JumpIfNotString(assembler, cid1, not_equal);
- // First type is String. Check if the second is a string too.
+ // Check if both are String types.
+ JumpIfNotString(assembler, cid1, ¬_integer_or_string);
+
+ // First type is a String. Check if the second is a String too.
JumpIfString(assembler, cid2, equal);
// String types are only equivalent to other String types.
__ jmp(not_equal);
+
+ __ Bind(¬_integer_or_string);
+ // Check if the first type is a Type. If it is not then types are not
+ // equivalent because they have different class ids and they are not String
+ // or integer or Type.
+ JumpIfNotType(assembler, cid1, not_equal);
+
+ // First type is a Type. Check if the second is a Type too.
+ JumpIfType(assembler, cid2, equal);
+ // Type types are only equivalent to other Type types.
+ __ jmp(not_equal);
}
void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index da97a49..f691931 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -1183,9 +1183,14 @@
kIfNotInRange, target);
}
+static void JumpIfType(Assembler* assembler, Register cid, Label* target) {
+ RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfInRange, target);
+}
+
static void JumpIfNotType(Assembler* assembler, Register cid, Label* target) {
RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfNotInRange, target);
}
+
// Return type quickly for simple types (not parameterized and not signature).
void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
Label* normal_ir_body) {
@@ -1265,7 +1270,7 @@
Register cid1,
Register cid2,
Register scratch) {
- Label different_cids, not_integer;
+ Label different_cids, not_integer, not_integer_or_string;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ cmpq(cid1, Immediate(kClosureCid));
@@ -1288,7 +1293,7 @@
__ jmp(equal);
// Class ids are different. Check if we are comparing two string types (with
- // different representations) or two integer types.
+ // different representations) or two integer types or two type types.
__ Bind(&different_cids);
__ cmpq(cid1, Immediate(kNumPredefinedCids));
__ j(ABOVE_EQUAL, not_equal);
@@ -1298,20 +1303,29 @@
JumpIfNotInteger(assembler, scratch, ¬_integer);
// First type is an integer. Check if the second is an integer too.
- // Otherwise types are unequiv because only integers have the same runtime
- // type as other integers.
JumpIfInteger(assembler, cid2, equal);
+ // Integer types are only equivalent to other integer types.
__ jmp(not_equal);
__ Bind(¬_integer);
- // Check if the first type is String. If it is not then types are not
- // equivalent because they have different class ids and they are not strings
- // or integers.
- JumpIfNotString(assembler, cid1, not_equal);
- // First type is String. Check if the second is a string too.
+ // Check if both are String types.
+ JumpIfNotString(assembler, cid1, ¬_integer_or_string);
+
+ // First type is a String. Check if the second is a String too.
JumpIfString(assembler, cid2, equal);
// String types are only equivalent to other String types.
__ jmp(not_equal);
+
+ __ Bind(¬_integer_or_string);
+ // Check if the first type is a Type. If it is not then types are not
+ // equivalent because they have different class ids and they are not String
+ // or integer or Type.
+ JumpIfNotType(assembler, cid1, not_equal);
+
+ // First type is a Type. Check if the second is a Type too.
+ JumpIfType(assembler, cid2, equal);
+ // Type types are only equivalent to other Type types.
+ __ jmp(not_equal);
}
void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index a3f7ea7..ab5f8aa 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -856,8 +856,7 @@
case MethodRecognizer::kGrowableArrayLength:
case MethodRecognizer::kObjectArrayLength:
case MethodRecognizer::kImmutableArrayLength:
- case MethodRecognizer::kTypedListLength:
- case MethodRecognizer::kTypedListViewLength:
+ case MethodRecognizer::kTypedListBaseLength:
case MethodRecognizer::kByteDataViewLength:
case MethodRecognizer::kByteDataViewOffsetInBytes:
case MethodRecognizer::kTypedDataViewOffsetInBytes:
@@ -1054,8 +1053,7 @@
body += LoadLocal(parsed_function_->RawParameterVariable(0));
body += LoadNativeField(Slot::Array_length());
break;
- case MethodRecognizer::kTypedListLength:
- case MethodRecognizer::kTypedListViewLength:
+ case MethodRecognizer::kTypedListBaseLength:
case MethodRecognizer::kByteDataViewLength:
ASSERT(function.NumParameters() == 1);
body += LoadLocal(parsed_function_->RawParameterVariable(0));
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index d0ca36b..49287d4 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -760,11 +760,7 @@
return BuildLoadField(flow_graph, Slot::String_length());
}
-bool GraphIntrinsifier::Build_TypedListLength(FlowGraph* flow_graph) {
- return BuildLoadField(flow_graph, Slot::TypedDataBase_length());
-}
-
-bool GraphIntrinsifier::Build_TypedListViewLength(FlowGraph* flow_graph) {
+bool GraphIntrinsifier::Build_TypedListBaseLength(FlowGraph* flow_graph) {
return BuildLoadField(flow_graph, Slot::TypedDataBase_length());
}
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 58d8c8b..d2a757a 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -318,8 +318,7 @@
V(_Int32x4List, []=, Int32x4ArraySetIndexed, 0x17a2cbc0) \
V(_Float64x2List, [], Float64x2ArrayGetIndexed, 0xea0577df) \
V(_Float64x2List, []=, Float64x2ArraySetIndexed, 0x8af8aa58) \
- V(_TypedList, get:length, TypedListLength, 0x5850f06b) \
- V(_TypedListView, get:length, TypedListViewLength, 0x5850f06b) \
+ V(_TypedListBase, get:length, TypedListBaseLength, 0x5850f06b) \
V(_ByteDataView, get:length, ByteDataViewLength, 0x5850f06b) \
V(_Float32x4, get:x, Float32x4ShuffleX, 0x3a398530) \
V(_Float32x4, get:y, Float32x4ShuffleY, 0x27cae053) \
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index f26d236..54be0aa 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -3211,8 +3211,8 @@
// Pass through errors.
return list;
}
- if (obj.IsTypedData()) {
- GET_LIST_LENGTH(Z, TypedData, obj, len);
+ if (obj.IsTypedDataBase()) {
+ GET_LIST_LENGTH(Z, TypedDataBase, obj, len);
}
if (obj.IsArray()) {
GET_LIST_LENGTH(Z, Array, obj, len);
@@ -3220,9 +3220,6 @@
if (obj.IsGrowableObjectArray()) {
GET_LIST_LENGTH(Z, GrowableObjectArray, obj, len);
}
- if (obj.IsExternalTypedData()) {
- GET_LIST_LENGTH(Z, ExternalTypedData, obj, len);
- }
CHECK_CALLBACK_STATE(T);
// Now check and handle a dart object that implements the List interface.
@@ -3464,63 +3461,22 @@
} \
return Api::NewError("Invalid length passed in to access array elements");
-template <typename T>
-static Dart_Handle CopyBytes(const T& array,
- intptr_t offset,
- uint8_t* native_array,
- intptr_t length) {
- ASSERT(array.ElementSizeInBytes() == 1);
- NoSafepointScope no_safepoint;
- memmove(native_array, reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
- length);
- return Api::Success();
-}
-
DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list,
intptr_t offset,
uint8_t* native_array,
intptr_t length) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
- if (obj.IsTypedData()) {
- const TypedData& array = TypedData::Cast(obj);
+ if (obj.IsTypedDataBase()) {
+ const TypedDataBase& array = TypedDataBase::Cast(obj);
if (array.ElementSizeInBytes() == 1) {
- if (!Utils::RangeCheck(offset, length, array.Length())) {
- return Api::NewError(
- "Invalid length passed in to access list elements");
+ if (Utils::RangeCheck(offset, length, array.Length())) {
+ NoSafepointScope no_safepoint;
+ memmove(native_array,
+ reinterpret_cast<uint8_t*>(array.DataAddr(offset)), length);
+ return Api::Success();
}
- return CopyBytes(array, offset, native_array, length);
- }
- }
- if (obj.IsExternalTypedData()) {
- const ExternalTypedData& external_array = ExternalTypedData::Cast(obj);
- if (external_array.ElementSizeInBytes() == 1) {
- if (!Utils::RangeCheck(offset, length, external_array.Length())) {
- return Api::NewError(
- "Invalid length passed in to access list elements");
- }
- return CopyBytes(external_array, offset, native_array, length);
- }
- }
- if (IsTypedDataViewClassId(obj.GetClassId())) {
- const auto& view = TypedDataView::Cast(obj);
- if (view.ElementSizeInBytes() == 1) {
- const intptr_t view_length = Smi::Value(view.length());
- if (!Utils::RangeCheck(offset, length, view_length)) {
- return Api::NewError(
- "Invalid length passed in to access list elements");
- }
- const auto& data = Instance::Handle(view.typed_data());
- if (data.IsTypedData()) {
- const TypedData& array = TypedData::Cast(data);
- if (array.ElementSizeInBytes() == 1) {
- const intptr_t data_offset =
- Smi::Value(view.offset_in_bytes()) + offset;
- // Range check already performed on the view object.
- ASSERT(Utils::RangeCheck(data_offset, length, array.Length()));
- return CopyBytes(array, data_offset, native_array, length);
- }
- }
+ return Api::NewError("Invalid length passed in to access list elements");
}
}
if (obj.IsArray()) {
@@ -3590,8 +3546,8 @@
intptr_t length) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
- if (obj.IsTypedData()) {
- const TypedData& array = TypedData::Cast(obj);
+ if (obj.IsTypedDataBase()) {
+ const TypedDataBase& array = TypedDataBase::Cast(obj);
if (array.ElementSizeInBytes() == 1) {
if (Utils::RangeCheck(offset, length, array.Length())) {
NoSafepointScope no_safepoint;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 4f333c6..a008f7b 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -5631,7 +5631,7 @@
TEST_CASE(DartAPI_New) {
const char* kScriptChars =
- "class MyClass {\n"
+ "class MyClass implements MyExtraHop {\n"
" MyClass() : foo = 7 {}\n"
" MyClass.named(value) : foo = value {}\n"
" MyClass._hidden(value) : foo = -value {}\n"
@@ -5644,7 +5644,7 @@
" var foo;\n"
"}\n"
"\n"
- "abstract class MyExtraHop {\n"
+ "abstract class MyExtraHop implements MyInterface {\n"
" factory MyExtraHop.hop(value) = MyClass.named;\n"
"}\n"
"\n"
@@ -5841,26 +5841,6 @@
result = Dart_New(type, NewString("exception"), 1, args);
EXPECT_ERROR(result, "ConstructorDeath");
- // Invoke two-hop redirecting factory constructor.
- result = Dart_New(intf, NewString("named"), 1, args);
- EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
- EXPECT(instanceOf);
- int_value = 0;
- foo = Dart_GetField(result, NewString("foo"));
- EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
- EXPECT_EQ(11, int_value);
-
- // Invoke one-hop redirecting factory constructor.
- result = Dart_New(intf, NewString("multiply"), 1, args);
- EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
- EXPECT(instanceOf);
- int_value = 0;
- foo = Dart_GetField(result, NewString("foo"));
- EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
- EXPECT_EQ(1100, int_value);
-
// Invoke a constructor that is missing in the interface.
result = Dart_New(intf, Dart_Null(), 0, NULL);
EXPECT_ERROR(result, "Dart_New: could not find constructor 'MyInterface.'.");
@@ -5872,6 +5852,71 @@
EXPECT(!instanceOf);
}
+// These two cases below currently fail because of issue
+// https://github.com/dart-lang/sdk/issues/42939
+TEST_CASE(DartAPI_New_Issue42939) {
+ const char* kScriptChars =
+ "class MyClass implements MyExtraHop {\n"
+ " MyClass() : foo = 7 {}\n"
+ " MyClass.named(value) : foo = value {}\n"
+ " MyClass._hidden(value) : foo = -value {}\n"
+ " MyClass.exception(value) : foo = value {\n"
+ " throw 'ConstructorDeath';\n"
+ " }\n"
+ " factory MyClass.multiply(value) {\n"
+ " return new MyClass.named(value * 100);\n"
+ " }\n"
+ " var foo;\n"
+ "}\n"
+ "\n"
+ "abstract class MyExtraHop implements MyInterface {\n"
+ " factory MyExtraHop.hop(value) = MyClass.named;\n"
+ "}\n"
+ "\n"
+ "abstract class MyInterface {\n"
+ " factory MyInterface.named(value) = MyExtraHop.hop;\n"
+ " factory MyInterface.multiply(value) = MyClass.multiply;\n"
+ " MyInterface.notfound(value);\n"
+ "}\n"
+ "\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ Dart_Handle type =
+ Dart_GetNonNullableType(lib, NewString("MyClass"), 0, NULL);
+ EXPECT_VALID(type);
+ Dart_Handle intf =
+ Dart_GetNonNullableType(lib, NewString("MyInterface"), 0, NULL);
+ EXPECT_VALID(intf);
+
+ Dart_Handle args[1];
+ args[0] = Dart_NewInteger(11);
+
+ // Invoke two-hop redirecting factory constructor.
+ bool instanceOf = false;
+ Dart_Handle result = Dart_New(intf, NewString("named"), 1, args);
+ EXPECT_VALID(result);
+ if (!Dart_IsError(result)) {
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
+ EXPECT(instanceOf);
+ int64_t int_value = 0;
+ Dart_Handle foo = Dart_GetField(result, NewString("foo"));
+ EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
+ EXPECT_EQ(11, int_value);
+ }
+
+ // Invoke one-hop redirecting factory constructor.
+ result = Dart_New(intf, NewString("multiply"), 1, args);
+ EXPECT_VALID(result);
+ if (!Dart_IsError(result)) {
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
+ EXPECT(instanceOf);
+ int64_t int_value = 0;
+ Dart_Handle foo = Dart_GetField(result, NewString("foo"));
+ EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
+ EXPECT_EQ(1100, int_value);
+ }
+}
+
TEST_CASE(DartAPI_New_Issue44205) {
const char* kScriptChars =
"class MyIntClass {\n"
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index cf4a20d..e153091 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -50,6 +50,7 @@
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/profiler.h"
+#include "vm/regexp.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
#include "vm/runtime_entry.h"
@@ -11103,8 +11104,7 @@
}
static intptr_t GetListLength(const Object& value) {
- if (value.IsTypedData() || value.IsTypedDataView() ||
- value.IsExternalTypedData()) {
+ if (value.IsTypedDataBase()) {
return TypedDataBase::Cast(value).Length();
} else if (value.IsArray()) {
return Array::Cast(value).Length();
@@ -23571,21 +23571,7 @@
return OneByteString::raw(result);
}
-OneByteStringPtr OneByteString::New(const TypedData& other_typed_data,
- intptr_t other_start_index,
- intptr_t other_len,
- Heap::Space space) {
- const String& result = String::Handle(OneByteString::New(other_len, space));
- ASSERT(other_typed_data.ElementSizeInBytes() == 1);
- if (other_len > 0) {
- NoSafepointScope no_safepoint;
- memmove(OneByteString::DataStart(result),
- other_typed_data.DataAddr(other_start_index), other_len);
- }
- return OneByteString::raw(result);
-}
-
-OneByteStringPtr OneByteString::New(const ExternalTypedData& other_typed_data,
+OneByteStringPtr OneByteString::New(const TypedDataBase& other_typed_data,
intptr_t other_start_index,
intptr_t other_len,
Heap::Space space) {
@@ -23765,21 +23751,7 @@
return TwoByteString::raw(result);
}
-TwoByteStringPtr TwoByteString::New(const TypedData& other_typed_data,
- intptr_t other_start_index,
- intptr_t other_len,
- Heap::Space space) {
- const String& result = String::Handle(TwoByteString::New(other_len, space));
- if (other_len > 0) {
- NoSafepointScope no_safepoint;
- memmove(TwoByteString::DataStart(result),
- other_typed_data.DataAddr(other_start_index),
- other_len * sizeof(uint16_t));
- }
- return TwoByteString::raw(result);
-}
-
-TwoByteStringPtr TwoByteString::New(const ExternalTypedData& other_typed_data,
+TwoByteStringPtr TwoByteString::New(const TypedDataBase& other_typed_data,
intptr_t other_start_index,
intptr_t other_len,
Heap::Space space) {
@@ -25049,7 +25021,7 @@
}
FunctionTypePtr Closure::GetInstantiatedSignature(Zone* zone) const {
- Function& fun = Function::Handle(zone, function());
+ const Function& fun = Function::Handle(zone, function());
FunctionType& sig = FunctionType::Handle(zone, fun.signature());
TypeArguments& fn_type_args =
TypeArguments::Handle(zone, function_type_arguments());
@@ -25518,7 +25490,7 @@
untag()->set_capture_name_map(array.ptr());
}
-RegExpPtr RegExp::New(Heap::Space space) {
+RegExpPtr RegExp::New(Zone* zone, Heap::Space space) {
RegExp& result = RegExp::Handle();
{
ObjectPtr raw =
@@ -25532,6 +25504,21 @@
result.set_num_registers(/*is_one_byte=*/false, -1);
result.set_num_registers(/*is_one_byte=*/true, -1);
}
+
+ if (!FLAG_interpret_irregexp) {
+ auto thread = Thread::Current();
+ const Library& lib = Library::Handle(zone, Library::CoreLibrary());
+ const Class& owner =
+ Class::Handle(zone, lib.LookupClass(Symbols::RegExp()));
+
+ for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid;
+ cid++) {
+ CreateSpecializedFunction(thread, zone, result, cid, /*sticky=*/false,
+ owner);
+ CreateSpecializedFunction(thread, zone, result, cid, /*sticky=*/true,
+ owner);
+ }
+ }
return result.ptr();
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index fe21539..105f60c 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -9486,12 +9486,7 @@
intptr_t other_len,
Heap::Space space);
- static OneByteStringPtr New(const TypedData& other_typed_data,
- intptr_t other_start_index,
- intptr_t other_len,
- Heap::Space space = Heap::kNew);
-
- static OneByteStringPtr New(const ExternalTypedData& other_typed_data,
+ static OneByteStringPtr New(const TypedDataBase& other_typed_data,
intptr_t other_start_index,
intptr_t other_len,
Heap::Space space = Heap::kNew);
@@ -9622,12 +9617,7 @@
Heap::Space space);
static TwoByteStringPtr New(const String& str, Heap::Space space);
- static TwoByteStringPtr New(const TypedData& other_typed_data,
- intptr_t other_start_index,
- intptr_t other_len,
- Heap::Space space = Heap::kNew);
-
- static TwoByteStringPtr New(const ExternalTypedData& other_typed_data,
+ static TwoByteStringPtr New(const TypedDataBase& other_typed_data,
intptr_t other_start_index,
intptr_t other_len,
Heap::Space space = Heap::kNew);
@@ -10408,6 +10398,32 @@
return reinterpret_cast<void*>(Validate(untag()->data_) + byte_offset);
}
+#define TYPED_GETTER_SETTER(name, type) \
+ type Get##name(intptr_t byte_offset) const { \
+ NoSafepointScope no_safepoint; \
+ return LoadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset))); \
+ } \
+ void Set##name(intptr_t byte_offset, type value) const { \
+ NoSafepointScope no_safepoint; \
+ StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value); \
+ }
+
+ TYPED_GETTER_SETTER(Int8, int8_t)
+ TYPED_GETTER_SETTER(Uint8, uint8_t)
+ TYPED_GETTER_SETTER(Int16, int16_t)
+ TYPED_GETTER_SETTER(Uint16, uint16_t)
+ TYPED_GETTER_SETTER(Int32, int32_t)
+ TYPED_GETTER_SETTER(Uint32, uint32_t)
+ TYPED_GETTER_SETTER(Int64, int64_t)
+ TYPED_GETTER_SETTER(Uint64, uint64_t)
+ TYPED_GETTER_SETTER(Float32, float)
+ TYPED_GETTER_SETTER(Float64, double)
+ TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
+ TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
+ TYPED_GETTER_SETTER(Float64x2, simd128_value_t)
+
+#undef TYPED_GETTER_SETTER
+
protected:
void SetLength(intptr_t value) const {
ASSERT(value <= Smi::kMaxValue);
@@ -10500,10 +10516,9 @@
intptr_t len,
Heap::Space space = Heap::kNew);
- template <typename DstType, typename SrcType>
- static void Copy(const DstType& dst,
+ static void Copy(const TypedDataBase& dst,
intptr_t dst_offset_in_bytes,
- const SrcType& src,
+ const TypedDataBase& src,
intptr_t src_offset_in_bytes,
intptr_t length_in_bytes) {
ASSERT(Utils::RangeCheck(src_offset_in_bytes, length_in_bytes,
@@ -10519,10 +10534,9 @@
}
}
- template <typename DstType, typename SrcType>
- static void ClampedCopy(const DstType& dst,
+ static void ClampedCopy(const TypedDataBase& dst,
intptr_t dst_offset_in_bytes,
- const SrcType& src,
+ const TypedDataBase& src,
intptr_t src_offset_in_bytes,
intptr_t length_in_bytes) {
ASSERT(Utils::RangeCheck(src_offset_in_bytes, length_in_bytes,
@@ -10580,29 +10594,6 @@
// snapshot. Should be independent of word size.
static const int kDataSerializationAlignment = 8;
-#define TYPED_GETTER_SETTER(name, type) \
- type Get##name(intptr_t byte_offset) const { \
- return LoadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset))); \
- } \
- void Set##name(intptr_t byte_offset, type value) const { \
- StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value); \
- }
- TYPED_GETTER_SETTER(Int8, int8_t)
- TYPED_GETTER_SETTER(Uint8, uint8_t)
- TYPED_GETTER_SETTER(Int16, int16_t)
- TYPED_GETTER_SETTER(Uint16, uint16_t)
- TYPED_GETTER_SETTER(Int32, int32_t)
- TYPED_GETTER_SETTER(Uint32, uint32_t)
- TYPED_GETTER_SETTER(Int64, int64_t)
- TYPED_GETTER_SETTER(Uint64, uint64_t)
- TYPED_GETTER_SETTER(Float32, float)
- TYPED_GETTER_SETTER(Float64, double)
- TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
- TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
- TYPED_GETTER_SETTER(Float64x2, simd128_value_t)
-
-#undef TYPED_GETTER_SETTER
-
FinalizablePersistentHandle* AddFinalizer(void* peer,
Dart_HandleFinalizer callback,
intptr_t external_size) const;
@@ -11436,7 +11427,7 @@
return RoundedAllocationSize(sizeof(UntaggedRegExp));
}
- static RegExpPtr New(Heap::Space space = Heap::kNew);
+ static RegExpPtr New(Zone* zone, Heap::Space space = Heap::kNew);
private:
void set_type(RegExType type) const {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 655857e..a533e45 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -7,6 +7,7 @@
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
+#include "vm/regexp.h"
#include "vm/snapshot.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
@@ -1748,9 +1749,9 @@
Snapshot::Kind kind,
bool as_reference) {
ASSERT(reader != NULL);
-
// Allocate RegExp object.
- RegExp& regex = RegExp::ZoneHandle(reader->zone(), RegExp::New());
+ RegExp& regex =
+ RegExp::ZoneHandle(reader->zone(), RegExp::New(reader->zone()));
reader->AddBackRef(object_id, ®ex, kIsDeserialized);
// Read and Set all the other fields.
@@ -1766,14 +1767,6 @@
regex.StoreNonPointer(®ex.untag()->num_two_byte_registers_,
reader->Read<int32_t>());
regex.StoreNonPointer(®ex.untag()->type_flags_, reader->Read<int8_t>());
-
- const Function& no_function = Function::Handle(reader->zone());
- for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid;
- cid++) {
- regex.set_function(cid, /*sticky=*/false, no_function);
- regex.set_function(cid, /*sticky=*/true, no_function);
- }
-
return regex.ptr();
}
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 782ecd1..bceb4e7 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5515,12 +5515,12 @@
return result;
}
-static void CreateSpecializedFunction(Thread* thread,
- Zone* zone,
- const RegExp& regexp,
- intptr_t specialization_cid,
- bool sticky,
- const Object& owner) {
+void CreateSpecializedFunction(Thread* thread,
+ Zone* zone,
+ const RegExp& regexp,
+ intptr_t specialization_cid,
+ bool sticky,
+ const Object& owner) {
const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
const FunctionType& signature =
@@ -5569,7 +5569,7 @@
const String& pattern,
RegExpFlags flags) {
Zone* zone = thread->zone();
- const RegExp& regexp = RegExp::Handle(RegExp::New());
+ const RegExp& regexp = RegExp::Handle(RegExp::New(zone));
regexp.set_pattern(pattern);
regexp.set_flags(flags);
diff --git a/runtime/vm/regexp.h b/runtime/vm/regexp.h
index 3fed61b..9c2b8e9 100644
--- a/runtime/vm/regexp.h
+++ b/runtime/vm/regexp.h
@@ -1517,6 +1517,13 @@
static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
};
+void CreateSpecializedFunction(Thread* thread,
+ Zone* zone,
+ const RegExp& regexp,
+ intptr_t specialization_cid,
+ bool sticky,
+ const Object& owner);
+
} // namespace dart
#endif // RUNTIME_VM_REGEXP_H_
diff --git a/sdk/lib/_internal/vm/lib/typed_data_patch.dart b/sdk/lib/_internal/vm/lib/typed_data_patch.dart
index b0c18d5..45b1dc9 100644
--- a/sdk/lib/_internal/vm/lib/typed_data_patch.dart
+++ b/sdk/lib/_internal/vm/lib/typed_data_patch.dart
@@ -58,7 +58,11 @@
// to instances of _TypeListBase. Instead the subclasses use type specific
// mixins (like _IntListMixin, _DoubleListMixin) to implement ListBase<T>.
abstract class _TypedListBase {
- int get length;
+ @pragma("vm:recognized", "graph-intrinsic")
+ @pragma("vm:exact-result-type", "dart:core#_Smi")
+ @pragma("vm:prefer-inline")
+ int get length native "TypedDataBase_length";
+
int get elementSizeInBytes;
int get offsetInBytes;
_ByteBuffer get buffer;
@@ -108,8 +112,13 @@
// match the cids of 'this' and 'from'.
// Uses toCid and fromCid to decide if clamping is necessary.
// Element size of toCid and fromCid must match (test at caller).
- bool _setRange(int startInBytes, int lengthInBytes, _TypedListBase from,
- int startFromInBytes, int toCid, int fromCid) native "TypedData_setRange";
+ bool _setRange(
+ int startInBytes,
+ int lengthInBytes,
+ _TypedListBase from,
+ int startFromInBytes,
+ int toCid,
+ int fromCid) native "TypedDataBase_setRange";
}
mixin _IntListMixin implements List<int> {
@@ -2035,13 +2044,6 @@
_ByteBuffer get buffer => new _ByteBuffer(this);
- // Methods implementing the collection interface.
-
- @pragma("vm:recognized", "graph-intrinsic")
- @pragma("vm:exact-result-type", "dart:core#_Smi")
- @pragma("vm:prefer-inline")
- int get length native "TypedData_length";
-
// Internal utility methods.
@pragma("vm:recognized", "other")
@@ -4009,11 +4011,6 @@
@pragma("vm:exact-result-type", "dart:core#_Smi")
@pragma("vm:prefer-inline")
int get offsetInBytes native "TypedDataView_offsetInBytes";
-
- @pragma("vm:recognized", "graph-intrinsic")
- @pragma("vm:exact-result-type", "dart:core#_Smi")
- @pragma("vm:prefer-inline")
- int get length native "TypedDataView_length";
}
@pragma("vm:entry-point")
@@ -4859,7 +4856,7 @@
@pragma("vm:recognized", "graph-intrinsic")
@pragma("vm:exact-result-type", "dart:core#_Smi")
@pragma("vm:prefer-inline")
- int get length native "TypedDataView_length";
+ int get length native "TypedDataBase_length";
}
@pragma("vm:prefer-inline")
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 8e3de55..d649a5d 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -56,6 +56,9 @@
regexp/global_test: Skip # Issue 21709
regexp/pcre_test: Slow, Pass
+[ $runtime != vm ]
+reg_exp_receive_port_test : Skip # uses SendPort/ReceivePort
+
[ $hot_reload || $hot_reload_rollback ]
bigint_parse_radix_test: Skip # Issue 31659. Issue 34361.
bigint_test: Skip # Issue 31659
diff --git a/tests/corelib/reg_exp_receive_port_test.dart b/tests/corelib/reg_exp_receive_port_test.dart
new file mode 100644
index 0000000..e894f30
--- /dev/null
+++ b/tests/corelib/reg_exp_receive_port_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2014, 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.
+//
+// Checks that you can send and receive regex in a message.
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main(args) async {
+ asyncStart();
+ final rp = ReceivePort();
+ final r = RegExp('b');
+ Expect.equals(r.firstMatch('bb')!.start, 0);
+ rp.sendPort.send(r);
+
+ final si = StreamIterator(rp);
+ await si.moveNext();
+ final x = si.current as RegExp;
+ Expect.equals(x.firstMatch('bb')!.start, 0);
+ rp.close();
+ asyncEnd();
+}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 8759284..5353258 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -16,6 +16,9 @@
[ $runtime != none ]
string_runes_test: Skip # See breaking change #40674
+[ $runtime != vm ]
+reg_exp_receive_port_test: Skip # uses SendPort/ReceivePort
+
[ $system == android ]
throw_half_surrogate_pair_test/*: Skip # Issue http://dartbug.com/42094
diff --git a/tests/corelib_2/reg_exp_receive_port_test.dart b/tests/corelib_2/reg_exp_receive_port_test.dart
new file mode 100644
index 0000000..a63f289
--- /dev/null
+++ b/tests/corelib_2/reg_exp_receive_port_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2014, 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.
+//
+// Checks that you can send and receive regex in a message.
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main(args) async {
+ asyncStart();
+ final rp = ReceivePort();
+ final r = RegExp('b');
+ final match = r.firstMatch('bb');
+ Expect.equals(match != null ? match.start : null, 0);
+ rp.sendPort.send(r);
+
+ final si = StreamIterator(rp);
+ await si.moveNext();
+ final x = si.current as RegExp;
+ final matchX = x.firstMatch('bb');
+ Expect.equals(matchX != null ? matchX.start : null, 0);
+ rp.close();
+ asyncEnd();
+}
diff --git a/tools/VERSION b/tools/VERSION
index a229bf4..9251a79 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 190
+PRERELEASE 191
PRERELEASE_PATCH 0
\ No newline at end of file