[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:
committed by
commit-bot@chromium.org
parent
33849927c9
commit
d8950da048
@@ -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();
|
||||
}
|
||||
@@ -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(),
|
||||
|
||||
@@ -301,7 +301,7 @@ class Precompiler : public ValueObject {
|
||||
|
||||
void TraceForRetainedFunctions();
|
||||
void FinalizeDispatchTable();
|
||||
void ReplaceFunctionPCRelativeCallEntries();
|
||||
void ReplaceFunctionStaticCallEntries();
|
||||
void DropFunctions();
|
||||
void DropFields();
|
||||
void TraceTypesFromRetainedClasses();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user