dart-sdk/runtime/vm/reverse_pc_lookup_cache.cc
Alexander Markov 5129cff930 [vm/aot] Discard Code objects from the heap
While deserializing AOT snapshot, Code objects which do not contain
valuable information besides entry point and stack maps are discarded
and not allocated on the heap (they are replaced with
StubCode::UnknownDartCode()).

PC -> Code/CompressedStackMaps lookup is implemented using a separate
table (InstructionsTable).

Flutter gallery in release-sizeopt mode:
Heap size of snapshot objects: arm -26.89%, arm64 -27.68%

Large Flutter application in release mode with --dwarf-stack-traces:
Heap size of snapshot objects: -24.3%.
Discarded Code objects: 72.5% of all Code objects.

Issue: https://github.com/dart-lang/sdk/issues/44852.

TEST=existing tests; "--dwarf_stack_traces --no-retain_function_objects
--no-retain_code_objects" mode is enabled for a few tests.

Change-Id: I5fe3e283630c8e8f4442319d5dcae38d174dd0d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/189560
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2021-04-13 02:36:16 +00:00

109 lines
3.9 KiB
C++

// Copyright (c) 2018, 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.
#include "vm/reverse_pc_lookup_cache.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/stub_code.h"
namespace dart {
ObjectPtr ReversePc::FindCodeDescriptorInGroup(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
#if defined(DART_PRECOMPILED_RUNTIME)
// This can run in the middle of GC and must not allocate handles.
NoSafepointScope no_safepoint;
if (is_return_address) {
pc--;
}
// This expected number of tables is low (one per loading unit), so we go
// through them linearly. If this changes, would could sort the table list
// during deserialization and binary search for the table.
GrowableObjectArrayPtr tables = group->object_store()->instructions_tables();
intptr_t tables_length = Smi::Value(tables->untag()->length_);
for (intptr_t i = 0; i < tables_length; i++) {
InstructionsTablePtr table = static_cast<InstructionsTablePtr>(
tables->untag()->data_->untag()->data()[i]);
intptr_t index = InstructionsTable::FindEntry(table, pc);
if (index >= 0) {
*code_start = InstructionsTable::PayloadStartAt(table, index);
return InstructionsTable::DescriptorAt(table, index);
}
}
#endif // defined(DART_PRECOMPILED_RUNTIME)
*code_start = 0;
return Object::null();
}
ObjectPtr ReversePc::FindCodeDescriptor(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
NoSafepointScope no_safepoint;
ObjectPtr code_descriptor =
FindCodeDescriptorInGroup(group, pc, is_return_address, code_start);
if (code_descriptor == Object::null()) {
code_descriptor = FindCodeDescriptorInGroup(Dart::vm_isolate_group(), pc,
is_return_address, code_start);
}
return code_descriptor;
}
CodePtr ReversePc::Lookup(IsolateGroup* group,
uword pc,
bool is_return_address) {
ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
NoSafepointScope no_safepoint;
uword code_start;
ObjectPtr code_descriptor =
FindCodeDescriptor(group, pc, is_return_address, &code_start);
if (code_descriptor != Object::null()) {
if (!code_descriptor->IsCode()) {
ASSERT(StubCode::UnknownDartCode().PayloadStart() == 0);
ASSERT(StubCode::UnknownDartCode().Size() == kUwordMax);
ASSERT(StubCode::UnknownDartCode().IsFunctionCode());
ASSERT(StubCode::UnknownDartCode().IsUnknownDartCode());
code_descriptor = StubCode::UnknownDartCode().ptr();
}
}
return static_cast<CodePtr>(code_descriptor);
}
CompressedStackMapsPtr ReversePc::FindCompressedStackMaps(
IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
NoSafepointScope no_safepoint;
ObjectPtr code_descriptor =
FindCodeDescriptor(group, pc, is_return_address, code_start);
if (code_descriptor != Object::null()) {
if (code_descriptor->IsCode()) {
CodePtr code = static_cast<CodePtr>(code_descriptor);
ASSERT(*code_start == Code::PayloadStartOf(code));
return code->untag()->compressed_stackmaps();
} else {
ASSERT(code_descriptor->IsCompressedStackMaps());
return static_cast<CompressedStackMapsPtr>(code_descriptor);
}
}
*code_start = 0;
return CompressedStackMaps::null();
}
} // namespace dart