[vm] Bug fix in dedup optimization when build deferred components.

Closes https://github.com/dart-lang/sdk/pull/49393

TEST=vm/dart{,_2}/regress_49372

Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-product-x64-try
GitOrigin-RevId: c6306f96ae2bafa25c45e5c7a818c71eb72d8d12
Bug: https://github.com/dart-lang/sdk/issues/49372
Change-Id: I7ec4b170819321cb74037e475006890259446744
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250720
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
This commit is contained in:
方哲源 2022-07-06 11:04:10 +00:00 committed by Commit Bot
parent 1b8cae19a6
commit 6b04cac19d
10 changed files with 141 additions and 35 deletions

View file

@ -0,0 +1,12 @@
// Copyright (c) 2022, 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.
// Regression test for https://github.com/dart-lang/sdk/issues/49372.
// Verifies that dedup optimization doesn't merge Code from different unit.
@pragma('vm:never-inline')
int foo() => 10;
@pragma('vm:never-inline')
int bar() => foo() + 2;

View file

@ -0,0 +1,21 @@
// Copyright (c) 2022, 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.
// Regression test for https://github.com/dart-lang/sdk/issues/49372.
// Verifies that dedup optimization doesn't merge Code from different unit.
import 'package:expect/expect.dart';
import 'regress_49372_deferred.dart' deferred as lib;
@pragma('vm:never-inline')
int foo() => 10;
@pragma('vm:never-inline')
int bar() => foo() + 7;
void main() async {
await lib.loadLibrary();
Expect.equals(12, lib.bar());
Expect.equals(17, bar());
}

View file

@ -0,0 +1,14 @@
// Copyright (c) 2022, 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.
// Regression test for https://github.com/dart-lang/sdk/issues/49372.
// Verifies that dedup optimization doesn't merge Code from different unit.
// @dart = 2.9
@pragma('vm:never-inline')
int foo() => 10;
@pragma('vm:never-inline')
int bar() => foo() + 2;

View file

@ -0,0 +1,23 @@
// Copyright (c) 2022, 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.
// Regression test for https://github.com/dart-lang/sdk/issues/49372.
// Verifies that dedup optimization doesn't merge Code from different unit.
// @dart = 2.9
import 'package:expect/expect.dart';
import 'regress_49372_deferred.dart' deferred as lib;
@pragma('vm:never-inline')
int foo() => 10;
@pragma('vm:never-inline')
int bar() => foo() + 7;
void main() async {
await lib.loadLibrary();
Expect.equals(12, lib.bar());
Expect.equals(17, bar());
}

View file

@ -3606,49 +3606,21 @@ void FlowGraphCompiler::EmitMoveFromNative(
}
}
// The assignment to loading units here must match that in
// AssignLoadingUnitsCodeVisitor, which runs after compilation is done.
static intptr_t LoadingUnitOf(Zone* zone, const Function& function) {
const Class& cls = Class::Handle(zone, function.Owner());
const Library& lib = Library::Handle(zone, cls.library());
const LoadingUnit& unit = LoadingUnit::Handle(zone, lib.loading_unit());
ASSERT(!unit.IsNull());
return unit.id();
}
static intptr_t LoadingUnitOf(Zone* zone, const Code& code) {
// No WeakSerializationReference owners here because those are only
// introduced during AOT serialization.
if (code.IsStubCode() || code.IsTypeTestStubCode()) {
return LoadingUnit::kRootId;
} else if (code.IsAllocationStubCode()) {
const Class& cls = Class::Cast(Object::Handle(zone, code.owner()));
const Library& lib = Library::Handle(zone, cls.library());
const LoadingUnit& unit = LoadingUnit::Handle(zone, lib.loading_unit());
ASSERT(!unit.IsNull());
return unit.id();
} else if (code.IsFunctionCode()) {
return LoadingUnitOf(zone,
Function::Cast(Object::Handle(zone, code.owner())));
} else {
UNREACHABLE();
return LoadingUnit::kIllegalId;
}
}
bool FlowGraphCompiler::CanPcRelativeCall(const Function& target) const {
return FLAG_precompiled_mode &&
(LoadingUnitOf(zone_, function()) == LoadingUnitOf(zone_, target));
return FLAG_precompiled_mode && (LoadingUnit::LoadingUnitOf(function()) ==
LoadingUnit::LoadingUnitOf(target));
}
bool FlowGraphCompiler::CanPcRelativeCall(const Code& target) const {
return FLAG_precompiled_mode && !target.InVMIsolateHeap() &&
(LoadingUnitOf(zone_, function()) == LoadingUnitOf(zone_, target));
(LoadingUnit::LoadingUnitOf(function()) ==
LoadingUnit::LoadingUnitOf(target));
}
bool FlowGraphCompiler::CanPcRelativeCall(const AbstractType& target) const {
return FLAG_precompiled_mode && !target.InVMIsolateHeap() &&
(LoadingUnitOf(zone_, function()) == LoadingUnit::kRootId);
(LoadingUnit::LoadingUnitOf(function()) ==
LoadingUnit::LoadingUnit::kRootId);
}
#undef __

