Version 2.16.0-1.0.dev
Merge commit '8bdae002f165883312a82b7549517930bfa6fe75' into 'dev'
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 29f89fc..980ace6 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -50,8 +50,8 @@
String get oldName => canRename.refactoringElement.element.displayName;
RenameResponse? computeRenameRanges() {
- var matches = canRename._fileResolver.findReferences(
- canRename.refactoringElement.element, canRename.filePath);
+ var matches = canRename._fileResolver
+ .findReferences(canRename.refactoringElement.element);
return RenameResponse(matches, this);
}
}
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 24876d2..3ec3691 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -185,25 +185,34 @@
removedCacheIds.addAll(libraryContext!.collectSharedDataIdentifiers());
}
- /// Looks for references to the given Element in the path. All the
- /// files currently cached by the resolver are searched, generated files are
- /// ignored.
- List<CiderSearchMatch> findReferences(Element element, String path,
+ /// Looks for references to the given Element. All the files currently
+ /// cached by the resolver are searched, generated files are ignored.
+ List<CiderSearchMatch> findReferences(Element element,
{OperationPerformanceImpl? performance}) {
var references = <CiderSearchMatch>[];
- // TODO(keertip): check if element is named constructor.
- var result = fsState!.getFilesContaining(element.displayName);
- result.forEach((filePath) {
- var resolved = resolve(path: filePath);
+
+ void collectReferences(String path) {
+ var resolved = resolve(path: path);
var collector = ReferencesCollector(element);
resolved.unit.accept(collector);
var offsets = collector.offsets;
if (offsets.isNotEmpty) {
var lineInfo = resolved.unit.lineInfo;
- references.add(CiderSearchMatch(filePath,
+ references.add(CiderSearchMatch(path,
offsets.map((offset) => lineInfo?.getLocation(offset)).toList()));
}
- });
+ }
+
+ // TODO(keertip): check if element is named constructor.
+ if (element is LocalVariableElement ||
+ (element is ParameterElement && !element.isNamed)) {
+ collectReferences(element.source!.fullName);
+ } else {
+ var result = fsState!.getFilesContaining(element.displayName);
+ result.forEach((filePath) {
+ collectReferences(filePath);
+ });
+ }
return references;
}
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 0c8f774..95f08a1 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -16,6 +16,7 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart' as file_system;
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/constant/compute.dart';
@@ -368,11 +369,26 @@
isNonNullableByDefault: libraryElement.isNonNullableByDefault,
);
+ var evaluationEngine = ConstantEvaluationEngine(
+ declaredVariables: declaredVariables,
+ isNonNullableByDefault: isEnabled(Feature.non_nullable),
+ );
+
+ var dependencies = <ConstantEvaluationTarget>[];
+ node.accept(
+ ReferenceFinder(dependencies.add),
+ );
+
+ computeConstants(
+ typeProvider,
+ typeSystem,
+ declaredVariables,
+ dependencies,
+ libraryElement.featureSet as ExperimentStatus,
+ );
+
var visitor = ConstantVisitor(
- ConstantEvaluationEngine(
- declaredVariables: declaredVariables,
- isNonNullableByDefault: isEnabled(Feature.non_nullable),
- ),
+ evaluationEngine,
libraryElement,
errorReporter,
);
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 3b59012..0b35e99 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -394,7 +394,7 @@
''');
await resolveFile(bPath);
- var result = fileResolver.findReferences(_findElement(6, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(6, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(bPath, [CharacterLocation(4, 11)]),
CiderSearchMatch(aPath, [CharacterLocation(1, 7)])
@@ -415,7 +415,7 @@
''');
await resolveFile(aPath);
- var result = fileResolver.findReferences(_findElement(16, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(16, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(
aPath, [CharacterLocation(2, 7), CharacterLocation(5, 5)])
@@ -434,7 +434,7 @@
''');
await resolveFile(aPath);
- var result = fileResolver.findReferences(_findElement(11, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(11, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(
aPath, [CharacterLocation(2, 3), CharacterLocation(5, 1)])
@@ -460,7 +460,7 @@
''');
await resolveFile(bPath);
- var result = fileResolver.findReferences(_findElement(20, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(20, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(bPath, [CharacterLocation(5, 15)]),
CiderSearchMatch(aPath, [CharacterLocation(2, 11)])
@@ -479,7 +479,7 @@
}
''');
await resolveFile(aPath);
- var result = fileResolver.findReferences(_findElement(39, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(39, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(
aPath, [CharacterLocation(3, 9), CharacterLocation(4, 11)])
@@ -512,7 +512,7 @@
''');
await resolveFile(bPath);
- var result = fileResolver.findReferences(_findElement(17, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(17, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(bPath, [CharacterLocation(5, 5)]),
CiderSearchMatch(
@@ -539,7 +539,7 @@
''');
await resolveFile(bPath);
- var result = fileResolver.findReferences(_findElement(21, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(21, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(bPath, [CharacterLocation(5, 5)]),
CiderSearchMatch(aPath, [CharacterLocation(2, 12)])
@@ -566,7 +566,7 @@
''');
await resolveFile(bPath);
- var result = fileResolver.findReferences(_findElement(19, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(19, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(bPath, [CharacterLocation(4, 13)]),
CiderSearchMatch(aPath, [CharacterLocation(3, 9)])
@@ -593,7 +593,7 @@
''');
await resolveFile(bPath);
- var result = fileResolver.findReferences(_findElement(20, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(20, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(bPath, [CharacterLocation(4, 3)]),
CiderSearchMatch(aPath, [CharacterLocation(3, 10)])
@@ -613,7 +613,7 @@
''');
await resolveFile(aPath);
- var result = fileResolver.findReferences(_findElement(10, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(10, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(
aPath, [CharacterLocation(1, 11), CharacterLocation(4, 11)])
@@ -631,7 +631,7 @@
}
''');
await resolveFile(aPath);
- var result = fileResolver.findReferences(_findElement(10, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(10, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(aPath, [
CharacterLocation(1, 11),
@@ -659,7 +659,7 @@
''');
await resolveFile(bPath);
- var result = fileResolver.findReferences(_findElement(8, aPath), aPath);
+ var result = fileResolver.findReferences(_findElement(8, aPath));
var expected = <CiderSearchMatch>[
CiderSearchMatch(bPath, [CharacterLocation(3, 8)]),
CiderSearchMatch(aPath, [CharacterLocation(1, 9)])
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 4212464..5beaead 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -488,6 +488,29 @@
expect(result.value!.toIntValue(), 3);
}
+ test_hasValue_constantReference() async {
+ await resolve('''
+const a = 42;
+var x = a;
+''');
+ var result = _evaluateX();
+ expect(result.errors, isEmpty);
+ expect(result.value!.toIntValue(), 42);
+ }
+
+ test_hasValue_constantReference_imported() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+const a = 42;
+''');
+ await resolve('''
+import 'a.dart';
+var x = a;
+''');
+ var result = _evaluateX();
+ expect(result.errors, isEmpty);
+ expect(result.value!.toIntValue(), 42);
+ }
+
test_hasValue_intLiteral() async {
await resolve('''
var x = 42;
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 3569eb9..f3bb2bd 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -111,9 +111,8 @@
// We have to check whether the reciever has the same isolate group (e.g.
// native message handlers such as an IOService handler does not but does
// share the same origin port).
- const bool same_group =
- FLAG_enable_isolate_groups && PortMap::IsReceiverInThisIsolateGroup(
- destination_port_id, isolate->group());
+ const bool same_group = PortMap::IsReceiverInThisIsolateGroup(
+ destination_port_id, isolate->group());
// TODO(turnidge): Throw an exception when the return value is false?
PortMap::PostMessage(WriteMessage(can_send_any_object, same_group, obj,
destination_port_id,
@@ -639,7 +638,7 @@
ASSERT(name != nullptr);
auto group = state_->isolate_group();
- if (!FLAG_enable_isolate_groups || group == nullptr) {
+ if (group == nullptr) {
RunHeavyweight(name);
} else {
RunLightweight(name);
@@ -676,8 +675,7 @@
}
void RunLightweight(const char* name) {
- // The create isolate initialize callback is mandatory if
- // --enable-isolate-groups was passed.
+ // The create isolate initialize callback is mandatory.
auto initialize_callback = Isolate::InitializeCallback();
if (initialize_callback == nullptr) {
FailedSpawn(
@@ -934,22 +932,16 @@
const auto& func = Function::Handle(zone, GetTopLevelFunction(zone, closure));
PersistentHandle* closure_tuple_handle = nullptr;
if (func.IsNull()) {
- if (!FLAG_enable_isolate_groups) {
- const String& msg = String::Handle(String::New(
- "Isolate.spawn expects to be passed a static or top-level function"));
- Exceptions::ThrowArgumentError(msg);
- } else {
- // We have a non-toplevel closure that we might need to copy.
- // Result will be [<closure-copy>, <objects-in-msg-to-rehash>]
- const auto& closure_copy_tuple = Object::Handle(
- zone, CopyMutableObjectGraph(closure)); // Throws if it fails.
- ASSERT(closure_copy_tuple.IsArray());
- ASSERT(Object::Handle(zone, Array::Cast(closure_copy_tuple).At(0))
- .IsClosure());
- closure_tuple_handle =
- isolate->group()->api_state()->AllocatePersistentHandle();
- closure_tuple_handle->set_ptr(closure_copy_tuple.ptr());
- }
+ // We have a non-toplevel closure that we might need to copy.
+ // Result will be [<closure-copy>, <objects-in-msg-to-rehash>]
+ const auto& closure_copy_tuple = Object::Handle(
+ zone, CopyMutableObjectGraph(closure)); // Throws if it fails.
+ ASSERT(closure_copy_tuple.IsArray());
+ ASSERT(Object::Handle(zone, Array::Cast(closure_copy_tuple).At(0))
+ .IsClosure());
+ closure_tuple_handle =
+ isolate->group()->api_state()->AllocatePersistentHandle();
+ closure_tuple_handle->set_ptr(closure_copy_tuple.ptr());
}
bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value();
@@ -960,9 +952,8 @@
// serializable this will throw an exception.
SerializedObjectBuffer message_buffer;
message_buffer.set_message(WriteMessage(
- /* can_send_any_object */ true,
- /* same_group */ FLAG_enable_isolate_groups, message, ILLEGAL_PORT,
- Message::kNormalPriority));
+ /*can_send_any_object=*/true,
+ /*same_group=*/true, message, ILLEGAL_PORT, Message::kNormalPriority));
const char* utf8_package_config =
packageConfig.IsNull() ? NULL : String2UTF8(packageConfig);
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index c8b3774..077e9bd 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -850,7 +850,7 @@
r'^<asynchronous suspension>$',
r'^#1 asyncStarThrowAsync \(.*/utils.dart:126(:5)?\)$',
r'^<asynchronous suspension>$',
- r'^#2 listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart(:0)?\)$',
+ r'^#2 listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart:132(:56)?\)$',
r'^<asynchronous suspension>$',
];
await doTestAwait(
diff --git a/runtime/tests/vm/dart_2/causal_stacks/utils.dart b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
index cd46b03..a17cade 100644
--- a/runtime/tests/vm/dart_2/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
@@ -852,7 +852,7 @@
r'^<asynchronous suspension>$',
r'^#1 asyncStarThrowAsync \(.*/utils.dart:128(:5)?\)$',
r'^<asynchronous suspension>$',
- r'^#2 listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart(:0)?\)$',
+ r'^#2 listenAsyncStarThrowAsync.<anonymous closure> \(.+/utils.dart:134(:56)?\)$',
r'^<asynchronous suspension>$',
];
await doTestAwait(
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index dd8bc1d..87625f3 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -417,6 +417,14 @@
}
}
+void CodeSourceMapBuilder::WriteFunctionEntrySourcePosition(
+ const InstructionSource& source) {
+ ASSERT(written_pc_offset_ == 0 && buffered_pc_offset_ == 0);
+ ASSERT(stream_.bytes_written() == 0);
+ WriteChangePosition(source.token_pos);
+ WriteAdvancePC(0);
+}
+
void CodeSourceMapBuilder::BeginCodeSourceRange(
int32_t pc_offset,
const InstructionSource& source) {
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index ac29be7..bd0d358 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -246,6 +246,7 @@
void NoteNullCheck(int32_t pc_offset,
const InstructionSource& source,
intptr_t name_index);
+ void WriteFunctionEntrySourcePosition(const InstructionSource& source);
// If source is from an inlined call, returns the token position of the
// original call in the root function, otherwise the source's token position.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index d8ce910..88106b2 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -560,6 +560,53 @@
return false;
}
+void FlowGraphCompiler::EmitFunctionEntrySourcePositionDescriptorIfNeeded() {
+ // When unwinding async stacks we might produce frames which correspond
+ // to future listeners which are going to be called when the future completes.
+ // These listeners are not yet called and thus their frame pc_offset is set
+ // to 0 - which does not actually correspond to any call- or yield- site
+ // inside the code object. Nevertheless we would like to be able to
+ // produce proper position information for it when symbolizing the stack.
+ // To achieve that in AOT mode (where we don't actually have
+ // |Function::token_pos| available) we instead emit an artificial descriptor
+ // at the very beginning of the function.
+ if (FLAG_precompiled_mode && flow_graph().function().IsClosureFunction()) {
+ code_source_map_builder_->WriteFunctionEntrySourcePosition(
+ InstructionSource(flow_graph().function().token_pos()));
+ }
+}
+
+void FlowGraphCompiler::CompileGraph() {
+ InitCompiler();
+
+#if !defined(TARGET_ARCH_IA32)
+ // For JIT we have multiple entrypoints functionality which moved the frame
+ // setup into the [TargetEntryInstr] (which will set the constant pool
+ // allowed bit to true). Despite this we still have to set the
+ // constant pool allowed bit to true here as well, because we can generate
+ // code for [CatchEntryInstr]s, which need the pool.
+ assembler()->set_constant_pool_allowed(true);
+#endif
+
+ EmitFunctionEntrySourcePositionDescriptorIfNeeded();
+ VisitBlocks();
+
+#if defined(DEBUG)
+ assembler()->Breakpoint();
+#endif
+
+ if (!skip_body_compilation()) {
+#if !defined(TARGET_ARCH_IA32)
+ ASSERT(assembler()->constant_pool_allowed());
+#endif
+ GenerateDeferredCode();
+ }
+
+ for (intptr_t i = 0; i < indirect_gotos_.length(); ++i) {
+ indirect_gotos_[i]->ComputeOffsetTable(this);
+ }
+}
+
void FlowGraphCompiler::VisitBlocks() {
CompactBlocks();
if (compiler::Assembler::EmittingComments()) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 7669e78..98488ae 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -559,6 +559,8 @@
void VisitBlocks();
+ void EmitFunctionEntrySourcePositionDescriptorIfNeeded();
+
// Bail out of the flow graph compiler. Does not return to the caller.
void Bailout(const char* reason);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index fbe3e61..ac4e0f8 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -382,38 +382,6 @@
EndCodeSourceRange(PrologueSource());
}
-// Input parameters:
-// LR: return address.
-// SP: address of last argument.
-// FP: caller's frame pointer.
-// PP: caller's pool pointer.
-// R4: arguments descriptor array.
-void FlowGraphCompiler::CompileGraph() {
- InitCompiler();
-
- // For JIT we have multiple entrypoints functionality which moved the frame
- // setup into the [TargetEntryInstr] (which will set the constant pool
- // allowed bit to true). Despite this we still have to set the
- // constant pool allowed bit to true here as well, because we can generate
- // code for [CatchEntryInstr]s, which need the pool.
- __ set_constant_pool_allowed(true);
-
- VisitBlocks();
-
-#if defined(DEBUG)
- __ bkpt(0);
-#endif
-
- if (!skip_body_compilation()) {
- ASSERT(assembler()->constant_pool_allowed());
- GenerateDeferredCode();
- }
-
- for (intptr_t i = 0; i < indirect_gotos_.length(); ++i) {
- indirect_gotos_[i]->ComputeOffsetTable(this);
- }
-}
-
void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
ASSERT(!stub.IsNull());
if (CanPcRelativeCall(stub)) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index fdbf099..233821a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -372,38 +372,6 @@
EndCodeSourceRange(PrologueSource());
}
-// Input parameters:
-// LR: return address.
-// SP: address of last argument.
-// FP: caller's frame pointer.
-// PP: caller's pool pointer.
-// R4: arguments descriptor array.
-void FlowGraphCompiler::CompileGraph() {
- InitCompiler();
-
- // For JIT we have multiple entrypoints functionality which moved the frame
- // setup into the [TargetEntryInstr] (which will set the constant pool
- // allowed bit to true). Despite this we still have to set the
- // constant pool allowed bit to true here as well, because we can generate
- // code for [CatchEntryInstr]s, which need the pool.
- __ set_constant_pool_allowed(true);
-
- VisitBlocks();
-
-#if defined(DEBUG)
- __ brk(0);
-#endif
-
- if (!skip_body_compilation()) {
- ASSERT(assembler()->constant_pool_allowed());
- GenerateDeferredCode();
- }
-
- for (intptr_t i = 0; i < indirect_gotos_.length(); ++i) {
- indirect_gotos_[i]->ComputeOffsetTable(this);
- }
-}
-
void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
ASSERT(!stub.IsNull());
if (CanPcRelativeCall(stub)) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 0b232dd..d613572 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -459,24 +459,6 @@
EndCodeSourceRange(PrologueSource());
}
-void FlowGraphCompiler::CompileGraph() {
- InitCompiler();
-
- ASSERT(!block_order().is_empty());
- VisitBlocks();
-
- if (!skip_body_compilation()) {
-#if defined(DEBUG)
- __ int3();
-#endif
- GenerateDeferredCode();
- }
-
- for (intptr_t i = 0; i < indirect_gotos_.length(); ++i) {
- indirect_gotos_[i]->ComputeOffsetTable(this);
- }
-}
-
void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
if (stub.InVMIsolateHeap()) {
__ CallVmStub(stub);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 573add6..3abdf84 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -378,33 +378,6 @@
EndCodeSourceRange(PrologueSource());
}
-void FlowGraphCompiler::CompileGraph() {
- InitCompiler();
-
- // We have multiple entrypoints functionality which moved the frame
- // setup into the [FunctionEntryInstr] (which will set the constant pool
- // allowed bit to true). Despite this we still have to set the
- // constant pool allowed bit to true here as well, because we can generate
- // code for [CatchEntryInstr]s, which need the pool.
- __ set_constant_pool_allowed(true);
-
- ASSERT(!block_order().is_empty());
- VisitBlocks();
-
-#if defined(DEBUG)
- __ int3();
-#endif
-
- if (!skip_body_compilation()) {
- ASSERT(assembler()->constant_pool_allowed());
- GenerateDeferredCode();
- }
-
- for (intptr_t i = 0; i < indirect_gotos_.length(); ++i) {
- indirect_gotos_[i]->ComputeOffsetTable(this);
- }
-}
-
void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
ASSERT(!stub.IsNull());
if (CanPcRelativeCall(stub)) {
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 1ec2adc..5b08899 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -211,7 +211,7 @@
ASSERT(thread->IsMutatorThread());
const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
- if (FLAG_enable_isolate_groups) {
+ {
// Another isolate's mutator thread may have created [function] and
// published it via an ICData, MegamorphicCache etc. Entering the lock below
// is an acquire operation that pairs with the release operation when the
@@ -220,12 +220,6 @@
SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
}
- // In single-isolate scenarios the lazy compile stub is only invoked if
- // there's no existing code. In multi-isolate scenarios with shared JITed code
- // we can end up in the lazy compile runtime entry here with code being
- // installed.
- ASSERT(!function.HasCode() || FLAG_enable_isolate_groups);
-
// Will throw if compilation failed (e.g. with compile-time error).
function.EnsureHasCode();
}
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 1c7026a..88dc441 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1463,13 +1463,6 @@
*error = nullptr;
- if (!FLAG_enable_isolate_groups) {
- *error = Utils::StrDup(
- "Lightweight isolates need to be explicitly enabled by passing "
- "--enable-isolate-groups.");
- return nullptr;
- }
-
Isolate* isolate;
isolate = CreateWithinExistingIsolateGroup(member->group(), name, error);
if (isolate != nullptr) {
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index 4f98848..d661bd7 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -717,6 +717,26 @@
function_stack.Clear();
token_positions.Clear();
+ // CodeSourceMap might start in the following way:
+ //
+ // ChangePosition function.token_pos()
+ // AdvancePC 0
+ // ChangePosition x
+ // AdvancePC y
+ //
+ // This entry is emitted to ensure correct symbolization of
+ // function listener frames produced by async unwinding.
+ // (See EmitFunctionEntrySourcePositionDescriptorIfNeeded).
+ // Directly interpreting this sequence would cause us to emit
+ // multiple with the same pc into line number table and different
+ // position information. To avoid this will make an adjustment for
+ // the second record we emit: if position x is a synthetic one we will
+ // simply drop the second record, if position x is real then we will
+ // emit row with a slightly adjusted PC (by 1 byte). This would not
+ // affect symbolization (you can't have a call that is 1 byte long)
+ // but will avoid line number table entries with the same PC.
+ bool function_entry_position_was_emitted = false;
+
int32_t current_pc_offset = 0;
function_stack.Add(&root_function);
token_positions.Add(kNoDwarfPositionInfo);
@@ -740,9 +760,30 @@
const intptr_t file = LookupScript(script);
const intptr_t line = token_positions.Last().line();
const intptr_t column = token_positions.Last().column();
- writer->EmitRow(file, line, column, asm_name, current_pc_offset);
+ intptr_t pc_offset_adjustment = 0;
+ bool should_emit = true;
+
+ // If we are at the function entry and have already emitted a row
+ // then adjust current_pc_offset to avoid duplicated entries.
+ // See the comment below which explains why this code is here.
+ if (current_pc_offset == 0 && function_entry_position_was_emitted) {
+ pc_offset_adjustment = 1;
+ // Ignore synthetic positions. Function entry position gives
+ // more information anyway.
+ should_emit = !(line == 0 && column == 0);
+ }
+
+ if (should_emit) {
+ writer->EmitRow(file, line, column, asm_name,
+ current_pc_offset + pc_offset_adjustment);
+ }
current_pc_offset += arg1;
+ if (arg1 == 0) { // Special case of AdvancePC 0.
+ ASSERT(current_pc_offset == 0);
+ ASSERT(!function_entry_position_was_emitted);
+ function_entry_position_was_emitted = true;
+ }
break;
}
case CodeSourceMapOps::kPushFunction: {
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 224a6b1..eccc2ac 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -194,7 +194,6 @@
P(retain_code_objects, bool, true, \
"Serialize all code objects even if not otherwise " \
"needed in the precompiled runtime.") \
- P(enable_isolate_groups, bool, true, "Enable isolate group support.") \
P(show_invisible_frames, bool, false, \
"Show invisible frames in stack traces.") \
D(trace_cha, bool, false, "Trace CHA operations") \
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index b30bf66..c45765c 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -574,9 +574,6 @@
};
VM_UNIT_TEST_CASE(CleanupBequestNeverReceived) {
- // This test uses features from isolate groups
- FLAG_enable_isolate_groups = true;
-
const char* TEST_MESSAGE = "hello, world";
Dart_Isolate parent = TestCase::CreateTestIsolate("parent");
EXPECT_EQ(parent, Dart_CurrentIsolate());
@@ -608,9 +605,6 @@
}
VM_UNIT_TEST_CASE(ReceivesSendAndExitMessage) {
- // This test uses features from isolate groups
- FLAG_enable_isolate_groups = true;
-
const char* TEST_MESSAGE = "hello, world";
Dart_Isolate parent = TestCase::CreateTestIsolate("parent");
EXPECT_EQ(parent, Dart_CurrentIsolate());
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index ef5cdad..34521bc 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2673,11 +2673,9 @@
Dart::thread_pool()->Run<ShutdownGroupTask>(isolate_group);
}
} else {
- if (FLAG_enable_isolate_groups) {
- // TODO(dartbug.com/36097): An isolate just died. A significant amount of
- // memory might have become unreachable. We should evaluate how to best
- // inform the GC about this situation.
- }
+ // TODO(dartbug.com/36097): An isolate just died. A significant amount of
+ // memory might have become unreachable. We should evaluate how to best
+ // inform the GC about this situation.
}
} // namespace dart
@@ -2842,11 +2840,6 @@
auto thread = Thread::Current();
StoppedMutatorsScope stopped_mutators_scope(thread);
- if (thread->IsMutatorThread() && !FLAG_enable_isolate_groups) {
- single_current_mutator->Call();
- return;
- }
-
if (thread->IsAtSafepoint()) {
RELEASE_ASSERT(safepoint_handler()->IsOwnedByTheThread(thread));
single_current_mutator->Call();
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index e272c5c..fd8822c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -25851,6 +25851,15 @@
// A visible frame ends any gap we might be in.
in_gap = false;
+ // Zero pc_offset can only occur in the frame produced by the async
+ // unwinding and it corresponds to the next future listener in the
+ // chain. This function is not yet called (it will be called when
+ // the future completes) hence pc_offset is set to 0. This frame
+ // is very different from other frames which have pc_offsets
+ // corresponding to call- or yield-sites in the generated code and
+ // should be handled specially.
+ const bool is_future_listener = pc_offset == 0;
+
#if defined(DART_PRECOMPILED_RUNTIME)
// When printing non-symbolic frames, we normally print call
// addresses, not return addresses, by subtracting one from the PC to
@@ -25861,7 +25870,6 @@
// is invoked with the value of the resolved future. Thus, we must
// report the return address, as returning a value before the closure
// payload will cause failures to decode the frame using DWARF info.
- const bool is_future_listener = pc_offset == 0;
const uword call_addr = is_future_listener ? pc : pc - 1;
if (FLAG_dwarf_stack_traces_mode) {
@@ -25887,7 +25895,11 @@
}
#endif
- if (code.is_optimized() && stack_trace.expand_inlined()) {
+ if (code.is_optimized() && stack_trace.expand_inlined() &&
+ (FLAG_precompiled_mode || !is_future_listener)) {
+ // Note: In AOT mode EmitFunctionEntrySourcePositionDescriptorIfNeeded
+ // will take care of emitting a descriptor that would allow us to
+ // symbolize stack frame with 0 offset.
code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions,
&inlined_token_positions);
ASSERT(inlined_functions.length() >= 1);
@@ -25901,7 +25913,8 @@
continue;
}
- auto const pos = code.GetTokenIndexOfPC(pc);
+ auto const pos = is_future_listener ? function.token_pos()
+ : code.GetTokenIndexOfPC(pc);
PrintSymbolicStackFrame(zone, &buffer, function, pos, frame_index);
frame_index++;
}
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 549dd9b..c693c02 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -869,9 +869,6 @@
new_cache.WriteEntryToBuffer(zone, &buffer, colliding_index, " ");
THR_Print("%s\n", buffer.buffer());
}
- if (!FLAG_enable_isolate_groups) {
- FATAL("Duplicate subtype test cache entry");
- }
if (old_result.ptr() != result.ptr()) {
FATAL("Existing subtype test cache entry has result %s, not %s",
old_result.ToCString(), result.ToCString());
@@ -1246,9 +1243,6 @@
const Code& target_code = Code::Handle(zone, target_function.EnsureHasCode());
// Before patching verify that we are not repeatedly patching to the same
// target.
- ASSERT(FLAG_enable_isolate_groups ||
- target_code.ptr() != CodePatcher::GetStaticCallTargetAt(
- caller_frame->pc(), caller_code));
if (target_code.ptr() !=
CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)) {
GcSafepointOperationScope safepoint(thread);
@@ -3018,10 +3012,6 @@
current_target_code.EntryPoint(),
current_target_code.is_optimized() ? "optimized" : "unoptimized");
}
- // With isolate groups enabled, it is possible that the target code
- // has been deactivated just now(as a result of re-optimizatin for example),
- // which will result in another run through FixCallersTarget.
- ASSERT(!current_target_code.IsDisabled() || FLAG_enable_isolate_groups);
arguments.SetReturn(current_target_code);
#else
UNREACHABLE();
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 673f26e..a60edfa 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -401,11 +401,6 @@
// cases.
if (thread->IsAtSafepoint()) {
RELEASE_ASSERT(group->safepoint_handler()->IsOwnedByTheThread(thread));
- // In DEBUG mode the snapshot writer also calls this method inside a
- // safepoint.
-#if !defined(DEBUG)
- RELEASE_ASSERT(FLAG_enable_isolate_groups || !USING_PRODUCT);
-#endif
data = object_store->symbol_table();
CanonicalStringSet table(&key, &value, &data);
symbol ^= table.GetOrNull(str);
diff --git a/tools/VERSION b/tools/VERSION
index 859524f..3fdef2c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 16
PATCH 0
-PRERELEASE 0
+PRERELEASE 1
PRERELEASE_PATCH 0
\ No newline at end of file