Version 2.15.0-51.0.dev
Merge commit '0231a0841a37ab2abfe9c236258f67f9f1bfa4fe' into 'dev'
diff --git a/benchmarks/EventLoopLatencyRegexp/dart2/EventLoopLatencyRegexp.dart b/benchmarks/EventLoopLatencyRegexp/dart2/EventLoopLatencyRegexp.dart
index 86ef5bc..11940c4 100644
--- a/benchmarks/EventLoopLatencyRegexp/dart2/EventLoopLatencyRegexp.dart
+++ b/benchmarks/EventLoopLatencyRegexp/dart2/EventLoopLatencyRegexp.dart
@@ -6,7 +6,7 @@
import 'dart:isolate';
-import 'json_benchmark.dart';
+import 'regexp_benchmark.dart';
import 'latency.dart';
main() async {
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 49d514d..59a0623 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1071,8 +1071,9 @@
.toList();
locations.sort();
for (var location in locations) {
- table.add(toRow(targetMetrics
- .map((metrics) => metrics.locationMrrComputers[location]!)));
+ table.add(toRow(targetMetrics.map((metrics) =>
+ metrics.locationMrrComputers[location] ??
+ MeanReciprocalRankComputer(location))));
}
}
rightJustifyColumns(table, range(1, table[0].length));
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 92573bd..9038287 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1701,9 +1701,9 @@
var functionRewrite = MethodInvocationResolver.getRewriteResult(node);
if (functionRewrite != null) {
- nullShortingTermination(node, discardType: true);
_resolveRewrittenFunctionExpressionInvocation(
functionRewrite, whyNotPromotedList);
+ nullShortingTermination(node, discardType: true);
} else {
nullShortingTermination(node);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 339e46a..4fe187f 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -2542,6 +2542,34 @@
);
}
+ test_hasReceiver_interfaceQ_nullShorting_getter() async {
+ await assertNoErrorsInCode(r'''
+abstract class C {
+ void Function(C) get foo;
+}
+
+void f(C? c) {
+ c?.foo(c); // 1
+}
+''');
+
+ var invocation = findNode.functionExpressionInvocation('foo(c);');
+ assertElementNull(invocation);
+ assertInvokeType(invocation, 'void Function(C)');
+ assertType(invocation, 'void');
+
+ var foo = invocation.function as PropertyAccess;
+ assertType(foo, 'void Function(C)');
+ assertElement(foo.propertyName, findElement.getter('foo'));
+ assertType(foo.propertyName, 'void Function(C)');
+
+ assertSimpleIdentifier(
+ findNode.simple('c); // 1'),
+ element: findElement.parameter('c'),
+ type: 'C',
+ );
+ }
+
test_hasReceiver_interfaceTypeQ_defined() async {
await assertErrorsInCode(r'''
class A {
diff --git a/pkg/vm_snapshot_analysis/test/utils.dart b/pkg/vm_snapshot_analysis/test/utils.dart
index 02e25bd..0d52b80 100644
--- a/pkg/vm_snapshot_analysis/test/utils.dart
+++ b/pkg/vm_snapshot_analysis/test/utils.dart
@@ -10,7 +10,7 @@
final dartCompile = () {
final sdkBin = path.dirname(Platform.executable);
- final dartCmd = path.join(sdkBin, Platform.isWindows ? 'dart.bat' : 'dart');
+ final dartCmd = path.join(sdkBin, Platform.isWindows ? 'dart.exe' : 'dart');
if (!File(dartCmd).existsSync()) {
throw 'Failed to locate `dart` in the SDK';
diff --git a/runtime/observatory/tests/service/regress_46419_test.dart b/runtime/observatory/tests/service/regress_46419_test.dart
new file mode 100644
index 0000000..9e1ef46
--- /dev/null
+++ b/runtime/observatory/tests/service/regress_46419_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose-debug
+
+import 'package:observatory/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+// DO NOT REORDER BEYOND THIS POINT
+bool testing = false;
+void printSync() {
+ print('sync');
+ if (testing) {
+ // We'll never reach this code, but setting a breakpoint here will result in
+ // the breakpoint being resolved below at line 25.
+ print('unreachable'); // line 18, bp1
+ }
+}
+
+printSyncStar() sync* {
+ // We'll end up resolving breakpoint 1 to this location instead of at line 15
+ // if #46419 regresses.
+ print('sync*');
+}
+
+testeeDo() {
+ printSync();
+ final iterator = printSyncStar();
+
+ print('middle'); // Line 32, bp2
+
+ iterator.toList();
+}
+// END DO NOT REORDER SECTION
+
+late Breakpoint bp1;
+late Breakpoint bp2;
+
+final tests = <IsolateTest>[
+ hasPausedAtStart,
+ (Isolate isolate) async {
+ await isolate.rootLibrary.load();
+ final script = isolate.rootLibrary.scripts[0];
+
+ bp1 = await isolate.addBreakpoint(script, 18);
+ print("BP1 - $bp1");
+ expect(bp1, isNotNull);
+ expect(bp1 is Breakpoint, isTrue);
+ bp2 = await isolate.addBreakpoint(script, 32);
+ print("BP2 - $bp2");
+ expect(bp2, isNotNull);
+ },
+ resumeIsolate,
+ (Isolate isolate) async {
+ final stream = await isolate.vm.getEventStream(VM.kDebugStream);
+ await for (ServiceEvent event in stream) {
+ if (event.kind == ServiceEvent.kPauseBreakpoint) {
+ var bp = event.breakpoint;
+ print('Hit $bp');
+ expect(bp, bp2);
+ await isolate.resume();
+ break;
+ }
+ }
+ }
+];
+
+void main([args = const []]) => runIsolateTests(
+ args,
+ tests,
+ testeeConcurrent: testeeDo,
+ pause_on_start: true,
+ );
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 3baefe9..2059774 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -163,6 +163,7 @@
regress_28443_test: SkipByDesign # Debugger is disabled in AOT mode.
regress_28980_test: SkipByDesign # Debugger is disabled in AOT mode.
regress_34841_test: SkipByDesign # Debugger is disabled in AOT mode.
+regress_46419_test: SkipByDesign # Debugger is disabled in AOT mode.
reload_sources_test: SkipByDesign # Hot reload is disabled in AOT mode.
rewind_optimized_out_test: SkipByDesign # Debugger is disabled in AOT mode.
rewind_test: SkipByDesign # Debugger is disabled in AOT mode.
diff --git a/runtime/observatory_2/tests/service_2/regress_46419_test.dart b/runtime/observatory_2/tests/service_2/regress_46419_test.dart
new file mode 100644
index 0000000..9a80e0b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/regress_46419_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose-debug
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+// DO NOT REORDER BEYOND THIS POINT
+bool testing = false;
+void printSync() {
+ print('sync');
+ if (testing) {
+ // We'll never reach this code, but setting a breakpoint here will result in
+ // the breakpoint being resolved below at line 25.
+ print('unreachable'); // line 18, bp1
+ }
+}
+
+printSyncStar() sync* {
+ // We'll end up resolving breakpoint 1 to this location instead of at line 15
+ // if #46419 regresses.
+ print('sync*');
+}
+
+testeeDo() {
+ printSync();
+ final iterator = printSyncStar();
+
+ print('middle'); // Line 32, bp2
+
+ iterator.toList();
+}
+// END DO NOT REORDER SECTION
+
+Breakpoint bp1;
+Breakpoint bp2;
+
+final tests = <IsolateTest>[
+ hasPausedAtStart,
+ (Isolate isolate) async {
+ await isolate.rootLibrary.load();
+ final script = isolate.rootLibrary.scripts[0];
+
+ bp1 = await isolate.addBreakpoint(script, 18);
+ print("BP1 - $bp1");
+ expect(bp1, isNotNull);
+ expect(bp1 is Breakpoint, isTrue);
+ bp2 = await isolate.addBreakpoint(script, 32);
+ print("BP2 - $bp2");
+ expect(bp2, isNotNull);
+ },
+ resumeIsolate,
+ (Isolate isolate) async {
+ final stream = await isolate.vm.getEventStream(VM.kDebugStream);
+ await for (ServiceEvent event in stream) {
+ if (event.kind == ServiceEvent.kPauseBreakpoint) {
+ var bp = event.breakpoint;
+ print('Hit $bp');
+ expect(bp, bp2);
+ await isolate.resume();
+ break;
+ }
+ }
+ }
+];
+
+void main([args = const []]) => runIsolateTests(
+ args,
+ tests,
+ testeeConcurrent: testeeDo,
+ pause_on_start: true,
+ );
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
index 1fb2444..f926c9a 100644
--- a/runtime/observatory_2/tests/service_2/service_2_kernel.status
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -163,6 +163,7 @@
regress_28443_test: SkipByDesign # Debugger is disabled in AOT mode.
regress_28980_test: SkipByDesign # Debugger is disabled in AOT mode.
regress_34841_test: SkipByDesign # Debugger is disabled in AOT mode.
+regress_46419_test: SkipByDesign # Debugger is disabled in AOT mode.
reload_sources_test: SkipByDesign # Hot reload is disabled in AOT mode.
rewind_optimized_out_test: SkipByDesign # Debugger is disabled in AOT mode.
rewind_test: SkipByDesign # Debugger is disabled in AOT mode.
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 8e2fb4b..c858051 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1381,6 +1381,7 @@
void ClassFinalizer::SortClasses() {
auto T = Thread::Current();
+ StackZone stack_zone(T);
auto Z = T->zone();
auto IG = T->isolate_group();
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.cc b/runtime/vm/compiler/aot/dispatch_table_generator.cc
index 2198ae7..42a8d8a 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.cc
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.cc
@@ -98,7 +98,7 @@
: selector_(selector),
class_ranges_(zone, 0),
ranges_(zone, 0),
- code_(Code::Handle(zone)) {}
+ code_(Code::ZoneHandle(zone)) {}
TableSelector* selector() const { return selector_; }
@@ -408,6 +408,7 @@
void DispatchTableGenerator::Initialize(ClassTable* table) {
classes_ = table;
+ HANDLESCOPE(Thread::Current());
ReadTableSelectorInfo();
NumberSelectors();
SetupSelectorRows();
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 35ca895..5c02e8a 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -718,6 +718,7 @@
}
void Precompiler::AddRoots() {
+ HANDLESCOPE(T);
// Note that <rootlibrary>.main is not a root. The appropriate main will be
// discovered through _getMainClosure.
@@ -776,6 +777,7 @@
}
void Precompiler::CollectCallbackFields() {
+ HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Class& subcls = Class::Handle(Z);
@@ -790,6 +792,7 @@
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -843,6 +846,7 @@
}
void Precompiler::ProcessFunction(const Function& function) {
+ HANDLESCOPE(T);
const intptr_t gop_offset =
FLAG_use_bare_instructions ? global_object_pool_builder()->CurrentLength()
: 0;
@@ -1462,6 +1466,7 @@
// Adds all values annotated with @pragma('vm:entry-point') as roots.
void Precompiler::AddAnnotatedRoots() {
+ HANDLESCOPE(T);
auto& lib = Library::Handle(Z);
auto& cls = Class::Handle(Z);
auto& members = Array::Handle(Z);
@@ -1480,6 +1485,7 @@
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -1592,6 +1598,7 @@
}
void Precompiler::CheckForNewDynamicFunctions() {
+ HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
@@ -1604,6 +1611,7 @@
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -1769,6 +1777,7 @@
if (!FLAG_collect_dynamic_function_names) {
return;
}
+ HANDLESCOPE(T);
auto& lib = Library::Handle(Z);
auto& cls = Class::Handle(Z);
auto& functions = Array::Handle(Z);
@@ -1781,6 +1790,7 @@
Table table(HashTables::New<Table>(100));
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -1873,6 +1883,7 @@
}
void Precompiler::TraceForRetainedFunctions() {
+ HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
@@ -1884,6 +1895,7 @@
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -1969,6 +1981,7 @@
void Precompiler::FinalizeDispatchTable() {
PRECOMPILER_TIMER_SCOPE(this, FinalizeDispatchTable);
if (!FLAG_use_bare_instructions || !FLAG_use_table_dispatch) return;
+ HANDLESCOPE(T);
// Build the entries used to serialize the dispatch table before
// dropping functions, as we may clear references to Code objects.
const auto& entries =
@@ -2083,6 +2096,7 @@
}
void Precompiler::DropFunctions() {
+ HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
@@ -2163,6 +2177,7 @@
auto& desc = Array::Handle(Z);
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -2232,6 +2247,7 @@
}
void Precompiler::DropFields() {
+ HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& fields = Array::Handle(Z);
@@ -2242,6 +2258,7 @@
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -2294,6 +2311,7 @@
void Precompiler::AttachOptimizedTypeTestingStub() {
PRECOMPILER_TIMER_SCOPE(this, AttachOptimizedTypeTestingStub);
+ HANDLESCOPE(T);
IsolateGroup::Current()->heap()->CollectAllGarbage();
GrowableHandlePtrArray<const AbstractType> types(Z, 200);
{
@@ -2359,6 +2377,7 @@
}
void Precompiler::TraceTypesFromRetainedClasses() {
+ HANDLESCOPE(T);
auto& lib = Library::Handle(Z);
auto& cls = Class::Handle(Z);
auto& members = Array::Handle(Z);
@@ -2370,6 +2389,7 @@
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@@ -2445,6 +2465,7 @@
}
void Precompiler::DropMetadata() {
+ HANDLESCOPE(T);
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
Library& lib = Library::Handle(Z);
@@ -2455,6 +2476,7 @@
}
void Precompiler::DropLibraryEntries() {
+ HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Array& dict = Array::Handle(Z);
Object& entry = Object::Handle(Z);
@@ -2501,6 +2523,7 @@
}
void Precompiler::DropClasses() {
+ HANDLESCOPE(T);
Class& cls = Class::Handle(Z);
Array& constants = Array::Handle(Z);
GrowableObjectArray& implementors = GrowableObjectArray::Handle(Z);
@@ -2587,6 +2610,7 @@
}
void Precompiler::DropLibraries() {
+ HANDLESCOPE(T);
const GrowableObjectArray& retained_libraries =
GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
const Library& root_lib =
@@ -2596,6 +2620,7 @@
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
+ HANDLESCOPE(T);
intptr_t entries = 0;
DictionaryIterator it(lib);
while (it.HasNext()) {
@@ -2824,6 +2849,7 @@
return;
}
+ HANDLESCOPE(T);
DiscardCodeVisitor visitor(Z, functions_to_retain_,
functions_called_dynamically_);
ProgramVisitor::WalkProgram(Z, IG, &visitor);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 5ce5395..58a9649 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -3102,16 +3102,6 @@
void FlowGraphCompiler::FrameStatePush(Definition* defn) {
Representation rep = defn->representation();
- if ((rep == kUnboxedDouble) || (rep == kUnboxedFloat64x2) ||
- (rep == kUnboxedFloat32x4)) {
- // The LoadField instruction may lie about its representation in unoptimized
- // code for Dart fields because Definition::representation() can't depend on
- // the type of compilation but MakeLocationSummary and EmitNativeCode can.
- ASSERT(defn->IsLoadField() &&
- defn->AsLoadField()->IsUnboxedDartFieldLoad());
- ASSERT(defn->locs()->out(0).IsRegister());
- rep = kTagged;
- }
ASSERT(!is_optimizing());
ASSERT((rep == kTagged) || (rep == kUntagged) ||
RepresentationUtils::IsUnboxedInteger(rep));
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 1a6db80..41ef3cb 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -903,7 +903,7 @@
}
Representation LoadFieldInstr::representation() const {
- if (IsUnboxedDartFieldLoad()) {
+ if (IsUnboxedDartFieldLoad() && CompilerState::Current().is_optimizing()) {
return FlowGraph::UnboxedFieldRepresentationOf(slot().field());
}
return slot().representation();
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 99362e7..2054bbb 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -5351,7 +5351,11 @@
function.set_is_inlinable(!FLAG_lazy_async_stacks);
}
- function.set_end_token_pos(function_node_helper.end_position_);
+ // If the start token position is synthetic, the end token position
+ // should be as well.
+ function.set_end_token_pos(
+ position.IsReal() ? function_node_helper.end_position_ : position);
+
LocalScope* scope = scopes()->function_scopes[i].scope;
const ContextScope& context_scope = ContextScope::Handle(
Z, scope->PreserveOuterScope(flow_graph_builder_->context_depth_));
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 71d09e7..c02e4fb 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -132,7 +132,8 @@
ASSERT(script_url.Equals(func_url));
#endif // defined(DEBUG)
ASSERT(!IsLatent());
- ASSERT(token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
+ ASSERT(func.is_generated_body() ||
+ token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
ASSERT(func.is_debuggable());
token_pos_.store(token_pos);
end_token_pos_.store(token_pos);
@@ -3249,12 +3250,7 @@
}
// There is no local function within function that contains the
- // breakpoint token position. Resolve the breakpoint if necessary
- // and set the code breakpoints.
- if (!location->EnsureIsResolved(function, token_pos)) {
- // Failed to resolve breakpoint location for some reason
- return false;
- }
+ // breakpoint token position.
return true;
}
@@ -3262,6 +3258,27 @@
if (!function.is_debuggable()) {
return;
}
+ Function& resolved_function = Function::Handle(function.ptr());
+ // Synchronous generators have the form:
+ //
+ // user_func sync* {
+ // :sync_op_gen() {
+ // :sync_op(..) yielding {
+ // // ...
+ // }
+ // }
+ // }
+ //
+ // Setting a breakpoint in a sync* function should result in a code
+ // breakpoint being inserted into the synthetic :sync_op(..) function node.
+ // In order to ensure we're setting the breakpoint in the right function,
+ // we need to be able to check against the token positions of the
+ // non-synthetic function. Note, we only check for the innermost synthetic
+ // method as this is where the user's code will execute.
+ if (function.IsSyncGenClosure()) {
+ resolved_function ^= function.parent_function();
+ resolved_function ^= resolved_function.parent_function();
+ }
auto thread = Thread::Current();
auto zone = thread->zone();
@@ -3275,7 +3292,9 @@
RELEASE_ASSERT(thread->IsInStoppedMutatorsScope());
for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
BreakpointLocation* location = breakpoint_locations_.At(i);
- if (EnsureLocationIsInFunction(zone, function, location)) {
+ if (EnsureLocationIsInFunction(zone, resolved_function, location)) {
+ // Ensure the location is resolved for the original function.
+ location->EnsureIsResolved(function, location->token_pos());
if (FLAG_verbose_debug) {
Breakpoint* bpt = location->breakpoints();
while (bpt != NULL) {
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 34022eb..0a07b1e 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -346,7 +346,7 @@
DirectChainedHashMap<S> canonical_objects_;
};
-void ProgramVisitor::BindStaticCalls(Zone* zone, IsolateGroup* isolate_group) {
+void ProgramVisitor::BindStaticCalls(Thread* thread) {
class BindStaticCallsVisitor : public CodeVisitor {
public:
explicit BindStaticCallsVisitor(Zone* zone)
@@ -422,17 +422,19 @@
Code& target_code_;
};
- BindStaticCallsVisitor visitor(zone);
- WalkProgram(zone, isolate_group, &visitor);
+ StackZone stack_zone(thread);
+ BindStaticCallsVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
DECLARE_FLAG(charp, trace_precompiler_to);
DECLARE_FLAG(charp, write_v8_snapshot_profile_to);
-void ProgramVisitor::ShareMegamorphicBuckets(Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::ShareMegamorphicBuckets(Thread* thread) {
+ StackZone stack_zone(thread);
+ Zone* zone = thread->zone();
const GrowableObjectArray& table = GrowableObjectArray::Handle(
- zone, isolate_group->object_store()->megamorphic_cache_table());
+ zone, thread->isolate_group()->object_store()->megamorphic_cache_table());
if (table.IsNull()) return;
MegamorphicCache& cache = MegamorphicCache::Handle(zone);
@@ -562,9 +564,7 @@
typedef DirectChainedHashMap<StackMapEntryKeyIntValueTrait> StackMapEntryIntMap;
-void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(
- Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(Thread* thread) {
// Walks all the CSMs in Code objects and collects their entry information
// for consolidation.
class CollectStackMapEntriesVisitor : public CodeVisitor {
@@ -724,9 +724,10 @@
CompressedStackMaps& maps_;
};
- NormalizeAndDedupCompressedStackMapsVisitor dedup_visitor(zone,
- isolate_group);
- WalkProgram(zone, isolate_group, &dedup_visitor);
+ StackZone stack_zone(thread);
+ NormalizeAndDedupCompressedStackMapsVisitor visitor(thread->zone(),
+ thread->isolate_group());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class PcDescriptorsKeyValueTrait {
@@ -747,8 +748,7 @@
}
};
-void ProgramVisitor::DedupPcDescriptors(Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::DedupPcDescriptors(Thread* thread) {
class DedupPcDescriptorsVisitor
: public CodeVisitor,
public Dedupper<PcDescriptors, PcDescriptorsKeyValueTrait> {
@@ -771,8 +771,9 @@
PcDescriptors& pc_descriptor_;
};
- DedupPcDescriptorsVisitor visitor(zone);
- WalkProgram(zone, isolate_group, &visitor);
+ StackZone stack_zone(thread);
+ DedupPcDescriptorsVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class TypedDataKeyValueTrait {
@@ -801,8 +802,7 @@
bool IsCorrectType(const Object& obj) const { return obj.IsTypedData(); }
};
-void ProgramVisitor::DedupDeoptEntries(Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::DedupDeoptEntries(Thread* thread) {
class DedupDeoptEntriesVisitor : public CodeVisitor,
public TypedDataDedupper {
public:
@@ -836,13 +836,14 @@
};
if (FLAG_precompiled_mode) return;
- DedupDeoptEntriesVisitor visitor(zone);
- WalkProgram(zone, isolate_group, &visitor);
+
+ StackZone stack_zone(thread);
+ DedupDeoptEntriesVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
#if defined(DART_PRECOMPILER)
-void ProgramVisitor::DedupCatchEntryMovesMaps(Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::DedupCatchEntryMovesMaps(Thread* thread) {
class DedupCatchEntryMovesMapsVisitor : public CodeVisitor,
public TypedDataDedupper {
public:
@@ -861,8 +862,10 @@
};
if (!FLAG_precompiled_mode) return;
- DedupCatchEntryMovesMapsVisitor visitor(zone);
- WalkProgram(zone, isolate_group, &visitor);
+
+ StackZone stack_zone(thread);
+ DedupCatchEntryMovesMapsVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class UnlinkedCallKeyValueTrait {
@@ -883,8 +886,7 @@
}
};
-void ProgramVisitor::DedupUnlinkedCalls(Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::DedupUnlinkedCalls(Thread* thread) {
class DedupUnlinkedCallsVisitor
: public CodeVisitor,
public Dedupper<UnlinkedCall, UnlinkedCallKeyValueTrait> {
@@ -924,7 +926,8 @@
if (!FLAG_precompiled_mode) return;
- DedupUnlinkedCallsVisitor deduper(zone, isolate_group);
+ StackZone stack_zone(thread);
+ DedupUnlinkedCallsVisitor visitor(thread->zone(), thread->isolate_group());
// Note: in bare instructions mode we can still have object pools attached
// to code objects and these pools need to be deduplicated.
@@ -935,11 +938,11 @@
if (!FLAG_use_bare_instructions ||
FLAG_write_v8_snapshot_profile_to != nullptr ||
FLAG_trace_precompiler_to != nullptr) {
- WalkProgram(zone, isolate_group, &deduper);
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
}
-void ProgramVisitor::PruneSubclasses(Zone* zone, IsolateGroup* isolate_group) {
+void ProgramVisitor::PruneSubclasses(Thread* thread) {
class PruneSubclassesVisitor : public ClassVisitor {
public:
explicit PruneSubclassesVisitor(Zone* zone)
@@ -996,9 +999,10 @@
GrowableObjectArray& null_list_;
};
- PruneSubclassesVisitor visitor(zone);
- SafepointWriteRwLocker ml(Thread::Current(), isolate_group->program_lock());
- WalkProgram(zone, isolate_group, &visitor);
+ StackZone stack_zone(thread);
+ PruneSubclassesVisitor visitor(thread->zone());
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
#endif // defined(DART_PRECOMPILER)
@@ -1024,8 +1028,7 @@
}
};
-void ProgramVisitor::DedupCodeSourceMaps(Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::DedupCodeSourceMaps(Thread* thread) {
class DedupCodeSourceMapsVisitor
: public CodeVisitor,
public Dedupper<CodeSourceMap, CodeSourceMapKeyValueTrait> {
@@ -1048,8 +1051,9 @@
CodeSourceMap& code_source_map_;
};
- DedupCodeSourceMapsVisitor visitor(zone);
- WalkProgram(zone, isolate_group, &visitor);
+ StackZone stack_zone(thread);
+ DedupCodeSourceMapsVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class ArrayKeyValueTrait {
@@ -1078,7 +1082,7 @@
}
};
-void ProgramVisitor::DedupLists(Zone* zone, IsolateGroup* isolate_group) {
+void ProgramVisitor::DedupLists(Thread* thread) {
class DedupListsVisitor : public CodeVisitor,
public Dedupper<Array, ArrayKeyValueTrait> {
public:
@@ -1122,8 +1126,9 @@
Field& field_;
};
- DedupListsVisitor visitor(zone);
- WalkProgram(zone, isolate_group, &visitor);
+ StackZone stack_zone(thread);
+ DedupListsVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
// Traits for comparing two [Instructions] objects for equality, which is
@@ -1208,8 +1213,7 @@
};
#endif
-void ProgramVisitor::DedupInstructions(Zone* zone,
- IsolateGroup* isolate_group) {
+void ProgramVisitor::DedupInstructions(Thread* thread) {
class DedupInstructionsVisitor
: public CodeVisitor,
public Dedupper<Instructions, InstructionsKeyValueTrait>,
@@ -1297,33 +1301,31 @@
};
if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- DedupInstructionsWithSameMetadataVisitor visitor(zone);
- return WalkProgram(zone, isolate_group, &visitor);
+ StackZone stack_zone(thread);
+ DedupInstructionsWithSameMetadataVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
+ return;
}
#endif // defined(DART_PRECOMPILER)
- DedupInstructionsVisitor visitor(zone);
- WalkProgram(zone, isolate_group, &visitor);
+ StackZone stack_zone(thread);
+ DedupInstructionsVisitor visitor(thread->zone());
+ WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
void ProgramVisitor::Dedup(Thread* thread) {
- auto const isolate_group = thread->isolate_group();
- StackZone stack_zone(thread);
- HANDLESCOPE(thread);
- auto const zone = thread->zone();
-
- BindStaticCalls(zone, isolate_group);
- ShareMegamorphicBuckets(zone, isolate_group);
- NormalizeAndDedupCompressedStackMaps(zone, isolate_group);
- DedupPcDescriptors(zone, isolate_group);
- DedupDeoptEntries(zone, isolate_group);
+ BindStaticCalls(thread);
+ ShareMegamorphicBuckets(thread);
+ NormalizeAndDedupCompressedStackMaps(thread);
+ DedupPcDescriptors(thread);
+ DedupDeoptEntries(thread);
#if defined(DART_PRECOMPILER)
- DedupCatchEntryMovesMaps(zone, isolate_group);
- DedupUnlinkedCalls(zone, isolate_group);
- PruneSubclasses(zone, isolate_group);
+ DedupCatchEntryMovesMaps(thread);
+ DedupUnlinkedCalls(thread);
+ PruneSubclasses(thread);
#endif
- DedupCodeSourceMaps(zone, isolate_group);
- DedupLists(zone, isolate_group);
+ DedupCodeSourceMaps(thread);
+ DedupLists(thread);
// Reduces binary size but obfuscates profiler results.
if (FLAG_dedup_instructions) {
@@ -1346,7 +1348,7 @@
if (FLAG_precompiled_mode && !FLAG_use_bare_instructions) return;
#endif
- DedupInstructions(zone, isolate_group);
+ DedupInstructions(thread);
}
}
@@ -1419,8 +1421,7 @@
void ProgramVisitor::AssignUnits(Thread* thread) {
StackZone stack_zone(thread);
- HANDLESCOPE(thread);
- Zone* zone = thread->zone();
+ Zone* zone = stack_zone.GetZone();
// VM stubs.
Instructions& inst = Instructions::Handle(zone);
diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h
index fa57326..b743e0a 100644
--- a/runtime/vm/program_visitor.h
+++ b/runtime/vm/program_visitor.h
@@ -106,20 +106,19 @@
#endif
private:
- static void BindStaticCalls(Zone* zone, IsolateGroup* isolate_group);
- static void ShareMegamorphicBuckets(Zone* zone, IsolateGroup* isolate_group);
- static void NormalizeAndDedupCompressedStackMaps(Zone* zone,
- IsolateGroup* isolate_group);
- static void DedupPcDescriptors(Zone* zone, IsolateGroup* isolate_group);
- static void DedupDeoptEntries(Zone* zone, IsolateGroup* isolate_group);
+ static void BindStaticCalls(Thread* thread);
+ static void ShareMegamorphicBuckets(Thread* thread);
+ static void NormalizeAndDedupCompressedStackMaps(Thread* thread);
+ static void DedupPcDescriptors(Thread* thread);
+ static void DedupDeoptEntries(Thread* thread);
#if defined(DART_PRECOMPILER)
- static void DedupCatchEntryMovesMaps(Zone* zone, IsolateGroup* isolate_group);
- static void DedupUnlinkedCalls(Zone* zone, IsolateGroup* isolate_group);
- static void PruneSubclasses(Zone* zone, IsolateGroup* isolate_group);
+ static void DedupCatchEntryMovesMaps(Thread* thread);
+ static void DedupUnlinkedCalls(Thread* thread);
+ static void PruneSubclasses(Thread* thread);
#endif
- static void DedupCodeSourceMaps(Zone* zone, IsolateGroup* isolate_group);
- static void DedupLists(Zone* zone, IsolateGroup* isolate_group);
- static void DedupInstructions(Zone* zone, IsolateGroup* isolate_group);
+ static void DedupCodeSourceMaps(Thread* thread);
+ static void DedupLists(Thread* thread);
+ static void DedupInstructions(Thread* thread);
};
} // namespace dart
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index b2545cf..7a966ac 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -403,7 +403,8 @@
desc.info.declaration_pos = context_scope.DeclarationTokenIndexAt(i);
desc.info.begin_pos = begin_token_pos();
desc.info.end_pos = end_token_pos();
- ASSERT(desc.info.begin_pos <= desc.info.end_pos);
+ ASSERT((desc.info.begin_pos.IsReal() != desc.info.end_pos.IsReal()) ||
+ (desc.info.begin_pos <= desc.info.end_pos));
desc.info.set_index(context_scope.ContextIndexAt(i));
vars.Add(desc);
}
diff --git a/tools/VERSION b/tools/VERSION
index 259aa5b..ac3e141 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 50
+PRERELEASE 51
PRERELEASE_PATCH 0
\ No newline at end of file