Skip to content

Commit

Permalink
Version 3.4.0-217.0.dev
Browse files Browse the repository at this point in the history
Merge 0402fa6 into dev
  • Loading branch information
Dart CI committed Mar 8, 2024
2 parents c34b995 + 0402fa6 commit 6f18b20
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 54 deletions.
24 changes: 12 additions & 12 deletions pkg/dev_compiler/lib/src/kernel/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4075,23 +4075,23 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

SourceLocation? location;
late String conditionSource;
if (node.location != null) {
var encodedSource =
node.enclosingComponent!.uriToSource[node.location!.file]!.source;
var assertLocation = node.location;
if (assertLocation != null) {
var fileUri = assertLocation.file;
var encodedSource = node.enclosingComponent!.uriToSource[fileUri]!.source;
var source = utf8.decode(encodedSource, allowMalformed: true);

conditionSource =
source.substring(node.conditionStartOffset, node.conditionEndOffset);
// Assertions that appear in debugger expressions have a synthetic Uri
// that is different than the current library where the expression will
// be evaluated.
var savedUri = _currentUri;
_currentUri = fileUri;
location = _toSourceLocation(node.conditionStartOffset)!;
_currentUri = savedUri;
} else {
// Location is null in expression compilation when modules
// are loaded from kernel using expression compiler worker.
// Show the error only in that case, with the condition AST
// instead of the source.
//
// TODO(annagrin): Can we add some information to the kernel,
// or add better printing for the condition?
// Issue: https://github.com/dart-lang/sdk/issues/43986
// If the location is ever null, only show the error with the condition
// AST instead of the source.
conditionSource = node.condition.toString();
}
return js.statement(' if (!#) #;', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ void main(List<String> args) async {
expression: '() { assert(false); return 0; } ()',
expectedError: allOf(
contains('Error: Assertion failed:'),
contains('<unknown source>:-1:-1'),
contains('BoolLiteral(false)'),
contains('org-dartlang-debug:synthetic_debug_expression:1:13'),
contains('false'),
contains('is not true'),
));
});
Expand Down
116 changes: 87 additions & 29 deletions pkg/dev_compiler/tool/ddb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ void main(List<String> args) async {
void printUsage() {
print('Usage: ddb [options] <dart-script-file>\n');
print('Compiles <dart-script-file> with the dev_compiler and runs it on a '
'JS platform.\n');
'JS platform.\n'
'Optionally, mulitple Dart source files can be passed as arguments and '
'they will be compiled into seperate modules in the order provided. '
'The order will be treated as an import DAG with the last file as the '
'application entrypoint. The .dill file outputs from each compile will '
'be collected and passed as dependency summaries for the next compile '
'step.');
}

