[vm] Fix --no-retain-function-objects when there are calls through Code.

With --no-use-bare-instructions or with splitting, not all calls are pc-relative. We must replace the Function with its Code in the static call table before detaching the Function's code as part of removing Function objects.

Also handle WeakSerializationReferences in AssignLoadingUnitsCodeVisitor.

Bug: https://github.com/dart-lang/sdk/issues/41974
Change-Id: I29f9258c240f5a2b1b8dca52f74146dfe44d6401
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/158165
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak
2020-08-13 17:01:24 +00:00
committed by commit-bot@chromium.org
parent 33849927c9
commit d8950da048
5 changed files with 46 additions and 7 deletions
@@ -0,0 +1,16 @@
// 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.
// These flags can cause WeakSerializationReferences to replace the owner of
// some Code, which must be accounted for in AssignLoadingUnitsCodeVisitor.
// VMOptions=--no_retain_function_objects
// VMOptions=--dwarf_stack_traces
import "splay_test.dart" deferred as splay; // Some non-trivial code.
main() async {
await splay.loadLibrary();
splay.main();
}
@@ -0,0 +1,16 @@
// 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.
// These flags can cause WeakSerializationReferences to replace the owner of
// some Code, which must be accounted for in AssignLoadingUnitsCodeVisitor.
// VMOptions=--no_retain_function_objects
// VMOptions=--dwarf_stack_traces
import "splay_test.dart" deferred as splay; // Some non-trivial code.
main() async {
await splay.loadLibrary();
splay.main();
}
+11 -3
View File
@@ -391,7 +391,7 @@ void Precompiler::DoCompileAll() {
TraceForRetainedFunctions();
FinalizeDispatchTable();
ReplaceFunctionPCRelativeCallEntries();
ReplaceFunctionStaticCallEntries();
DropFunctions();
DropFields();
@@ -1644,7 +1644,7 @@ void Precompiler::FinalizeDispatchTable() {
printed.Release();
}
void Precompiler::ReplaceFunctionPCRelativeCallEntries() {
void Precompiler::ReplaceFunctionStaticCallEntries() {
class StaticCallTableEntryFixer : public CodeVisitor {
public:
explicit StaticCallTableEntryFixer(Zone* zone)
@@ -1660,7 +1660,9 @@ void Precompiler::ReplaceFunctionPCRelativeCallEntries() {
for (auto& view : static_calls) {
kind_and_offset_ = view.Get<Code::kSCallTableKindAndOffset>();
auto const kind = Code::KindField::decode(kind_and_offset_.Value());
if (kind != Code::kPcRelativeCall) continue;
if ((kind != Code::kCallViaCode) && (kind != Code::kPcRelativeCall))
continue;
target_function_ = view.Get<Code::kSCallTableFunctionTarget>();
if (target_function_.IsNull()) continue;
@@ -1671,6 +1673,12 @@ void Precompiler::ReplaceFunctionPCRelativeCallEntries() {
ASSERT(!target_code_.IsStubCode());
view.Set<Code::kSCallTableCodeOrTypeTarget>(target_code_);
view.Set<Code::kSCallTableFunctionTarget>(Object::null_function());
if (kind == Code::kCallViaCode) {
auto const pc_offset =
Code::OffsetField::decode(kind_and_offset_.Value());
const uword pc = pc_offset + code.PayloadStart();
CodePatcher::PatchStaticCallAt(pc, code, target_code_);
}
if (FLAG_trace_precompiler) {
THR_Print("Updated static call entry to %s in \"%s\"\n",
target_function_.ToFullyQualifiedCString(),
+1 -1
View File
@@ -301,7 +301,7 @@ class Precompiler : public ValueObject {
void TraceForRetainedFunctions();
void FinalizeDispatchTable();
void ReplaceFunctionPCRelativeCallEntries();
void ReplaceFunctionStaticCallEntries();
void DropFunctions();
void DropFields();
void TraceTypesFromRetainedClasses();
+2 -3
View File
@@ -368,8 +368,7 @@ void ProgramVisitor::BindStaticCalls(Zone* zone, Isolate* isolate) {
if (target_.IsNull()) {
target_ =
Code::RawCast(view.Get<Code::kSCallTableCodeOrTypeTarget>());
ASSERT(!Code::Cast(target_).IsFunctionCode());
// Allocation stub or AllocateContext or AllocateArray or ...
ASSERT(!target_.IsNull()); // Already bound.
continue;
}
@@ -1314,7 +1313,7 @@ class AssignLoadingUnitsCodeVisitor : public CodeVisitor {
void VisitCode(const Code& code) {
intptr_t id;
if (code.IsFunctionCode()) {
func_ ^= code.owner();
func_ ^= code.function();
cls_ = func_.Owner();
lib_ = cls_.library();
unit_ = lib_.loading_unit();