Version 2.12.0-115.0.dev
Merge commit 'c7f364562cabef42a42869646b3246a1aaf58d2f' into 'dev'
diff --git a/pkg/dartdev/test/fix_driver_test.dart b/pkg/dartdev/test/fix_driver_test.dart
new file mode 100644
index 0000000..35ec72a
--- /dev/null
+++ b/pkg/dartdev/test/fix_driver_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import '../tool/fix_driver.dart';
+import 'utils.dart';
+
+void main() {
+ group('Driver', _driver);
+}
+
+Future<FixOutput> runFix(List<String> args) async {
+ var runner = FixRunner(logger: CapturingLogger());
+ var result = await runner.runFix(args);
+ return FixOutput(result);
+}
+
+void _driver() {
+ TestProject p;
+ tearDown(() => p?.dispose());
+
+ test('no fixes', () async {
+ p = project(mainSrc: 'int get foo => 1;\n');
+ var result = await runFix(['--apply', p.dirPath]);
+ expect(result.stdout, contains('Nothing to fix!'));
+ expect(result.returnCode, 0);
+ });
+}
+
+class FixOutput {
+ final FixResult<CapturingLogger> result;
+ FixOutput(this.result);
+
+ int get returnCode => result.returnCode;
+ String get stderr => result.logger.output.stderr.toString();
+ String get stdout => result.logger.output.stdout.toString();
+}
diff --git a/pkg/dartdev/test/test_all.dart b/pkg/dartdev/test/test_all.dart
index 2576ac9..edd644b 100644
--- a/pkg/dartdev/test/test_all.dart
+++ b/pkg/dartdev/test/test_all.dart
@@ -18,6 +18,7 @@
import 'commands/test_test.dart' as test;
import 'core_test.dart' as core;
import 'experiments_test.dart' as experiments;
+import 'fix_driver_test.dart' as fix_driver;
import 'no_such_file_test.dart' as no_such_file;
import 'sdk_test.dart' as sdk;
import 'smoke/implicit_smoke_test.dart' as implicit_smoke;
@@ -32,6 +33,7 @@
create.main();
experiments.main();
fix.main();
+ fix_driver.main();
flag.main();
format.main();
help.main();
diff --git a/pkg/dartdev/tool/fix_driver.dart b/pkg/dartdev/tool/fix_driver.dart
new file mode 100644
index 0000000..17f246a
--- /dev/null
+++ b/pkg/dartdev/tool/fix_driver.dart
@@ -0,0 +1,140 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:args/args.dart';
+import 'package:args/command_runner.dart';
+import 'package:cli_util/cli_logging.dart';
+import 'package:dartdev/src/commands/fix.dart';
+import 'package:dartdev/src/core.dart';
+import 'package:dartdev/src/utils.dart';
+import 'package:meta/meta.dart';
+
+Future<void> main(List<String> args) async {
+ var runner = FixRunner(logger: Logger.standard());
+ var result = await runner.runFix(args);
+ return result.returnCode;
+}
+
+class CapturedProgress extends Progress {
+ final LoggerOutput output;
+
+ bool canceled = false;
+ bool finished = false;
+
+ CapturedProgress(this.output, String message) : super(message) {
+ output.progress.writeln(message);
+ }
+
+ @override
+ void cancel() {
+ canceled = true;
+ }
+
+ @override
+ void finish({String message, bool showTiming = false}) {
+ // todo (pq): consider capturing / tracking finish display updates.
+ finished = true;
+ }
+}
+
+class CapturingLogger implements Logger {
+ final LoggerOutput output = LoggerOutput();
+
+ @override
+ final Ansi ansi = Ansi(Ansi.terminalSupportsAnsi);
+
+ @override
+ bool isVerbose;
+
+ CapturingLogger({this.isVerbose = false});
+
+ @override
+ void flush() {
+ // deprecated.
+ }
+
+ @override
+ Progress progress(String message) => CapturedProgress(output, message);
+
+ @override
+ void stderr(String message) {
+ output.stderr.writeln(message);
+ }
+
+ @override
+ void stdout(String message) {
+ output.stdout.writeln(message);
+ }
+
+ @override
+ void trace(String message) {
+ output.trace.writeln(message);
+ }
+
+ @override
+ void write(String message) {
+ output.stdout.write(message);
+ }
+
+ @override
+ void writeCharCode(int charCode) {
+ output.stdout.writeCharCode(charCode);
+ }
+}
+
+class FixResult<T extends Logger> {
+ /// The value returned by [FixCommand.run].
+ final int returnCode;
+
+ /// The logger used in driving fixes.
+ final T logger;
+
+ FixResult(this.logger, this.returnCode);
+}
+
+class FixRunner<T extends Logger> extends CommandRunner<int> {
+ final _supportedOptions = ['dry-run', 'apply'];
+
+ T logger;
+
+ @override
+ final ArgParser argParser = ArgParser(
+ usageLineLength: dartdevUsageLineLength,
+ allowTrailingOptions: false,
+ );
+
+ FixRunner({@required this.logger})
+ : super('fix_runner',
+ 'A command-line utility for testing the `dart fix` command.') {
+ addCommand(FixCommand());
+ _supportedOptions.forEach(argParser.addOption);
+ }
+
+ @override
+ Future<int> runCommand(ArgResults topLevelResults) async {
+ var result = await super.runCommand(topLevelResults);
+ return result;
+ }
+
+ Future<FixResult<T>> runFix(List<String> args) async {
+ log = logger;
+ var argResults = argParser.parse(['fix', ...?args]);
+ var result = await runCommand(argResults);
+ return FixResult(logger, result);
+ }
+}
+
+class LoggerOutput {
+ /// Messages reported to progress.
+ final StringBuffer progress = StringBuffer();
+
+ /// Messages reported to stdout.
+ final StringBuffer stdout = StringBuffer();
+
+ /// Messages reported to stderr.
+ final StringBuffer stderr = StringBuffer();
+
+ /// Messages reported to trace.
+ final StringBuffer trace = StringBuffer();
+}
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 1c348aa..f0a4f2c 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -110,10 +110,18 @@
return kIllegalCid;
}
+AcqRelAtomic<Slot*> Slot::native_fields_(nullptr);
+
+enum NativeSlotsEnumeration {
+#define DECLARE_KIND(CN, __, FN, ___, ____) k##CN##_##FN,
+ NATIVE_SLOTS_LIST(DECLARE_KIND)
+#undef DECLARE_KIND
+ kNativeSlotsCount
+};
+
const Slot& Slot::GetNativeSlot(Kind kind) {
- // There is a fixed statically known number of native slots so we cache
- // them statically.
- static const Slot fields[] = {
+ if (native_fields_.load() == nullptr) {
+ Slot* new_value = new Slot[kNativeSlotsCount]{
#define NULLABLE_FIELD_FINAL \
(IsNullableBit::encode(true) | IsImmutableBit::encode(true))
#define NULLABLE_FIELD_VAR (IsNullableBit::encode(true))
@@ -123,7 +131,7 @@
k##cid##Cid, compiler::target::ClassName::FieldName##_offset(), \
#ClassName "." #FieldName, nullptr, kTagged),
- NULLABLE_BOXED_NATIVE_SLOTS_LIST(DEFINE_NULLABLE_BOXED_NATIVE_FIELD)
+ NULLABLE_BOXED_NATIVE_SLOTS_LIST(DEFINE_NULLABLE_BOXED_NATIVE_FIELD)
#undef DEFINE_NULLABLE_BOXED_NATIVE_FIELD
#undef NULLABLE_FIELD_FINAL
@@ -137,8 +145,8 @@
k##cid##Cid, compiler::target::ClassName::FieldName##_offset(), \
#ClassName "." #FieldName, nullptr, kTagged),
- NONNULLABLE_BOXED_NATIVE_SLOTS_LIST(
- DEFINE_NONNULLABLE_BOXED_NATIVE_FIELD)
+ NONNULLABLE_BOXED_NATIVE_SLOTS_LIST(
+ DEFINE_NONNULLABLE_BOXED_NATIVE_FIELD)
#undef DEFINE_NONNULLABLE_BOXED_NATIVE_FIELD
#define DEFINE_UNBOXED_NATIVE_FIELD(ClassName, UnderlyingType, FieldName, \
@@ -148,15 +156,20 @@
compiler::target::ClassName::FieldName##_offset(), \
#ClassName "." #FieldName, nullptr, kUnboxed##representation),
- UNBOXED_NATIVE_SLOTS_LIST(DEFINE_UNBOXED_NATIVE_FIELD)
+ UNBOXED_NATIVE_SLOTS_LIST(DEFINE_UNBOXED_NATIVE_FIELD)
#undef DEFINE_UNBOXED_NATIVE_FIELD
#undef NONNULLABLE_FIELD_VAR
#undef NONNULLABLE_FIELD_FINAL
- };
+ };
+ Slot* old_value = nullptr;
+ if (!native_fields_.compare_exchange_strong(old_value, new_value)) {
+ delete[] new_value;
+ }
+ }
- ASSERT(static_cast<uint8_t>(kind) < ARRAY_SIZE(fields));
- return fields[static_cast<uint8_t>(kind)];
+ ASSERT(static_cast<uint8_t>(kind) < kNativeSlotsCount);
+ return native_fields_.load()[static_cast<uint8_t>(kind)];
}
// Note: should only be called with cids of array-like classes.
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 8c24078..ba85613 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -295,6 +295,9 @@
return static_cast<const T*>(data_);
}
+ // There is a fixed statically known number of native slots so we cache
+ // them statically.
+ static AcqRelAtomic<Slot*> native_fields_;
static const Slot& GetNativeSlot(Kind kind);
const Kind kind_;
diff --git a/tools/VERSION b/tools/VERSION
index 41ab758..3e3f95d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 114
+PRERELEASE 115
PRERELEASE_PATCH 0
\ No newline at end of file