// Parse flags.
Expand Down Expand Up @@ -66,6 +72,11 @@ void main(List<String> args) async {
negatable: true)
..addFlag('weak-null-safety-errors',
help: 'Treat weak null safety warnings as errors.', defaultsTo: false)
..addFlag('ddc-modules',
help: 'Emit modules in the ddc format. Currently supported in Chrome '
'(amd modules by default) and D8 (already uses ddc modules by '
'default).',
defaultsTo: false)
..addFlag('canary',
help: 'Enable all compiler features under active development.',
defaultsTo: false)
Expand Down Expand Up @@ -105,7 +116,7 @@ void main(List<String> args) async {
print(parser.usage);
exit(0);
}
if (options.rest.length != 1) {
if (options.rest.isEmpty) {
print('Dart script file required.\n');
printUsage();
exit(1);
Expand All @@ -130,21 +141,21 @@ void main(List<String> args) async {
? options['native-null-assertions'] as bool
: soundNullSafety;
var weakNullSafetyErrors = options['weak-null-safety-errors'] as bool;
var ddcModules = options['ddc-modules'] as bool;
var canaryFeatures = options['canary'] as bool;
var entry = p.canonicalize(options.rest.first);
var out = (options['out'] as String?) ?? p.setExtension(entry, '.js');
var libRoot = p.dirname(entry);
var basename = p.basenameWithoutExtension(entry);
var libname =
js_names.pathToJSIdentifier(p.relative(p.withoutExtension(entry)));
var sourceFiles = options.rest.map(p.canonicalize);
var entryPoint = sourceFiles.last;
var libRoot = p.dirname(entryPoint);
var basename = p.basenameWithoutExtension(entryPoint);
var libname = pathToLibName(entryPoint);

// This is used in the DDC module system and usually corresponds to the
// entrypoint's path.
var appname = p.relative(p.withoutExtension(entry));
var appname = p.relative(p.withoutExtension(entryPoint));

// This is used in the DDC module system for multiapp workflows and is
// stubbed in ddb.
var uuid = "00000000-0000-0000-0000-000000000000";
var uuid = '00000000-0000-0000-0000-000000000000';

// By default (no `-d`), we use the `dartdevc` binary on the user's path to
// compute the SDK we use for execution. I.e., we assume that `dart` is
Expand Down Expand Up @@ -214,6 +225,11 @@ void main(List<String> args) async {
var runtime = options['runtime'] as String?;
switch (runtime) {
case 'node':
// TODO(nshahan): Cleanup after the ddc module format is used everywhere.
if (ddcModules) {
throw ('The combination of `--runtime=$runtime` and `--ddc-modules` '
'is not supported at this time.');
}
node = true;
mod = 'common';
break;
Expand All @@ -223,7 +239,8 @@ void main(List<String> args) async {
break;
case 'chrome':
chrome = true;
mod = 'amd';
// TODO(nshahan): Cleanup after the ddc module format is used everywhere.
mod = ddcModules ? 'ddc' : 'amd';
break;
default:
throw Exception('Unexpected runtime: $runtime');
Expand All @@ -240,12 +257,14 @@ void main(List<String> args) async {
].join();
var sdkJsPath =
p.join(buildDir, 'gen', 'utils', 'ddc', compileModeDir, 'sdk', mod);
var preamblesDir = p.join(
sdkRoot, 'sdk', 'lib', '_internal', 'js_runtime', 'lib', 'preambles');

// Print an initial empty line to separate the invocation from the output.
if (verbose) {
print('');
}

var outputs = <String>[];
if (compile) {
var ddcArgs = [
if (summarizeText) '--summarize-text',
Expand All @@ -257,11 +276,23 @@ void main(List<String> args) async {
if (options['packages'] != null) '--packages=${options['packages']}',
if (emitDebugSymbols) '--emit-debug-symbols',
if (canaryFeatures) '--canary',
'-o',
out,
entry
];
await runDdc(ddcArgs);
var summaryFiles = [];
for (var sourceFile in sourceFiles) {
var out = p.setExtension(sourceFile, '.js');
var requestArgs = [
for (var summary in summaryFiles) '--summary=$summary',
'-o',
out,
sourceFile,
];
await runDdc([...ddcArgs, ...requestArgs]);
outputs.add(out);
var summaryFile = p.setExtension(out, '.dill');
var libname =
js_names.pathToJSIdentifier(p.basenameWithoutExtension(sourceFile));
summaryFiles.add('$summaryFile=$libname');
}
}

if (run) {
Expand All @@ -279,23 +310,25 @@ void main(List<String> args) async {
// Assume Linux
chromeBinary = 'google-chrome';
}
var amdModulePaths = [
for (var output in outputs)
'"${pathToLibName(output)}": "${p.withoutExtension(output)}"'
].join(',\n ');

// Seal the native JavaScript Object prototype to avoid pollution before
// loading the Dart SDK module.
var html = '''
<script>
delete Object.prototype.__proto__;
Object.seal(Object.prototype);
</script>
var amdModulesHtml = '''
<script src="$preamblesDir/seal_native_object.js"></script>
<script src='$requirePath/require.js'></script>
<script>
require.config({
paths: {
'dart_sdk': '$sdkJsPath/dart_sdk',
$amdModulePaths
},
waitSeconds: 15
});
require(['dart_sdk', '$basename'],
require(['dart_sdk', '$libname'],
function(sdk, app) {
'use strict';
Expand All @@ -309,8 +342,28 @@ Object.seal(Object.prototype);
});
</script>
''';
var htmlFile = p.setExtension(out, '.html');
File(htmlFile).writeAsStringSync(html);
var ddcModuleScriptTags = [
for (var output in outputs) '<script src="$output"></script>'
].join('\n');
var ddcModulesHtml = '''
<script src="$preamblesDir/seal_native_object.js"></script>
<script src="$ddcPath/lib/js/ddc/ddc_module_loader.js"></script>
<script src="$sdkJsPath/dart_sdk.js"></script>
$ddcModuleScriptTags
<script>
let sdk = dart_library.import("dart_sdk");
sdk.dart.weakNullSafetyWarnings(
!($weakNullSafetyErrors || $soundNullSafety));
sdk.dart.weakNullSafetyErrors($weakNullSafetyErrors);
sdk.dart.nonNullAsserts($nonNullAsserts);
sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts);
dart_library.start("$appname", "$uuid", "$basename", "$libname", false);
</script>
''';
var htmlFile = p.setExtension(entryPoint, '.html');
File(htmlFile)
.writeAsStringSync(ddcModules ? ddcModulesHtml : amdModulesHtml);
var tmp = p.join(Directory.systemTemp.path, 'ddc');

var process = await startProcess('Chrome', chromeBinary, [
Expand Down Expand Up @@ -354,17 +407,19 @@ try {
process.exit(1);
}
''';
var nodeFile = p.setExtension(out, '.run.js');
var nodeFile = p.setExtension(entryPoint, '.run.js');
File(nodeFile).writeAsStringSync(runjs);
var nodeBinary = binary ?? 'node';
var process = await startProcess('Node', nodeBinary,
['--inspect=localhost:$port', nodeFile], {'NODE_PATH': nodePath});
if (await process.exitCode != 0) exit(await process.exitCode);
} else if (d8) {
var ddcModuleScriptTags =
[for (var output in outputs) 'load("$output");'].join('\n');
var runjs = '''
load("$ddcPath/lib/js/ddc/ddc_module_loader.js");
load("$sdkJsPath/dart_sdk.js");
load("$out");
$ddcModuleScriptTags
let sdk = dart_library.import('dart_sdk');
// Create a self reference for JS interop tests that set fields on self.
Expand All @@ -381,9 +436,7 @@ self.dartMainRunner(function () {
dart_library.start("$appname", "$uuid", "$basename", "$libname", false);
});
''';
var preamblesDir = p.join(
sdkRoot, 'sdk', 'lib', '_internal', 'js_runtime', 'lib', 'preambles');
var d8File = p.setExtension(out, '.d8.js');
var d8File = p.setExtension(entryPoint, '.d8.js');
File(d8File).writeAsStringSync(runjs);
var d8Binary = binary ?? p.join(dartCheckoutPath, _d8executable);
var process = await startProcess('D8', d8Binary, [
Expand All @@ -396,6 +449,11 @@ self.dartMainRunner(function () {
}
}

/// Converts a path to the expected default library name DDC will use.
String pathToLibName(String path) =>
js_names.pathToJSIdentifier(p.withoutExtension(
p.isWithin(p.current, path) ? p.relative(path) : p.absolute(path)));

String get _d8executable {
final arch = Abi.current().toString().split('_')[1];
if (Platform.isWindows) {
Expand Down
32 changes: 24 additions & 8 deletions runtime/tests/vm/dart/regress_55003_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,32 @@
// 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.

int var64 = -1;
num var68 = 2;
// Verifies that compiler correctly chooses representation and
// doesn't crash when canonicalizing multiplication to a shift
// after the final SelectRepresentations pass.
// Regression test for https://github.com/dart-lang/sdk/issues/55003.

@pragma("vm:always-consider-inlining")
Set<bool>? foo0_1() {
return <bool>{
(8 <= (((var64 + -90) * 9223372034707292160) % var68)),
};
import 'package:expect/expect.dart';

int one = int.parse('1');

@pragma('vm:never-inline')
void test1() {
// Truncation of 0xaabbccdd00000004 to uint32 is inserted
// by SelectRepresentations_Final. After that, canonicalization
// replaces BinaryUint32Op multiplication with a shift.
Expect.equals(4, (one * 0xaabbccdd00000004) % 8);
}

@pragma('vm:never-inline')
void test2() {
// Truncation of 0xaabbccdd00000000 to uint32 is inserted
// by SelectRepresentations_Final. After that, canonicalization
// replaces outer BinaryInt64Op multiplication with a shift.
Expect.equals(4, one * (((one * 0xaabbccdd00000000) % 8) + 4));
}

main() {
foo0_1();
test1();
test2();
}
12 changes: 11 additions & 1 deletion runtime/vm/compiler/backend/il.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2434,6 +2434,13 @@ Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
}
}

if (IsBinaryUint32Op() && HasUnmatchedInputRepresentations()) {
// Canonicalization may eliminate instruction and loose truncation,
// so it is illegal to canonicalize truncating uint32 instruction
// until all conversions for its inputs are inserted.
return this;
}

switch (op_kind()) {
case Token::kMUL:
if (rhs == 1) {
Expand All @@ -2442,8 +2449,11 @@ Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
return right()->definition();
} else if ((rhs > 0) && Utils::IsPowerOfTwo(rhs)) {
const int64_t shift_amount = Utils::ShiftForPowerOfTwo(rhs);
const Representation shift_amount_rep =
(SpeculativeModeOfInputs() == kNotSpeculative) ? kUnboxedInt64
: kTagged;
ConstantInstr* constant_shift_amount = flow_graph->GetConstant(
Smi::Handle(Smi::New(shift_amount)), kTagged);
Smi::Handle(Smi::New(shift_amount)), shift_amount_rep);
BinaryIntegerOpInstr* shift = BinaryIntegerOpInstr::Make(
representation(), Token::kSHL, left()->CopyWithType(),
new Value(constant_shift_amount), GetDeoptId(), can_overflow(),
Expand Down
8 changes: 7 additions & 1 deletion runtime/vm/compiler/backend/il.h
Original file line number Diff line number Diff line change
Expand Up @@ -9285,6 +9285,10 @@ class BinaryUint32OpInstr : public BinaryIntegerOpInstr {
return kUnboxedUint32;
}

virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
return kNotSpeculative;
}

static bool IsSupported(Token::Kind op_kind) {
switch (op_kind) {
case Token::kADD:
Expand Down Expand Up @@ -9479,7 +9483,9 @@ class ShiftUint32OpInstr : public ShiftIntegerOpInstr {
return kNotSpeculative;
}
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool MayThrow() const { return true; }
virtual bool MayThrow() const {
return !IsShiftCountInRange(kUint32ShiftCountLimit);
}

virtual Representation representation() const { return kUnboxedUint32; }

Expand Down
2 changes: 1 addition & 1 deletion tools/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ CHANNEL dev
MAJOR 3
MINOR 4
PATCH 0
PRERELEASE 216
PRERELEASE 217
PRERELEASE_PATCH 0

0 comments on commit 6f18b20

Please sign in to comment.