View file

@ -18602,6 +18602,60 @@ ObjectPtr LoadingUnit::CompleteLoad(const String& error_message,
return DartEntry::InvokeFunction(func, args);
}
// The assignment to loading units here must match that in
// AssignLoadingUnitsCodeVisitor, which runs after compilation is done.
intptr_t LoadingUnit::LoadingUnitOf(const Function& function) {
Thread* thread = Thread::Current();
REUSABLE_CLASS_HANDLESCOPE(thread);
REUSABLE_LIBRARY_HANDLESCOPE(thread);
REUSABLE_LOADING_UNIT_HANDLESCOPE(thread);
Class& cls = thread->ClassHandle();
Library& lib = thread->LibraryHandle();
LoadingUnit& unit = thread->LoadingUnitHandle();
cls = function.Owner();
lib = cls.library();
unit = lib.loading_unit();
ASSERT(!unit.IsNull());
return unit.id();
}
intptr_t LoadingUnit::LoadingUnitOf(const Code& code) {
if (code.IsStubCode() || code.IsTypeTestStubCode()) {
return LoadingUnit::kRootId;
} else {
Thread* thread = Thread::Current();
REUSABLE_FUNCTION_HANDLESCOPE(thread);
REUSABLE_CLASS_HANDLESCOPE(thread);
REUSABLE_LIBRARY_HANDLESCOPE(thread);
REUSABLE_LOADING_UNIT_HANDLESCOPE(thread);
Class& cls = thread->ClassHandle();
Library& lib = thread->LibraryHandle();
LoadingUnit& unit = thread->LoadingUnitHandle();
Function& func = thread->FunctionHandle();
if (code.IsAllocationStubCode()) {
cls ^= code.owner();
lib = cls.library();
unit = lib.loading_unit();
ASSERT(!unit.IsNull());
return unit.id();
} else if (code.IsFunctionCode()) {
func ^= code.function();
cls = func.Owner();
lib = cls.library();
unit = lib.loading_unit();
ASSERT(!unit.IsNull());
return unit.id();
} else {
UNREACHABLE();
return LoadingUnit::kIllegalId;
}
}
}
const char* Error::ToErrorCString() const {
if (IsNull()) {
return "Error: null";

View file

@ -7432,6 +7432,9 @@ class LoadingUnit : public Object {
return RoundedAllocationSize(sizeof(UntaggedLoadingUnit));
}
static intptr_t LoadingUnitOf(const Function& function);
static intptr_t LoadingUnitOf(const Code& code);
LoadingUnitPtr parent() const;
void set_parent(const LoadingUnit& value) const;

View file

@ -1214,7 +1214,11 @@ class CodeKeyValueTrait {
if (pair->UncheckedEntryPointOffset() != key->UncheckedEntryPointOffset()) {
return false;
}
return Instructions::Equals(pair->instructions(), key->instructions());
if (!Instructions::Equals(pair->instructions(), key->instructions())) {
return false;
}
return LoadingUnit::LoadingUnitOf(*pair) ==
LoadingUnit::LoadingUnitOf(*key);
}
};
#endif

View file

@ -96,6 +96,8 @@ REUSABLE_HANDLE_LIST(REUSABLE_SCOPE)
ReusableInstanceHandleScope reused_instance_handle(thread);
#define REUSABLE_LIBRARY_HANDLESCOPE(thread) \
ReusableLibraryHandleScope reused_library_handle(thread);
#define REUSABLE_LOADING_UNIT_HANDLESCOPE(thread) \
ReusableLoadingUnitHandleScope reused_loading_unit_handle(thread);
#define REUSABLE_OBJECT_HANDLESCOPE(thread) \
ReusableObjectHandleScope reused_object_handle(thread);
#define REUSABLE_PC_DESCRIPTORS_HANDLESCOPE(thread) \

View file

@ -84,6 +84,7 @@ class Thread;
V(GrowableObjectArray) \
V(Instance) \
V(Library) \
V(LoadingUnit) \
V(Object) \
V(PcDescriptors) \
V(Smi) \