mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 21:50:11 +00:00
5cb3b37c74
This reverts commit69f32d6ad7
. Reason for revert: We seem to have a number of tests failing with timeouts in CBUILD after this change, please see logs at69f32d6ad7
Original change's description: > Refactor `_Future`. > > This is a major rewrite of the `_Future` class, > which is the default implementation of the `Future` interface. > > The main goal was to reduce the number of expensive type checks > in the internal passing around of data. > Expensive type checks are things like > * `is _Future<T>` (more expensive than just `is _Future`, the latter > can be a single class-ID check. > * Covariant generic parameter checks (using `T` covariantly in a > parameter forces a run-time type check). > > Also removed some plain unnecessary casts and turned some > implicit casts from `dynamic` into `unsafeCast`s. > > This seems to be an success, at least on very primitive benchmarks, according to Golem: > FutureCatchErrorTest 41.22% (1.9 noise) > FutureValueTest 46.51% (2.8 noise) > EmptyFutureTest 59.15% (3.1 noise) > FutureWhenCompleteTest 51.10% (3.2 noise) > > A secondary goal was to clean up a very old and messy class, > and make it clearer for other `dart:async` how to interact > with the future. > > The change has a memory cost: The `_FutureListener<S,T>` class, > which represents a `then`, `catchError` or `whenComplete` > call on a `_Future`, now contains a reference to its source future, > the one which provides the inputs to the callbacks, > as well as the result future returned by the call. > That's one extra memory slot per listener. > > In return, the `_FutureListener` now does not need to > get its source future as an argument, which needs a covariant > generic type check, and the methods of `_Future` can be written > in a way which ignores the type parameters of both `_Future` > and `_FutureListener`, which reduces complex type checks > significantly. > > In general, typed code is in `_FutureListener`, which knows both > the source and target types of the listener callbacks, and which > contains the futures already at that type, so no extra type checking > is needed. > The `_Future` class is mostly untyped, except for its "public" > API, called by other classes, which checks inputs, > and code interacting with non-native futures. > Invariants ensure that only correctly typed values > are stored in the untyped shared `_resultOrListeners` field > on `_Future`, as determined by its `_state` integer. > (This was already partially true, and has simply been made > more consistent.) > > Further, we now throw an error in a situation that was previously > unhandled: When a `_Future` is completed with *itself*. > That would ensure that the future would never complete > (it waits for itself to complete before it can complete), > and may potentially have caused weird loops in the representation. > In practice, it probably never happens. Now it makes the error > fail with an error. > Currently a private `_FutureCyclicDependencyError` which presents > as an `UnsupportedError`. > That avoids code like > ```dart > import "dart:async"; > void main() { > var c = Completer(); > c.complete(c.future); // bad. > print("well!"); > var d = Completer(); > d.complete(c.future); > print("shucks!"); > } > ``` > from hanging the runtime by busily searching for the end of a cycle. > > See https://github.com/dart-lang/sdk/issues/48225 > Fixes #48225 > > TEST= refactoring covered by existing tests, few new tests. > > Change-Id: Id9fc5af5fe011deb0af3e1e8a4ea3a91799f9da4 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244241 > Reviewed-by: Martin Kustermann <kustermann@google.com> > Commit-Queue: Lasse Nielsen <lrn@google.com> TBR=lrn@google.com,kustermann@google.com,sra@google.com,sigmund@google.com,nshahan@google.com Change-Id: I455be5a04b4c346df26d4ded0fa7388baccb0f8c No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/247762 Reviewed-by: Siva Annamalai <asiva@google.com> Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Alexander Aprelev <aam@google.com>
144 lines
4.2 KiB
Dart
144 lines
4.2 KiB
Dart
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:developer';
|
|
|
|
import 'package:test/test.dart';
|
|
import 'package:vm_service/vm_service.dart';
|
|
|
|
import 'common/service_test_common.dart';
|
|
import 'common/test_helper.dart';
|
|
|
|
const int LINE_A = 25;
|
|
const int LINE_B = 28;
|
|
const int LINE_C = 31;
|
|
|
|
testFunction() {
|
|
debugger();
|
|
var a;
|
|
try {
|
|
var b;
|
|
try {
|
|
for (int i = 0; i < 10; i++) {
|
|
var x = () => i + a + b;
|
|
return x; // LINE_A
|
|
}
|
|
} finally {
|
|
b = 10; // LINE_B
|
|
}
|
|
} finally {
|
|
a = 1; // LINE_C
|
|
}
|
|
}
|
|
|
|
testMain() {
|
|
var f = testFunction();
|
|
expect(f(), equals(11));
|
|
}
|
|
|
|
var tests = <IsolateTest>[
|
|
hasStoppedAtBreakpoint,
|
|
// Add breakpoint
|
|
(VmService service, IsolateRef isolateRef) async {
|
|
final isolateId = isolateRef.id!;
|
|
Isolate isolate = await service.getIsolate(isolateId);
|
|
final rootLib =
|
|
await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
|
|
|
|
final script =
|
|
await service.getObject(isolateId, rootLib.scripts![0].id!) as Script;
|
|
|
|
// Add 3 breakpoints.
|
|
{
|
|
final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_A);
|
|
expect(bpt.location!.script.id!, script.id);
|
|
final tmpScript =
|
|
await service.getObject(isolateId, script.id!) as Script;
|
|
expect(
|
|
tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
|
|
LINE_A,
|
|
);
|
|
isolate = await service.getIsolate(isolateId);
|
|
expect(isolate.breakpoints!.length, 1);
|
|
}
|
|
|
|
{
|
|
final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_B);
|
|
expect(bpt.location!.script.id, script.id);
|
|
final tmpScript =
|
|
await service.getObject(isolateId, script.id!) as Script;
|
|
expect(
|
|
tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
|
|
LINE_B,
|
|
);
|
|
isolate = await service.getIsolate(isolateId);
|
|
expect(isolate.breakpoints!.length, 2);
|
|
}
|
|
|
|
{
|
|
final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_C);
|
|
expect(bpt.location!.script.id, script.id!);
|
|
final tmpScript =
|
|
await service.getObject(isolateId, script.id!) as Script;
|
|
expect(
|
|
tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
|
|
LINE_C,
|
|
);
|
|
isolate = await service.getIsolate(isolateId);
|
|
expect(isolate.breakpoints!.length, 3);
|
|
}
|
|
// Wait for breakpoint events.
|
|
},
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
// We are at the breakpoint on line LINE_A.
|
|
(VmService service, IsolateRef isolateRef) async {
|
|
final stack = await service.getStack(isolateRef.id!);
|
|
expect(stack.frames!.length, greaterThanOrEqualTo(1));
|
|
|
|
final script = await service.getObject(
|
|
isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
|
|
expect(
|
|
script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
|
|
LINE_A,
|
|
);
|
|
},
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
// We are at the breakpoint on line LINE_B.
|
|
(VmService service, IsolateRef isolateRef) async {
|
|
final stack = await service.getStack(isolateRef.id!);
|
|
expect(stack.frames!.length, greaterThanOrEqualTo(1));
|
|
|
|
final script = await service.getObject(
|
|
isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
|
|
expect(
|
|
script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
|
|
LINE_B,
|
|
);
|
|
},
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
// We are at the breakpoint on line LINE_C.
|
|
(VmService service, IsolateRef isolateRef) async {
|
|
final stack = await service.getStack(isolateRef.id!);
|
|
expect(stack.frames!.length, greaterThanOrEqualTo(1));
|
|
|
|
final script = await service.getObject(
|
|
isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
|
|
expect(
|
|
script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
|
|
LINE_C,
|
|
);
|
|
},
|
|
resumeIsolate,
|
|
];
|
|
|
|
main(args) => runIsolateTests(
|
|
args,
|
|
tests,
|
|
'debugging_inlined_finally_test.dart',
|
|
testeeConcurrent: testMain,
|
|
);
|