2017-11-02 00:57:42 +00:00
|
|
|
// Copyright (c) 2017, 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/image_snapshot.h"
|
|
|
|
|
2020-04-23 09:31:08 +00:00
|
|
|
#include "include/dart_api.h"
|
2017-11-02 00:57:42 +00:00
|
|
|
#include "platform/assert.h"
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
#include "platform/elf.h"
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#include "vm/bss_relocs.h"
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
#include "vm/class_id.h"
|
2019-09-25 17:09:16 +00:00
|
|
|
#include "vm/compiler/runtime_api.h"
|
2017-11-02 00:57:42 +00:00
|
|
|
#include "vm/dwarf.h"
|
2019-05-28 18:48:57 +00:00
|
|
|
#include "vm/elf.h"
|
2018-04-27 17:42:16 +00:00
|
|
|
#include "vm/hash.h"
|
|
|
|
#include "vm/hash_map.h"
|
2018-06-20 00:39:49 +00:00
|
|
|
#include "vm/heap/heap.h"
|
2018-12-13 12:10:59 +00:00
|
|
|
#include "vm/instructions.h"
|
2018-04-11 13:03:16 +00:00
|
|
|
#include "vm/json_writer.h"
|
2017-11-02 00:57:42 +00:00
|
|
|
#include "vm/object.h"
|
2018-10-23 15:51:37 +00:00
|
|
|
#include "vm/object_store.h"
|
2018-09-25 23:44:29 +00:00
|
|
|
#include "vm/program_visitor.h"
|
2017-11-02 00:57:42 +00:00
|
|
|
#include "vm/stub_code.h"
|
|
|
|
#include "vm/timeline.h"
|
Reland "[VM] Introduction of type testing stubs - Part 1-4"
Relands 165c583d57af613836cf7d08242ce969521db00b
[VM] Introduction of type testing stubs - Part 1
This CL:
* Adds a field to [RawAbstractType] which will always hold a pointer
to the entrypoint of a type testing stub
* Makes this new field be initialized to a default stub whenever a
instances are created (e.g. via Type::New(), snapshot reader, ...)
* Makes the clustered snapshotter write a reference to the
corresponding [RawInstructions] object when writing the field and do
the reverse when reading it.
* Makes us call the type testing stub for performing assert-assignable
checks.
To reduce unnecessary loads on callsites, we store the entrypoint of the
type testing stubs directly in the type objects. This means that the
caller of type testing stubs can simply branch there without populating
a code object first. This also means that the type testing stubs
themselves have no access to a pool and we therefore also don't hold on
to the [Code] object, only the [Instruction] object is necessary.
The type testing stubs do not setup a frame themselves and also have no
safepoint. In the case when the type testing stubs could not determine
a positive answer they will tail-call a general-purpose stub.
The general-purpose stub sets up a stub frame, tries to consult a
[SubtypeTestCache] and bails out to runtime if this was unsuccessful.
This CL is just the the first, for ease of reviewing. The actual
type-specialized type testing stubs will be generated in later CLs.
Reviewed-on: https://dart-review.googlesource.com/44787
Relands f226c22424c483d65499545e560efc059f9dde1c
[VM] Introduction of type testing stubs - Part 2
This CL starts building type testing stubs specialzed for [Type] objects
we test against.
More specifically, it adds support for:
* Handling obvious fast cases on the call sites (while still having a
call to stub for negative case)
* Handling type tests against type parameters, by loading the value
of the type parameter on the call sites and invoking it's type testing stub.
* Specialzed type testing stubs for instantiated types where we can
do [CidRange]-based subtype-checks.
==> e.g. String/List<dynamic>
* Specialzed type testing stubs for instantiated types where we can
do [CidRange]-based subclass-checks for the class and
[CidRange]-based subtype-checks for the type arguments.
==> e.g. Widget<State>, where we know [Widget] is only extended and not
implemented.
* Specialzed type testing stubs for certain non-instantiated types where we
can do [CidRange]-based subclass-checks for the class and
[CidRange]-based subtype-checks for the instantiated type arguments and
cid based comparisons for type parameters. (Note that this fast-case migth
result in some false-negatives!)
==> e.g. _HashMapEntry<K, V>, where we know [_HashMapEntry] is only
extended and not implemented.
This optimizes cases where the caller uses `new HashMap<A, B>()` and only
uses `A` and `B` as key/values (and not subclasses of it). The false-negative
can occur when subtypes of A or B are used. In such cases we fall back to the
[SubtypeTestCache]-based imlementation.
Reviewed-on: https://dart-review.googlesource.com/44788
Relands 25f98bcc7561006d70a487ba3de55551658ac683
[VM] Introduction of type testing stubs - Part 3
The changes include:
* Make AssertAssignableInstr no longer have a call-summary, which
helps methods with several parameter checks by not having to
re-load/re-initialize type arguments registers
* Lazily create SubtypeTestCaches: We already go to runtime to warm up
the caches, so we now also create the caches on the first runtime
call and patch the pool entries.
* No longer load the destination name into a register: We only need
the name when we throw an exception, so it is not on the hot path.
Instead we let the runtime look at the call site, decoding a pool
index from the instructions stream. The destination name will be
available in the pool, at a consecutive index to the subtype cache.
* Remove the fall-through to N=1 case for probing subtypeing tests,
since those will always be handled by the optimized stubs.
* Do not generate optimized stubs for FutureOr<T> (so far it just
falled-through to TTS). We can make optimzed version of that later,
but it requires special subtyping rules.
* Local code quality improvement in the type-testing-stubs: Avoid
extra jump at last case of cid-class-range checks.
There are still a number of optimization opportunities we can do in
future changes.
Reviewed-on: https://dart-review.googlesource.com/46984
Relands 2c52480ec87392992a1388517c46ccc97bdc9b2b
[VM] Introduction of type testing stubs - Part 4
In order to avoid generating type testing stubs for too many types in
the system - and thereby potentially cause an increase in code size -
this change introduces a smarter way to decide for which types we should
generate optimized type testing stubs.
The precompiler creates a [TypeUsageInfo] which we use to collect
information. More specifically:
a) We collect the destination types for all type checks we emit
(we do this inside AssertAssignableInstr::EmitNativeCode).
-> These are types we might want to generate optimized type testing
stubs for.
b) We collect type argument vectors used in instance creations (we do
this inside AllocateObjectInstr::EmitNativeCode) and keep a set of
of used type argument vectors for each class.
After the precompiler has finished compiling normal code we scan the set
of destination types collected in a) for uninstantiated types (or more
specifically, type parameter types).
We then propagate the type argument vectors used on object allocation sites,
which were collected in b), in order to find out what kind of types are flowing
into those type parameters.
This allows us to extend the set of types which we test against, by
adding the types that flow into type parameters.
We use this final augmented set of destination types as a "filter" when
making the decision whether to generate an optimized type testing stub
for a given type.
Reviewed-on: https://dart-review.googlesource.com/48640
Issue https://github.com/dart-lang/sdk/issues/32603
Closes https://github.com/dart-lang/sdk/issues/32852
Change-Id: Ib79fbe7f043aa88f32bddad62d7656c638914b44
Reviewed-on: https://dart-review.googlesource.com/50944
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
2018-04-13 09:06:56 +00:00
|
|
|
#include "vm/type_testing_stubs.h"
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2020-04-16 22:59:03 +00:00
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
#include "vm/compiler/backend/code_statistics.h"
|
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
|
2017-11-02 00:57:42 +00:00
|
|
|
namespace dart {
|
|
|
|
|
2018-04-11 13:03:16 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
DEFINE_FLAG(bool,
|
|
|
|
print_instruction_stats,
|
|
|
|
false,
|
|
|
|
"Print instruction statistics");
|
|
|
|
|
|
|
|
DEFINE_FLAG(charp,
|
|
|
|
print_instructions_sizes_to,
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
nullptr,
|
2018-04-11 13:03:16 +00:00
|
|
|
"Print sizes of all instruction objects to the given file");
|
|
|
|
#endif
|
|
|
|
|
2021-01-15 23:32:02 +00:00
|
|
|
const UntaggedInstructionsSection* Image::ExtraInfo(const uword raw_memory,
|
|
|
|
const uword size) {
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
auto const raw_value =
|
|
|
|
FieldValue(raw_memory, HeaderField::InstructionsSectionOffset);
|
|
|
|
if (raw_value != kNoInstructionsSection) {
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
ASSERT(raw_value >= kHeaderSize);
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
ASSERT(raw_value <= size - InstructionsSection::HeaderSize());
|
2021-01-15 23:32:02 +00:00
|
|
|
auto const layout = reinterpret_cast<const UntaggedInstructionsSection*>(
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
raw_memory + raw_value);
|
|
|
|
// The instructions section is likely non-empty in bare instructions mode
|
|
|
|
// (unless splitting into multiple outputs and there are no Code objects
|
|
|
|
// in this particular output), but is guaranteed empty otherwise (the
|
|
|
|
// instructions follow the InstructionsSection object instead).
|
|
|
|
ASSERT(FLAG_use_bare_instructions || layout->payload_length_ == 0);
|
|
|
|
ASSERT(raw_value <=
|
|
|
|
size - InstructionsSection::InstanceSize(layout->payload_length_));
|
|
|
|
return layout;
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
uword* Image::bss() const {
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
ASSERT(extra_info_ != nullptr);
|
|
|
|
// There should always be a non-zero BSS offset.
|
|
|
|
ASSERT(extra_info_->bss_offset_ != 0);
|
|
|
|
// Returning a non-const uword* is safe because we're translating from
|
|
|
|
// the start of the instructions (read-only) to the start of the BSS
|
|
|
|
// (read-write).
|
|
|
|
return reinterpret_cast<uword*>(raw_memory_ + extra_info_->bss_offset_);
|
|
|
|
#else
|
|
|
|
return nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
uword Image::instructions_relocated_address() const {
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
ASSERT(extra_info_ != nullptr);
|
|
|
|
// For assembly snapshots, we need to retrieve this from the initialized BSS.
|
|
|
|
const uword address =
|
|
|
|
compiled_to_elf() ? extra_info_->instructions_relocated_address_
|
|
|
|
: bss()[BSS::RelocationIndex(
|
|
|
|
BSS::Relocation::InstructionsRelocatedAddress)];
|
|
|
|
ASSERT(address != kNoRelocatedAddress);
|
|
|
|
return address;
|
|
|
|
#else
|
|
|
|
return kNoRelocatedAddress;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t* Image::build_id() const {
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
ASSERT(extra_info_ != nullptr);
|
|
|
|
if (extra_info_->build_id_offset_ != kNoBuildId) {
|
[vm] Simplify symbol naming/address retrieval.
Before, picking a symbol name for a Code object when generating
assembly required adding a placeholder entry in the Dwarf object,
because the Dwarf object separately used a SnapshotTextObjectNamer
to determine the appropriate symbol name to use in relocations.
Instead, now the ImageWriter subclasses are entirely responsible for
creating the symbol name for a given Code object, and that name is
passed when adding the Code object to the Dwarf object.
For Elf output, we eagerly create symbols for sections and Code objects
again in the appropriate symbol table, and so looking up the start of a
given section or Code object can be done simply by asking for the
corresponding symbol's address, removing special case methods and other
workarounds.
We also clean up the generated static and dynamic symbol tables by
only generating local symbols for Code objects and BSS sections (these
are local in assembly output also), and only adding global symbols to
the dynamic symbol table.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ie40c0c836681e98f345483136bb6860e5588ef30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166002
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
auto const note = reinterpret_cast<elf::Note*>(
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
raw_memory_ + extra_info_->build_id_offset_);
|
[vm] Simplify symbol naming/address retrieval.
Before, picking a symbol name for a Code object when generating
assembly required adding a placeholder entry in the Dwarf object,
because the Dwarf object separately used a SnapshotTextObjectNamer
to determine the appropriate symbol name to use in relocations.
Instead, now the ImageWriter subclasses are entirely responsible for
creating the symbol name for a given Code object, and that name is
passed when adding the Code object to the Dwarf object.
For Elf output, we eagerly create symbols for sections and Code objects
again in the appropriate symbol table, and so looking up the start of a
given section or Code object can be done simply by asking for the
corresponding symbol's address, removing special case methods and other
workarounds.
We also clean up the generated static and dynamic symbol tables by
only generating local symbols for Code objects and BSS sections (these
are local in assembly output also), and only adding global symbols to
the dynamic symbol table.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ie40c0c836681e98f345483136bb6860e5588ef30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166002
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
// Check that we have a final build ID. A non-final build ID will either
|
|
|
|
// have a description length of 0 or an initial byte of 0.
|
|
|
|
auto const description = note->data + note->name_size;
|
|
|
|
auto const length = note->description_size;
|
|
|
|
if (length != 0 && description[0] != 0) {
|
|
|
|
return description;
|
|
|
|
}
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t Image::build_id_length() const {
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
ASSERT(extra_info_ != nullptr);
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
if (extra_info_->build_id_offset_ != kNoBuildId) {
|
[vm] Simplify symbol naming/address retrieval.
Before, picking a symbol name for a Code object when generating
assembly required adding a placeholder entry in the Dwarf object,
because the Dwarf object separately used a SnapshotTextObjectNamer
to determine the appropriate symbol name to use in relocations.
Instead, now the ImageWriter subclasses are entirely responsible for
creating the symbol name for a given Code object, and that name is
passed when adding the Code object to the Dwarf object.
For Elf output, we eagerly create symbols for sections and Code objects
again in the appropriate symbol table, and so looking up the start of a
given section or Code object can be done simply by asking for the
corresponding symbol's address, removing special case methods and other
workarounds.
We also clean up the generated static and dynamic symbol tables by
only generating local symbols for Code objects and BSS sections (these
are local in assembly output also), and only adding global symbols to
the dynamic symbol table.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ie40c0c836681e98f345483136bb6860e5588ef30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166002
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
auto const note = reinterpret_cast<elf::Note*>(
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
raw_memory_ + extra_info_->build_id_offset_);
|
[vm] Simplify symbol naming/address retrieval.
Before, picking a symbol name for a Code object when generating
assembly required adding a placeholder entry in the Dwarf object,
because the Dwarf object separately used a SnapshotTextObjectNamer
to determine the appropriate symbol name to use in relocations.
Instead, now the ImageWriter subclasses are entirely responsible for
creating the symbol name for a given Code object, and that name is
passed when adding the Code object to the Dwarf object.
For Elf output, we eagerly create symbols for sections and Code objects
again in the appropriate symbol table, and so looking up the start of a
given section or Code object can be done simply by asking for the
corresponding symbol's address, removing special case methods and other
workarounds.
We also clean up the generated static and dynamic symbol tables by
only generating local symbols for Code objects and BSS sections (these
are local in assembly output also), and only adding global symbols to
the dynamic symbol table.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ie40c0c836681e98f345483136bb6860e5588ef30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166002
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
// Check that we have a final build ID. A non-final build ID will either
|
|
|
|
// have a description length of 0 or an initial byte of 0.
|
|
|
|
auto const description = note->data + note->name_size;
|
|
|
|
auto const length = note->description_size;
|
|
|
|
if (length != 0 && description[0] != 0) {
|
|
|
|
return length;
|
|
|
|
}
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
}
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#endif
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
return 0;
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Image::compiled_to_elf() const {
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
ASSERT(extra_info_ != nullptr);
|
|
|
|
// Since assembly snapshots can't set up this field correctly (instead,
|
|
|
|
// it's initialized in BSS at snapshot load time), we use it to detect
|
|
|
|
// direct-to-ELF snapshots.
|
|
|
|
return extra_info_->instructions_relocated_address_ != kNoRelocatedAddress;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-04-14 10:04:48 +00:00
|
|
|
uword ObjectOffsetTrait::Hash(Key key) {
|
2020-04-25 05:21:27 +00:00
|
|
|
ObjectPtr obj = key;
|
2018-04-27 17:42:16 +00:00
|
|
|
ASSERT(!obj->IsSmi());
|
|
|
|
|
2021-01-15 23:32:02 +00:00
|
|
|
uword body = UntaggedObject::ToAddr(obj) + sizeof(UntaggedObject);
|
|
|
|
uword end = UntaggedObject::ToAddr(obj) + obj->untag()->HeapSize();
|
2018-04-27 17:42:16 +00:00
|
|
|
|
|
|
|
uint32_t hash = obj->GetClassId();
|
|
|
|
// Don't include the header. Objects in the image are pre-marked, but objects
|
|
|
|
// in the current isolate are not.
|
|
|
|
for (uword cursor = body; cursor < end; cursor += sizeof(uint32_t)) {
|
|
|
|
hash = CombineHashes(hash, *reinterpret_cast<uint32_t*>(cursor));
|
|
|
|
}
|
|
|
|
|
|
|
|
return FinalizeHash(hash, 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ObjectOffsetTrait::IsKeyEqual(Pair pair, Key key) {
|
2020-04-25 05:21:27 +00:00
|
|
|
ObjectPtr a = pair.object;
|
|
|
|
ObjectPtr b = key;
|
2018-04-27 17:42:16 +00:00
|
|
|
ASSERT(!a->IsSmi());
|
|
|
|
ASSERT(!b->IsSmi());
|
|
|
|
|
|
|
|
if (a->GetClassId() != b->GetClassId()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-01-15 23:32:02 +00:00
|
|
|
intptr_t heap_size = a->untag()->HeapSize();
|
|
|
|
if (b->untag()->HeapSize() != heap_size) {
|
2018-04-27 17:42:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't include the header. Objects in the image are pre-marked, but objects
|
|
|
|
// in the current isolate are not.
|
2021-01-15 23:32:02 +00:00
|
|
|
uword body_a = UntaggedObject::ToAddr(a) + sizeof(UntaggedObject);
|
|
|
|
uword body_b = UntaggedObject::ToAddr(b) + sizeof(UntaggedObject);
|
|
|
|
uword body_size = heap_size - sizeof(UntaggedObject);
|
2018-04-27 17:42:16 +00:00
|
|
|
return 0 == memcmp(reinterpret_cast<const void*>(body_a),
|
|
|
|
reinterpret_cast<const void*>(body_b), body_size);
|
|
|
|
}
|
|
|
|
|
2019-09-25 17:09:16 +00:00
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
ImageWriter::ImageWriter(Thread* t)
|
|
|
|
: heap_(t->heap()),
|
2018-11-01 14:22:37 +00:00
|
|
|
next_data_offset_(0),
|
|
|
|
next_text_offset_(0),
|
|
|
|
objects_(),
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
instructions_(),
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
image_type_(TagObjectTypeAsReadOnly(t->zone(), "Image")),
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
instructions_section_type_(
|
|
|
|
TagObjectTypeAsReadOnly(t->zone(), "InstructionsSection")),
|
|
|
|
instructions_type_(TagObjectTypeAsReadOnly(t->zone(), "Instructions")),
|
|
|
|
trampoline_type_(TagObjectTypeAsReadOnly(t->zone(), "Trampoline")) {
|
2018-04-27 17:42:16 +00:00
|
|
|
ResetOffsets();
|
|
|
|
}
|
|
|
|
|
2018-12-13 12:10:59 +00:00
|
|
|
void ImageWriter::PrepareForSerialization(
|
|
|
|
GrowableArray<ImageWriterCommand>* commands) {
|
|
|
|
if (commands != nullptr) {
|
|
|
|
const intptr_t initial_offset = next_text_offset_;
|
|
|
|
for (auto& inst : *commands) {
|
|
|
|
ASSERT((initial_offset + inst.expected_offset) == next_text_offset_);
|
|
|
|
switch (inst.op) {
|
|
|
|
case ImageWriterCommand::InsertInstructionOfCode: {
|
2020-04-25 05:21:27 +00:00
|
|
|
CodePtr code = inst.insert_instruction_of_code.code;
|
|
|
|
InstructionsPtr instructions = Code::InstructionsOf(code);
|
2018-12-13 12:10:59 +00:00
|
|
|
const intptr_t offset = next_text_offset_;
|
|
|
|
instructions_.Add(InstructionsData(instructions, code, offset));
|
2019-06-10 02:55:25 +00:00
|
|
|
next_text_offset_ += SizeInSnapshot(instructions);
|
2018-12-13 12:10:59 +00:00
|
|
|
ASSERT(heap_->GetObjectId(instructions) == 0);
|
|
|
|
heap_->SetObjectId(instructions, offset);
|
|
|
|
break;
|
|
|
|
}
|
2019-01-17 12:32:38 +00:00
|
|
|
case ImageWriterCommand::InsertBytesOfTrampoline: {
|
|
|
|
auto trampoline_bytes = inst.insert_trampoline_bytes.buffer;
|
|
|
|
auto trampoline_length = inst.insert_trampoline_bytes.buffer_length;
|
|
|
|
const intptr_t offset = next_text_offset_;
|
|
|
|
instructions_.Add(
|
|
|
|
InstructionsData(trampoline_bytes, trampoline_length, offset));
|
|
|
|
next_text_offset_ += trampoline_length;
|
|
|
|
break;
|
|
|
|
}
|
2018-12-13 12:10:59 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-25 05:21:27 +00:00
|
|
|
int32_t ImageWriter::GetTextOffsetFor(InstructionsPtr instructions,
|
|
|
|
CodePtr code) {
|
2018-11-01 14:22:37 +00:00
|
|
|
intptr_t offset = heap_->GetObjectId(instructions);
|
|
|
|
if (offset != 0) {
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = next_text_offset_;
|
|
|
|
heap_->SetObjectId(instructions, offset);
|
2019-06-10 02:55:25 +00:00
|
|
|
next_text_offset_ += SizeInSnapshot(instructions);
|
2017-11-02 00:57:42 +00:00
|
|
|
instructions_.Add(InstructionsData(instructions, code, offset));
|
2018-12-13 12:10:59 +00:00
|
|
|
|
2019-03-13 23:36:06 +00:00
|
|
|
ASSERT(offset != 0);
|
2017-11-02 00:57:42 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2020-04-25 05:21:27 +00:00
|
|
|
intptr_t ImageWriter::SizeInSnapshot(ObjectPtr raw_object) {
|
2019-06-21 04:00:35 +00:00
|
|
|
const classid_t cid = raw_object->GetClassId();
|
|
|
|
|
|
|
|
switch (cid) {
|
[vm/compiler] Reland "Further compress the information... in StackMaps."
Fixes an assumption that CompressedStackMapsIterator::Find() is never
passed a PC offset of 0. Adds back an ASSERT that was dropped which checks
for specific cases where a given PC offset does not have a stack map entry.
Original commit message:
Lifting the PC offset in a2bb730 was a small, lightweight change that
gave us big gains, at least on 32-bit architectures. Here, we make
much more invasive changes that will improve the amount of memory used
by the information previously stored in StackMap objects.
Instead of allocating separate objects for StackMaps, we instead compress
all StackMap information for a given Code object into a single object
(CompressedStackMaps, or CSM for short). This replaces the Array used to
store PC offsets (as Smis) and the individual StackMap objects.
While we lose all canonicalization for individual StackMap entries, the
drop in space required to store stack map information more than offsets that.
-----
The impact on AOT snapshot size when compiling the Flutter Gallery
in release mode:
armv7: Total size -2.58% (Isolate RO: +14.46%, Isolate snapshot: -22.93%)
armv8: Total size -1.85% (Isolate RO: +15.69%, Isolate snapshot: -22.97%)
The impact on in-memory, not on-disk, size for the Flutter Gallery as seen
in the Observatory while running a profile (not release) build:
armv7: Drops from 7.1 MB to 6.2MB (-0.9 MB)
armv8: Drops from 13.5MB to 11.7MB (-1.8 MB)
-----
Bug: https://github.com/dart-lang/sdk/issues/35274, https://github.com/dart-lang/sdk/issues/38873
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-mac-debug-simdbc64-try
Change-Id: I111b129b0ed64f03184370bceb7cda69d5d4b3c9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121700
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-10-16 08:25:53 +00:00
|
|
|
case kCompressedStackMapsCid: {
|
2020-10-06 07:59:33 +00:00
|
|
|
auto raw_maps = CompressedStackMaps::RawCast(raw_object);
|
|
|
|
return compiler::target::CompressedStackMaps::InstanceSize(
|
|
|
|
CompressedStackMaps::PayloadSizeOf(raw_maps));
|
2019-06-21 04:00:35 +00:00
|
|
|
}
|
|
|
|
case kCodeSourceMapCid: {
|
2020-10-06 07:59:33 +00:00
|
|
|
auto raw_map = CodeSourceMap::RawCast(raw_object);
|
|
|
|
return compiler::target::CodeSourceMap::InstanceSize(
|
2021-01-15 23:32:02 +00:00
|
|
|
raw_map->untag()->length_);
|
2019-06-21 04:00:35 +00:00
|
|
|
}
|
|
|
|
case kPcDescriptorsCid: {
|
2020-10-06 07:59:33 +00:00
|
|
|
auto raw_desc = PcDescriptors::RawCast(raw_object);
|
|
|
|
return compiler::target::PcDescriptors::InstanceSize(
|
2021-01-15 23:32:02 +00:00
|
|
|
raw_desc->untag()->length_);
|
2019-06-21 04:00:35 +00:00
|
|
|
}
|
|
|
|
case kInstructionsCid: {
|
2020-10-06 07:59:33 +00:00
|
|
|
auto raw_insns = Instructions::RawCast(raw_object);
|
|
|
|
return compiler::target::Instructions::InstanceSize(
|
|
|
|
Instructions::Size(raw_insns));
|
2019-06-21 04:00:35 +00:00
|
|
|
}
|
2020-11-02 21:11:50 +00:00
|
|
|
case kOneByteStringCid: {
|
|
|
|
auto raw_str = String::RawCast(raw_object);
|
|
|
|
return compiler::target::String::InstanceSize(
|
|
|
|
String::LengthOf(raw_str) * OneByteString::kBytesPerElement);
|
|
|
|
}
|
|
|
|
case kTwoByteStringCid: {
|
|
|
|
auto raw_str = String::RawCast(raw_object);
|
|
|
|
return compiler::target::String::InstanceSize(
|
|
|
|
String::LengthOf(raw_str) * TwoByteString::kBytesPerElement);
|
|
|
|
}
|
2019-06-21 04:00:35 +00:00
|
|
|
default: {
|
|
|
|
const Class& clazz = Class::Handle(Object::Handle(raw_object).clazz());
|
2020-10-06 07:59:33 +00:00
|
|
|
FATAL("Unsupported class %s in rodata section.\n", clazz.ToCString());
|
2019-06-21 04:00:35 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-10 02:55:25 +00:00
|
|
|
|
2020-04-25 05:21:27 +00:00
|
|
|
uint32_t ImageWriter::GetDataOffsetFor(ObjectPtr raw_object) {
|
2019-06-10 02:55:25 +00:00
|
|
|
intptr_t snap_size = SizeInSnapshot(raw_object);
|
2017-11-11 00:19:18 +00:00
|
|
|
intptr_t offset = next_data_offset_;
|
2019-06-10 02:55:25 +00:00
|
|
|
next_data_offset_ += snap_size;
|
2017-11-02 00:57:42 +00:00
|
|
|
objects_.Add(ObjectData(raw_object));
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
intptr_t ImageWriter::GetTextObjectCount() const {
|
|
|
|
return instructions_.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWriter::GetTrampolineInfo(intptr_t* count, intptr_t* size) const {
|
|
|
|
ASSERT(count != nullptr && size != nullptr);
|
|
|
|
*count = 0;
|
|
|
|
*size = 0;
|
2020-09-21 22:02:32 +00:00
|
|
|
for (auto const& data : instructions_) {
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
if (data.trampoline_length != 0) {
|
|
|
|
*count += 1;
|
|
|
|
*size += data.trampoline_length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns nullptr if there is no profile writer.
|
|
|
|
const char* ImageWriter::ObjectTypeForProfile(const Object& object) const {
|
|
|
|
if (profile_writer_ == nullptr) return nullptr;
|
|
|
|
ASSERT(IsROSpace());
|
|
|
|
Thread* thread = Thread::Current();
|
|
|
|
REUSABLE_CLASS_HANDLESCOPE(thread);
|
|
|
|
REUSABLE_STRING_HANDLESCOPE(thread);
|
|
|
|
Class& klass = thread->ClassHandle();
|
|
|
|
String& name = thread->StringHandle();
|
|
|
|
klass = object.clazz();
|
|
|
|
name = klass.UserVisibleName();
|
|
|
|
auto const name_str = name.ToCString();
|
|
|
|
return TagObjectTypeAsReadOnly(thread->zone(), name_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* ImageWriter::TagObjectTypeAsReadOnly(Zone* zone, const char* type) {
|
|
|
|
ASSERT(zone != nullptr && type != nullptr);
|
|
|
|
return OS::SCreate(zone, "(RO) %s", type);
|
|
|
|
}
|
|
|
|
|
2018-04-11 13:03:16 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
void ImageWriter::DumpInstructionStats() {
|
2019-12-11 18:15:27 +00:00
|
|
|
std::unique_ptr<CombinedCodeStatistics> instruction_stats(
|
|
|
|
new CombinedCodeStatistics());
|
2018-04-11 13:03:16 +00:00
|
|
|
for (intptr_t i = 0; i < instructions_.length(); i++) {
|
|
|
|
auto& data = instructions_[i];
|
|
|
|
CodeStatistics* stats = data.insns_->stats();
|
|
|
|
if (stats != nullptr) {
|
2019-12-11 18:15:27 +00:00
|
|
|
stats->AppendTo(instruction_stats.get());
|
2018-04-11 13:03:16 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-11 18:15:27 +00:00
|
|
|
instruction_stats->DumpStatistics();
|
2018-04-11 13:03:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWriter::DumpInstructionsSizes() {
|
|
|
|
auto thread = Thread::Current();
|
|
|
|
auto zone = thread->zone();
|
|
|
|
|
|
|
|
auto& cls = Class::Handle(zone);
|
|
|
|
auto& lib = Library::Handle(zone);
|
|
|
|
auto& owner = Object::Handle(zone);
|
|
|
|
auto& url = String::Handle(zone);
|
|
|
|
auto& name = String::Handle(zone);
|
2020-05-26 23:14:32 +00:00
|
|
|
intptr_t trampolines_total_size = 0;
|
2018-04-11 13:03:16 +00:00
|
|
|
|
|
|
|
JSONWriter js;
|
|
|
|
js.OpenArray();
|
|
|
|
for (intptr_t i = 0; i < instructions_.length(); i++) {
|
|
|
|
auto& data = instructions_[i];
|
2020-05-26 23:14:32 +00:00
|
|
|
const bool is_trampoline = data.code_ == nullptr;
|
|
|
|
if (is_trampoline) {
|
|
|
|
trampolines_total_size += data.trampoline_length;
|
|
|
|
continue;
|
|
|
|
}
|
2020-05-07 12:39:27 +00:00
|
|
|
owner = WeakSerializationReference::Unwrap(data.code_->owner());
|
2018-04-11 13:03:16 +00:00
|
|
|
js.OpenObject();
|
|
|
|
if (owner.IsFunction()) {
|
|
|
|
cls = Function::Cast(owner).Owner();
|
|
|
|
name = cls.ScrubbedName();
|
|
|
|
lib = cls.library();
|
|
|
|
url = lib.url();
|
|
|
|
js.PrintPropertyStr("l", url);
|
|
|
|
js.PrintPropertyStr("c", name);
|
2020-05-07 12:39:27 +00:00
|
|
|
} else if (owner.IsClass()) {
|
2021-01-15 23:32:02 +00:00
|
|
|
cls ^= owner.ptr();
|
2020-05-07 12:39:27 +00:00
|
|
|
name = cls.ScrubbedName();
|
|
|
|
lib = cls.library();
|
2020-09-01 16:50:29 +00:00
|
|
|
url = lib.url();
|
2020-05-07 12:39:27 +00:00
|
|
|
js.PrintPropertyStr("l", url);
|
|
|
|
js.PrintPropertyStr("c", name);
|
2018-04-11 13:03:16 +00:00
|
|
|
}
|
2020-06-10 10:18:37 +00:00
|
|
|
js.PrintProperty("n",
|
|
|
|
data.code_->QualifiedName(
|
|
|
|
NameFormattingParams::DisambiguatedWithoutClassName(
|
|
|
|
Object::kInternalName)));
|
2021-01-15 23:32:02 +00:00
|
|
|
js.PrintProperty("s", SizeInSnapshot(data.insns_->ptr()));
|
2018-04-11 13:03:16 +00:00
|
|
|
js.CloseObject();
|
|
|
|
}
|
2020-05-26 23:14:32 +00:00
|
|
|
if (trampolines_total_size != 0) {
|
|
|
|
js.OpenObject();
|
|
|
|
js.PrintProperty("n", "[Stub] Trampoline");
|
|
|
|
js.PrintProperty("s", trampolines_total_size);
|
|
|
|
js.CloseObject();
|
|
|
|
}
|
2018-04-11 13:03:16 +00:00
|
|
|
js.CloseArray();
|
|
|
|
|
|
|
|
auto file_open = Dart::file_open_callback();
|
|
|
|
auto file_write = Dart::file_write_callback();
|
|
|
|
auto file_close = Dart::file_close_callback();
|
|
|
|
if ((file_open == nullptr) || (file_write == nullptr) ||
|
|
|
|
(file_close == nullptr)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto file = file_open(FLAG_print_instructions_sizes_to, /*write=*/true);
|
|
|
|
if (file == nullptr) {
|
|
|
|
OS::PrintErr("Failed to open file %s\n", FLAG_print_instructions_sizes_to);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* output = nullptr;
|
|
|
|
intptr_t output_length = 0;
|
|
|
|
js.Steal(&output, &output_length);
|
|
|
|
file_write(output, output_length, file);
|
|
|
|
free(output);
|
|
|
|
file_close(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWriter::DumpStatistics() {
|
|
|
|
if (FLAG_print_instruction_stats) {
|
|
|
|
DumpInstructionStats();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FLAG_print_instructions_sizes_to != nullptr) {
|
|
|
|
DumpInstructionsSizes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
void ImageWriter::Write(NonStreamingWriteStream* clustered_stream, bool vm) {
|
2017-11-02 00:57:42 +00:00
|
|
|
Thread* thread = Thread::Current();
|
|
|
|
Zone* zone = thread->zone();
|
2021-01-06 15:22:11 +00:00
|
|
|
Heap* heap = thread->isolate_group()->heap();
|
2019-01-18 00:06:10 +00:00
|
|
|
TIMELINE_DURATION(thread, Isolate, "WriteInstructions");
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
// Handlify collected raw pointers as building the names below
|
|
|
|
// will allocate on the Dart heap.
|
|
|
|
for (intptr_t i = 0; i < instructions_.length(); i++) {
|
|
|
|
InstructionsData& data = instructions_[i];
|
2019-01-17 12:32:38 +00:00
|
|
|
const bool is_trampoline = data.trampoline_bytes != nullptr;
|
|
|
|
if (is_trampoline) continue;
|
|
|
|
|
2017-11-02 00:57:42 +00:00
|
|
|
data.insns_ = &Instructions::Handle(zone, data.raw_insns_);
|
2020-04-25 05:21:27 +00:00
|
|
|
ASSERT(data.raw_code_ != nullptr);
|
2017-11-02 00:57:42 +00:00
|
|
|
data.code_ = &Code::Handle(zone, data.raw_code_);
|
|
|
|
|
2018-04-27 17:42:16 +00:00
|
|
|
// Reset object id as an isolate snapshot after a VM snapshot will not use
|
|
|
|
// the VM snapshot's text image.
|
2021-01-15 23:32:02 +00:00
|
|
|
heap->SetObjectId(data.insns_->ptr(), 0);
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
for (intptr_t i = 0; i < objects_.length(); i++) {
|
|
|
|
ObjectData& data = objects_[i];
|
|
|
|
data.obj_ = &Object::Handle(zone, data.raw_obj_);
|
|
|
|
}
|
|
|
|
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
// Needs to happen before WriteText, as we add information about the
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
// BSSsection in the text section as an initial InstructionsSection object.
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
WriteBss(vm);
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2021-04-20 11:17:36 +00:00
|
|
|
offset_space_ = vm ? IdSpace::kVmText : IdSpace::kIsolateText;
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
WriteText(vm);
|
|
|
|
|
|
|
|
// Append the direct-mapped RO data objects after the clustered snapshot
|
|
|
|
// and then for ELF and assembly outputs, add appropriate sections with
|
|
|
|
// that combined data.
|
2021-04-20 11:17:36 +00:00
|
|
|
offset_space_ = vm ? IdSpace::kVmData : IdSpace::kIsolateData;
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
WriteROData(clustered_stream, vm);
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
void ImageWriter::WriteROData(NonStreamingWriteStream* stream, bool vm) {
|
2020-05-26 10:46:05 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
const intptr_t start_position = stream->Position();
|
|
|
|
#endif
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
stream->Align(ImageWriter::kRODataAlignment);
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
// Heap page starts here.
|
|
|
|
|
2018-11-22 15:14:46 +00:00
|
|
|
intptr_t section_start = stream->Position();
|
|
|
|
|
2017-11-11 00:19:18 +00:00
|
|
|
stream->WriteWord(next_data_offset_); // Data length.
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
stream->WriteWord(Image::kNoInstructionsSection);
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
// Zero values for the rest of the Image object header bytes.
|
|
|
|
stream->Align(Image::kHeaderSize);
|
2020-10-06 17:10:05 +00:00
|
|
|
ASSERT_EQUAL(stream->Position() - section_start, Image::kHeaderSize);
|
2020-05-26 10:46:05 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
if (profile_writer_ != nullptr) {
|
|
|
|
const intptr_t end_position = stream->Position();
|
|
|
|
profile_writer_->AttributeBytesTo(
|
2021-04-14 08:44:58 +00:00
|
|
|
V8SnapshotProfileWriter::kArtificialRootId,
|
2020-05-26 10:46:05 +00:00
|
|
|
end_position - start_position);
|
|
|
|
}
|
|
|
|
#endif
|
2018-11-22 15:14:46 +00:00
|
|
|
|
2017-11-02 00:57:42 +00:00
|
|
|
// Heap page objects start here.
|
|
|
|
|
|
|
|
for (intptr_t i = 0; i < objects_.length(); i++) {
|
|
|
|
const Object& obj = *objects_[i].obj_;
|
2020-10-06 17:10:05 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
2018-12-03 19:11:42 +00:00
|
|
|
AutoTraceImage(obj, section_start, stream);
|
2020-10-06 17:10:05 +00:00
|
|
|
#endif
|
2020-10-06 07:59:33 +00:00
|
|
|
auto const object_start = stream->Position();
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
NoSafepointScope no_safepoint;
|
|
|
|
|
2019-03-07 00:20:30 +00:00
|
|
|
// Write object header with the mark and read-only bits set.
|
2020-10-06 07:59:33 +00:00
|
|
|
stream->WriteTargetWord(GetMarkedTags(obj));
|
[vm/compiler] Reland "Further compress the information... in StackMaps."
Fixes an assumption that CompressedStackMapsIterator::Find() is never
passed a PC offset of 0. Adds back an ASSERT that was dropped which checks
for specific cases where a given PC offset does not have a stack map entry.
Original commit message:
Lifting the PC offset in a2bb730 was a small, lightweight change that
gave us big gains, at least on 32-bit architectures. Here, we make
much more invasive changes that will improve the amount of memory used
by the information previously stored in StackMap objects.
Instead of allocating separate objects for StackMaps, we instead compress
all StackMap information for a given Code object into a single object
(CompressedStackMaps, or CSM for short). This replaces the Array used to
store PC offsets (as Smis) and the individual StackMap objects.
While we lose all canonicalization for individual StackMap entries, the
drop in space required to store stack map information more than offsets that.
-----
The impact on AOT snapshot size when compiling the Flutter Gallery
in release mode:
armv7: Total size -2.58% (Isolate RO: +14.46%, Isolate snapshot: -22.93%)
armv8: Total size -1.85% (Isolate RO: +15.69%, Isolate snapshot: -22.97%)
The impact on in-memory, not on-disk, size for the Flutter Gallery as seen
in the Observatory while running a profile (not release) build:
armv7: Drops from 7.1 MB to 6.2MB (-0.9 MB)
armv8: Drops from 13.5MB to 11.7MB (-1.8 MB)
-----
Bug: https://github.com/dart-lang/sdk/issues/35274, https://github.com/dart-lang/sdk/issues/38873
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-mac-debug-simdbc64-try
Change-Id: I111b129b0ed64f03184370bceb7cda69d5d4b3c9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121700
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-10-16 08:25:53 +00:00
|
|
|
if (obj.IsCompressedStackMaps()) {
|
|
|
|
const CompressedStackMaps& map = CompressedStackMaps::Cast(obj);
|
|
|
|
const intptr_t payload_size = map.payload_size();
|
2021-01-15 23:32:02 +00:00
|
|
|
stream->WriteTargetWord(map.ptr()->untag()->flags_and_size_);
|
2020-02-14 17:57:47 +00:00
|
|
|
ASSERT_EQUAL(stream->Position() - object_start,
|
|
|
|
compiler::target::CompressedStackMaps::HeaderSize());
|
2021-01-15 23:32:02 +00:00
|
|
|
stream->WriteBytes(map.ptr()->untag()->data(), payload_size);
|
2019-06-21 04:00:35 +00:00
|
|
|
} else if (obj.IsCodeSourceMap()) {
|
|
|
|
const CodeSourceMap& map = CodeSourceMap::Cast(obj);
|
|
|
|
stream->WriteTargetWord(map.Length());
|
2020-10-06 07:59:33 +00:00
|
|
|
ASSERT_EQUAL(stream->Position() - object_start,
|
|
|
|
compiler::target::CodeSourceMap::HeaderSize());
|
2019-06-21 04:00:35 +00:00
|
|
|
stream->WriteBytes(map.Data(), map.Length());
|
|
|
|
} else if (obj.IsPcDescriptors()) {
|
|
|
|
const PcDescriptors& desc = PcDescriptors::Cast(obj);
|
|
|
|
stream->WriteTargetWord(desc.Length());
|
2020-10-06 07:59:33 +00:00
|
|
|
ASSERT_EQUAL(stream->Position() - object_start,
|
|
|
|
compiler::target::PcDescriptors::HeaderSize());
|
2021-01-15 23:32:02 +00:00
|
|
|
stream->WriteBytes(desc.ptr()->untag()->data(), desc.Length());
|
2020-11-02 21:11:50 +00:00
|
|
|
} else if (obj.IsString()) {
|
|
|
|
const String& str = String::Cast(obj);
|
2021-01-15 23:32:02 +00:00
|
|
|
RELEASE_ASSERT(String::GetCachedHash(str.ptr()) != 0);
|
2020-11-02 21:11:50 +00:00
|
|
|
RELEASE_ASSERT(str.IsOneByteString() || str.IsTwoByteString());
|
|
|
|
|
2021-04-05 17:43:16 +00:00
|
|
|
stream->WriteTargetWord(static_cast<uword>(str.ptr()->untag()->length()));
|
2020-11-02 21:11:50 +00:00
|
|
|
#if !defined(HASH_IN_OBJECT_HEADER)
|
2021-04-05 17:43:16 +00:00
|
|
|
stream->WriteTargetWord(static_cast<uword>(str.ptr()->untag()->hash()));
|
2020-11-02 21:11:50 +00:00
|
|
|
#endif
|
|
|
|
ASSERT_EQUAL(stream->Position() - object_start,
|
|
|
|
compiler::target::String::InstanceSize());
|
|
|
|
stream->WriteBytes(
|
|
|
|
str.IsOneByteString()
|
|
|
|
? static_cast<const void*>(OneByteString::DataStart(str))
|
|
|
|
: static_cast<const void*>(TwoByteString::DataStart(str)),
|
|
|
|
str.Length() * (str.IsOneByteString()
|
|
|
|
? OneByteString::kBytesPerElement
|
|
|
|
: TwoByteString::kBytesPerElement));
|
2019-06-21 04:00:35 +00:00
|
|
|
} else {
|
|
|
|
const Class& clazz = Class::Handle(obj.clazz());
|
2020-10-06 07:59:33 +00:00
|
|
|
FATAL("Unsupported class %s in rodata section.\n", clazz.ToCString());
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
2020-10-06 07:59:33 +00:00
|
|
|
stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
|
|
|
|
ASSERT_EQUAL(stream->Position() - object_start, SizeInSnapshot(obj));
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-19 15:29:57 +00:00
|
|
|
static constexpr uword kReadOnlyGCBits =
|
2021-01-15 23:32:02 +00:00
|
|
|
UntaggedObject::OldBit::encode(true) |
|
|
|
|
UntaggedObject::OldAndNotMarkedBit::encode(false) |
|
|
|
|
UntaggedObject::OldAndNotRememberedBit::encode(true) |
|
|
|
|
UntaggedObject::NewBit::encode(false);
|
2020-10-06 07:59:33 +00:00
|
|
|
|
2020-11-02 21:11:50 +00:00
|
|
|
uword ImageWriter::GetMarkedTags(classid_t cid,
|
|
|
|
intptr_t size,
|
|
|
|
bool is_canonical /* = false */) {
|
2021-01-15 23:32:02 +00:00
|
|
|
// UntaggedObject::SizeTag expects a size divisible by kObjectAlignment and
|
2020-10-06 07:59:33 +00:00
|
|
|
// checks this in debug mode, but the size on the target machine may not be
|
|
|
|
// divisible by the host machine's object alignment if they differ.
|
|
|
|
//
|
|
|
|
// We define [adjusted_size] as [size] * m, where m is the host alignment
|
|
|
|
// divided by the target alignment. This means [adjusted_size] encodes on the
|
|
|
|
// host machine to the same bits that decode to [size] on the target machine.
|
|
|
|
// That is,
|
|
|
|
// [adjusted_size] / host align ==
|
|
|
|
// [size] * (host align / target align) / host align ==
|
|
|
|
// [size] / target align
|
|
|
|
//
|
|
|
|
// Since alignments are always powers of 2, we use shifts and logs.
|
|
|
|
const intptr_t adjusted_size =
|
|
|
|
size << (kObjectAlignmentLog2 -
|
|
|
|
compiler::target::ObjectAlignment::kObjectAlignmentLog2);
|
|
|
|
|
2021-01-15 23:32:02 +00:00
|
|
|
return kReadOnlyGCBits | UntaggedObject::ClassIdTag::encode(cid) |
|
|
|
|
UntaggedObject::SizeTag::encode(adjusted_size) |
|
|
|
|
UntaggedObject::CanonicalBit::encode(is_canonical);
|
2020-10-06 07:59:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uword ImageWriter::GetMarkedTags(const Object& obj) {
|
2021-01-15 23:32:02 +00:00
|
|
|
uword tags = GetMarkedTags(obj.ptr()->untag()->GetClassId(),
|
|
|
|
SizeInSnapshot(obj), obj.IsCanonical());
|
2020-10-06 07:59:33 +00:00
|
|
|
#if defined(HASH_IN_OBJECT_HEADER)
|
2021-01-15 23:32:02 +00:00
|
|
|
tags = UntaggedObject::HashTag::update(obj.ptr()->untag()->GetHeaderHash(),
|
|
|
|
tags);
|
2020-10-06 07:59:33 +00:00
|
|
|
#endif
|
2020-11-30 23:43:54 +00:00
|
|
|
return tags;
|
2020-10-06 07:59:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
const char* ImageWriter::SectionSymbol(ProgramSection section, bool vm) const {
|
|
|
|
switch (section) {
|
|
|
|
case ProgramSection::Text:
|
|
|
|
return vm ? kVmSnapshotInstructionsAsmSymbol
|
|
|
|
: kIsolateSnapshotInstructionsAsmSymbol;
|
|
|
|
case ProgramSection::Data:
|
|
|
|
return vm ? kVmSnapshotDataAsmSymbol : kIsolateSnapshotDataAsmSymbol;
|
|
|
|
case ProgramSection::Bss:
|
|
|
|
return vm ? kVmSnapshotBssAsmSymbol : kIsolateSnapshotBssAsmSymbol;
|
|
|
|
case ProgramSection::BuildId:
|
|
|
|
return kSnapshotBuildIdAsmSymbol;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWriter::WriteText(bool vm) {
|
|
|
|
Zone* zone = Thread::Current()->zone();
|
|
|
|
|
|
|
|
const bool bare_instruction_payloads =
|
|
|
|
FLAG_precompiled_mode && FLAG_use_bare_instructions;
|
|
|
|
|
|
|
|
// Start snapshot at page boundary.
|
|
|
|
ASSERT(ImageWriter::kTextAlignment >= VirtualMemory::PageSize());
|
|
|
|
if (!EnterSection(ProgramSection::Text, vm, ImageWriter::kTextAlignment)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t text_offset = 0;
|
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
// Parent used for later profile objects. Starts off as the Image. When
|
|
|
|
// writing bare instructions payloads, this is later updated with the
|
|
|
|
// InstructionsSection object which contains all the bare payloads.
|
|
|
|
V8SnapshotProfileWriter::ObjectId parent_id(offset_space_, text_offset);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// This head also provides the gap to make the instructions snapshot
|
|
|
|
// look like a OldPage.
|
|
|
|
const intptr_t image_size = Utils::RoundUp(
|
|
|
|
next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
|
|
|
|
text_offset += WriteTargetWord(image_size);
|
|
|
|
// Output the offset to the InstructionsSection object from the start of the
|
|
|
|
// image, if any.
|
|
|
|
text_offset +=
|
|
|
|
WriteTargetWord(FLAG_precompiled_mode ? Image::kHeaderSize
|
|
|
|
: Image::kNoInstructionsSection);
|
|
|
|
// Zero values for the rest of the Image object header bytes.
|
|
|
|
text_offset += Align(Image::kHeaderSize, text_offset);
|
|
|
|
ASSERT_EQUAL(text_offset, Image::kHeaderSize);
|
|
|
|
|
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
const char* instructions_symbol = SectionSymbol(ProgramSection::Text, vm);
|
|
|
|
ASSERT(instructions_symbol != nullptr);
|
|
|
|
const char* bss_symbol = SectionSymbol(ProgramSection::Bss, vm);
|
|
|
|
ASSERT(bss_symbol != nullptr);
|
|
|
|
|
|
|
|
if (FLAG_precompiled_mode) {
|
|
|
|
if (profile_writer_ != nullptr) {
|
|
|
|
profile_writer_->SetObjectTypeAndName(parent_id, image_type_,
|
|
|
|
instructions_symbol);
|
|
|
|
profile_writer_->AttributeBytesTo(parent_id, Image::kHeaderSize);
|
|
|
|
profile_writer_->AddRoot(parent_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
const intptr_t section_header_length =
|
|
|
|
compiler::target::InstructionsSection::HeaderSize();
|
|
|
|
// Calculated using next_text_offset_, which doesn't include post-payload
|
|
|
|
// padding to object alignment. Note that if not in bare instructions mode,
|
|
|
|
// the section has no contents, instead the instructions objects follow it.
|
|
|
|
const intptr_t section_payload_length =
|
|
|
|
bare_instruction_payloads
|
|
|
|
? next_text_offset_ - text_offset - section_header_length
|
|
|
|
: 0;
|
|
|
|
const intptr_t section_size =
|
|
|
|
compiler::target::InstructionsSection::InstanceSize(
|
|
|
|
section_payload_length);
|
|
|
|
|
|
|
|
const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
|
|
|
|
if (profile_writer_ != nullptr) {
|
|
|
|
profile_writer_->SetObjectTypeAndName(id, instructions_section_type_,
|
|
|
|
instructions_symbol);
|
|
|
|
profile_writer_->AttributeBytesTo(id,
|
|
|
|
section_size - section_payload_length);
|
2021-04-20 11:17:36 +00:00
|
|
|
const intptr_t element_offset = id.nonce() - parent_id.nonce();
|
2020-10-06 17:10:05 +00:00
|
|
|
profile_writer_->AttributeReferenceTo(
|
|
|
|
parent_id,
|
2021-04-20 11:17:36 +00:00
|
|
|
V8SnapshotProfileWriter::Reference::Element(element_offset), id);
|
2020-10-06 17:10:05 +00:00
|
|
|
// Later objects will have the InstructionsSection as a parent if in
|
|
|
|
// bare instructions mode, otherwise the image.
|
|
|
|
if (bare_instruction_payloads) {
|
|
|
|
parent_id = id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the RawInstructionsSection header.
|
|
|
|
text_offset +=
|
|
|
|
WriteTargetWord(GetMarkedTags(kInstructionsSectionCid, section_size));
|
|
|
|
// An InstructionsSection has five fields:
|
|
|
|
// 1) The length of the payload.
|
|
|
|
text_offset += WriteTargetWord(section_payload_length);
|
|
|
|
// 2) The BSS offset from this section.
|
|
|
|
text_offset += Relocation(text_offset, instructions_symbol, bss_symbol);
|
|
|
|
// 3) The relocated address of the instructions.
|
|
|
|
text_offset += WriteTargetWord(RelocatedAddress(instructions_symbol));
|
|
|
|
// 4) The GNU build ID note offset from this section.
|
|
|
|
text_offset += Relocation(text_offset, instructions_symbol,
|
|
|
|
SectionSymbol(ProgramSection::BuildId, vm));
|
|
|
|
|
|
|
|
const intptr_t section_contents_alignment =
|
|
|
|
bare_instruction_payloads
|
|
|
|
? compiler::target::Instructions::kBarePayloadAlignment
|
|
|
|
: compiler::target::ObjectAlignment::kObjectAlignment;
|
|
|
|
const intptr_t expected_size =
|
|
|
|
bare_instruction_payloads
|
|
|
|
? compiler::target::InstructionsSection::HeaderSize()
|
|
|
|
: compiler::target::InstructionsSection::InstanceSize(0);
|
|
|
|
text_offset += Align(section_contents_alignment, text_offset);
|
2021-04-20 11:17:36 +00:00
|
|
|
ASSERT_EQUAL(text_offset - id.nonce(), expected_size);
|
2020-10-06 17:10:05 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
FrameUnwindPrologue();
|
|
|
|
|
|
|
|
PcDescriptors& descriptors = PcDescriptors::Handle(zone);
|
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
SnapshotTextObjectNamer namer(zone);
|
|
|
|
#endif
|
|
|
|
|
2021-04-20 11:17:36 +00:00
|
|
|
ASSERT(offset_space_ != IdSpace::kSnapshot);
|
2020-10-06 17:10:05 +00:00
|
|
|
for (intptr_t i = 0; i < instructions_.length(); i++) {
|
|
|
|
auto& data = instructions_[i];
|
|
|
|
const bool is_trampoline = data.trampoline_bytes != nullptr;
|
|
|
|
ASSERT_EQUAL(data.text_offset_, text_offset);
|
|
|
|
|
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
// We won't add trampolines as symbols, so their name need not be unique
|
|
|
|
// across different WriteText() calls.
|
|
|
|
const char* object_name = namer.SnapshotNameFor(
|
|
|
|
is_trampoline ? i : unique_symbol_counter_++, data);
|
|
|
|
|
|
|
|
if (profile_writer_ != nullptr) {
|
|
|
|
const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
|
|
|
|
auto const type = is_trampoline ? trampoline_type_ : instructions_type_;
|
|
|
|
const intptr_t size = is_trampoline ? data.trampoline_length
|
2021-01-15 23:32:02 +00:00
|
|
|
: SizeInSnapshot(data.insns_->ptr());
|
2020-10-06 17:10:05 +00:00
|
|
|
profile_writer_->SetObjectTypeAndName(id, type, object_name);
|
|
|
|
profile_writer_->AttributeBytesTo(id, size);
|
2021-04-20 11:17:36 +00:00
|
|
|
const intptr_t element_offset = id.nonce() - parent_id.nonce();
|
2020-10-06 17:10:05 +00:00
|
|
|
profile_writer_->AttributeReferenceTo(
|
|
|
|
parent_id,
|
2021-04-20 11:17:36 +00:00
|
|
|
V8SnapshotProfileWriter::Reference::Element(element_offset), id);
|
2020-10-06 17:10:05 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (is_trampoline) {
|
|
|
|
text_offset += WriteBytes(data.trampoline_bytes, data.trampoline_length);
|
|
|
|
delete[] data.trampoline_bytes;
|
|
|
|
data.trampoline_bytes = nullptr;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const intptr_t instr_start = text_offset;
|
|
|
|
const auto& code = *data.code_;
|
|
|
|
const auto& insns = *data.insns_;
|
|
|
|
|
|
|
|
// 1. Write from the object start to the payload start. This includes the
|
|
|
|
// object header and the fixed fields. Not written for AOT snapshots using
|
|
|
|
// bare instructions.
|
|
|
|
if (!bare_instruction_payloads) {
|
|
|
|
NoSafepointScope no_safepoint;
|
|
|
|
|
|
|
|
// Write Instructions with the mark and read-only bits set.
|
|
|
|
text_offset += WriteTargetWord(GetMarkedTags(insns));
|
2021-01-15 23:32:02 +00:00
|
|
|
text_offset += WriteFixed(insns.untag()->size_and_flags_);
|
2020-10-06 17:10:05 +00:00
|
|
|
text_offset +=
|
|
|
|
Align(compiler::target::Instructions::kNonBarePayloadAlignment,
|
|
|
|
text_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_EQUAL(text_offset - instr_start,
|
|
|
|
compiler::target::Instructions::HeaderSize());
|
|
|
|
|
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
// 2. Add a symbol for the code at the entry point in precompiled snapshots.
|
|
|
|
// Linux's perf uses these labels.
|
|
|
|
AddCodeSymbol(code, object_name, text_offset);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
{
|
|
|
|
NoSafepointScope no_safepoint;
|
|
|
|
|
|
|
|
// 3. Write from the payload start to payload end. For AOT snapshots
|
|
|
|
// with bare instructions, this is the only part serialized other than
|
|
|
|
// any padding needed for alignment.
|
|
|
|
auto const payload_start =
|
|
|
|
reinterpret_cast<const uint8_t*>(insns.PayloadStart());
|
|
|
|
// Double-check the payload alignment, since we will load and write
|
|
|
|
// target-sized words starting from that address.
|
|
|
|
ASSERT(Utils::IsAligned(payload_start, compiler::target::kWordSize));
|
|
|
|
const uword payload_size = insns.Size();
|
|
|
|
descriptors = code.pc_descriptors();
|
|
|
|
PcDescriptors::Iterator iterator(
|
2021-01-15 23:32:02 +00:00
|
|
|
descriptors, /*kind_mask=*/UntaggedPcDescriptors::kBSSRelocation);
|
2020-10-06 17:10:05 +00:00
|
|
|
|
|
|
|
auto const payload_end = payload_start + payload_size;
|
|
|
|
auto cursor = payload_start;
|
|
|
|
while (iterator.MoveNext()) {
|
|
|
|
ASSERT(FLAG_precompiled_mode);
|
|
|
|
auto const next_reloc_offset = iterator.PcOffset();
|
|
|
|
auto const next_reloc_address = payload_start + next_reloc_offset;
|
|
|
|
// We only generate BSS relocations that are target word-sized and at
|
|
|
|
// target word-aligned offsets in the payload. Double-check this..
|
|
|
|
ASSERT(
|
|
|
|
Utils::IsAligned(next_reloc_address, compiler::target::kWordSize));
|
|
|
|
text_offset += WriteBytes(cursor, next_reloc_address - cursor);
|
|
|
|
|
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
// The instruction stream at the relocation position holds an offset
|
|
|
|
// into BSS corresponding to the symbol being resolved. This addend is
|
|
|
|
// factored into the relocation.
|
|
|
|
const auto addend = *reinterpret_cast<const compiler::target::word*>(
|
|
|
|
next_reloc_address);
|
|
|
|
text_offset += Relocation(text_offset, instructions_symbol, text_offset,
|
|
|
|
bss_symbol, /*target_offset=*/0, addend);
|
|
|
|
#endif
|
|
|
|
cursor = next_reloc_address + compiler::target::kWordSize;
|
|
|
|
}
|
|
|
|
text_offset += WriteBytes(cursor, payload_end - cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4. Add appropriate padding. Note we can't simply copy from the object
|
|
|
|
// because the host object may have less alignment filler than the target
|
|
|
|
// object in the cross-word case.
|
|
|
|
const intptr_t alignment =
|
|
|
|
bare_instruction_payloads
|
|
|
|
? compiler::target::Instructions::kBarePayloadAlignment
|
|
|
|
: compiler::target::ObjectAlignment::kObjectAlignment;
|
|
|
|
text_offset += AlignWithBreakInstructions(alignment, text_offset);
|
|
|
|
|
2021-01-15 23:32:02 +00:00
|
|
|
ASSERT_EQUAL(text_offset - instr_start, SizeInSnapshot(insns.ptr()));
|
2020-10-06 17:10:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Should be a no-op unless writing bare instruction payloads, in which case
|
|
|
|
// we need to add post-payload padding for the InstructionsSection object.
|
|
|
|
// Since this follows instructions, we'll use break instructions for padding.
|
|
|
|
ASSERT(bare_instruction_payloads ||
|
|
|
|
Utils::IsAligned(text_offset,
|
|
|
|
compiler::target::ObjectAlignment::kObjectAlignment));
|
|
|
|
text_offset += AlignWithBreakInstructions(
|
|
|
|
compiler::target::ObjectAlignment::kObjectAlignment, text_offset);
|
|
|
|
|
|
|
|
ASSERT_EQUAL(text_offset, image_size);
|
|
|
|
|
|
|
|
FrameUnwindEpilogue();
|
|
|
|
|
|
|
|
ExitSection(ProgramSection::Text, vm, text_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t ImageWriter::AlignWithBreakInstructions(intptr_t alignment,
|
|
|
|
intptr_t offset) {
|
|
|
|
intptr_t bytes_written = 0;
|
|
|
|
uword remaining;
|
|
|
|
for (remaining = Utils::RoundUp(offset, alignment) - offset;
|
|
|
|
remaining >= compiler::target::kWordSize;
|
|
|
|
remaining -= compiler::target::kWordSize) {
|
|
|
|
bytes_written += WriteTargetWord(kBreakInstructionFiller);
|
|
|
|
}
|
|
|
|
#if defined(TARGET_ARCH_ARM)
|
|
|
|
// All instructions are 4 bytes long on ARM architectures, so on 32-bit ARM
|
|
|
|
// there won't be any padding.
|
|
|
|
ASSERT_EQUAL(remaining, 0);
|
|
|
|
#elif defined(TARGET_ARCH_ARM64)
|
|
|
|
// All instructions are 4 bytes long on ARM architectures, so on 64-bit ARM
|
|
|
|
// there is only 0 or 4 bytes of padding.
|
|
|
|
if (remaining != 0) {
|
|
|
|
ASSERT_EQUAL(remaining, 4);
|
|
|
|
bytes_written += WriteBytes(&kBreakInstructionFiller, remaining);
|
|
|
|
}
|
|
|
|
#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
|
|
|
|
// The break instruction is a single byte, repeated to fill a word.
|
|
|
|
bytes_written += WriteBytes(&kBreakInstructionFiller, remaining);
|
|
|
|
#else
|
|
|
|
#error Unexpected architecture.
|
|
|
|
#endif
|
|
|
|
ASSERT_EQUAL(bytes_written, Utils::RoundUp(offset, alignment) - offset);
|
|
|
|
return bytes_written;
|
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
|
|
|
|
// Indices are log2(size in bytes).
|
|
|
|
static constexpr const char* kSizeDirectives[] = {".byte", ".2byte", ".long",
|
|
|
|
".quad"};
|
|
|
|
|
|
|
|
static constexpr const char* kWordDirective =
|
|
|
|
kSizeDirectives[compiler::target::kWordSizeLog2];
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
class DwarfAssemblyStream : public DwarfWriteStream {
|
|
|
|
public:
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
explicit DwarfAssemblyStream(BaseWriteStream* stream)
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
: stream_(ASSERT_NOTNULL(stream)) {}
|
|
|
|
|
2020-09-24 16:58:30 +00:00
|
|
|
void sleb128(intptr_t value) { stream_->Printf(".sleb128 %" Pd "\n", value); }
|
|
|
|
void uleb128(uintptr_t value) {
|
|
|
|
stream_->Printf(".uleb128 %" Pd "\n", value);
|
|
|
|
}
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
void u1(uint8_t value) {
|
|
|
|
stream_->Printf("%s %u\n", kSizeDirectives[kInt8SizeLog2], value);
|
|
|
|
}
|
|
|
|
void u2(uint16_t value) {
|
|
|
|
stream_->Printf("%s %u\n", kSizeDirectives[kInt16SizeLog2], value);
|
|
|
|
}
|
|
|
|
void u4(uint32_t value) {
|
|
|
|
stream_->Printf("%s %" Pu32 "\n", kSizeDirectives[kInt32SizeLog2], value);
|
|
|
|
}
|
|
|
|
void u8(uint64_t value) {
|
|
|
|
stream_->Printf("%s %" Pu64 "\n", kSizeDirectives[kInt64SizeLog2], value);
|
|
|
|
}
|
|
|
|
void string(const char* cstr) { // NOLINT
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf(".string \"%s\"\n", cstr); // NOLINT
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
}
|
|
|
|
// Uses labels, so doesn't output to start or return a useful fixup position.
|
|
|
|
intptr_t ReserveSize(const char* prefix, intptr_t* start) {
|
|
|
|
// Assignment to temp works around buggy Mac assembler.
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf("L%s_size = .L%s_end - .L%s_start\n", prefix, prefix,
|
|
|
|
prefix);
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
stream_->Printf("%s L%s_size\n", kSizeDirectives[kInt32SizeLog2], prefix);
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf(".L%s_start:\n", prefix);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
// Just need to label the end so the assembler can calculate the size, so
|
|
|
|
// start and the fixup position is unused.
|
|
|
|
void SetSize(intptr_t fixup, const char* prefix, intptr_t start) {
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf(".L%s_end:\n", prefix);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
}
|
|
|
|
void OffsetFromSymbol(const char* symbol, intptr_t offset) {
|
2020-06-12 15:05:35 +00:00
|
|
|
if (offset == 0) {
|
|
|
|
PrintNamedAddress(symbol);
|
|
|
|
} else {
|
|
|
|
PrintNamedAddressWithOffset(symbol, offset);
|
|
|
|
}
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
}
|
|
|
|
void DistanceBetweenSymbolOffsets(const char* symbol1,
|
|
|
|
intptr_t offset1,
|
|
|
|
const char* symbol2,
|
|
|
|
intptr_t offset2) {
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf(".uleb128 %s - %s + %" Pd "\n", symbol1, symbol2,
|
|
|
|
offset1 - offset2);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// No-op, we'll be using labels.
|
|
|
|
void InitializeAbstractOrigins(intptr_t size) {}
|
|
|
|
void RegisterAbstractOrigin(intptr_t index) {
|
|
|
|
// Label for DW_AT_abstract_origin references
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf(".Lfunc%" Pd ":\n", index);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
}
|
|
|
|
void AbstractOrigin(intptr_t index) {
|
|
|
|
// Assignment to temp works around buggy Mac assembler.
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf("Ltemp%" Pd " = .Lfunc%" Pd " - %s\n", temp_, index,
|
|
|
|
kDebugInfoLabel);
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
stream_->Printf("%s Ltemp%" Pd "\n", kSizeDirectives[kInt32SizeLog2],
|
|
|
|
temp_);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
temp_++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Methods for writing the assembly prologues for various DWARF sections.
|
|
|
|
void AbbreviationsPrologue() {
|
|
|
|
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->WriteString(".section __DWARF,__debug_abbrev,regular,debug\n");
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
|
|
|
|
defined(TARGET_OS_FUCHSIA)
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->WriteString(".section .debug_abbrev,\"\"\n");
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
#else
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
void DebugInfoPrologue() {
|
|
|
|
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->WriteString(".section __DWARF,__debug_info,regular,debug\n");
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
|
|
|
|
defined(TARGET_OS_FUCHSIA)
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->WriteString(".section .debug_info,\"\"\n");
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
#else
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
#endif
|
|
|
|
// Used to calculate abstract origin values.
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->Printf("%s:\n", kDebugInfoLabel);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
}
|
|
|
|
void LineNumberProgramPrologue() {
|
|
|
|
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->WriteString(".section __DWARF,__debug_line,regular,debug\n");
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
|
|
|
|
defined(TARGET_OS_FUCHSIA)
|
2020-09-24 16:58:30 +00:00
|
|
|
stream_->WriteString(".section .debug_line,\"\"\n");
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
#else
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static constexpr const char* kDebugInfoLabel = ".Ldebug_info";
|
|
|
|
|
2020-09-24 16:58:30 +00:00
|
|
|
void PrintNamedAddress(const char* name) {
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
stream_->Printf("%s %s\n", kWordDirective, name);
|
2020-09-24 16:58:30 +00:00
|
|
|
}
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
void PrintNamedAddressWithOffset(const char* name, intptr_t offset) {
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
stream_->Printf("%s %s + %" Pd "\n", kWordDirective, name, offset);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
}
|
|
|
|
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
BaseWriteStream* const stream_;
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
intptr_t temp_ = 0;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(DwarfAssemblyStream);
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline Dwarf* AddDwarfIfUnstripped(Zone* zone, bool strip, Elf* elf) {
|
|
|
|
if (!strip) {
|
|
|
|
if (elf != nullptr) {
|
|
|
|
// Reuse the existing DWARF object.
|
|
|
|
ASSERT(elf->dwarf() != nullptr);
|
|
|
|
return elf->dwarf();
|
|
|
|
}
|
|
|
|
return new (zone) Dwarf(zone);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-11-01 14:22:37 +00:00
|
|
|
AssemblyImageWriter::AssemblyImageWriter(Thread* thread,
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
BaseWriteStream* stream,
|
2019-12-20 10:14:10 +00:00
|
|
|
bool strip,
|
|
|
|
Elf* debug_elf)
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
: ImageWriter(thread),
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
assembly_stream_(stream),
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
assembly_dwarf_(AddDwarfIfUnstripped(thread->zone(), strip, debug_elf)),
|
|
|
|
debug_elf_(debug_elf) {}
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
void AssemblyImageWriter::Finalize() {
|
[vm/compiler] Clean up ELF creation code.
Instead of making the ELF object handle stripping and keep track of two
possible output stream, just revert ELF objects to only output to a
single stream. Now, layers that use ELF, like the ImageWriters, handle
the stripping by deciding whether or not to add certain sections or
static symbols to the generated ELF, and we create separate DWARF
objects for each unstripped ELF object.
We also avoid duplication of writing segment and section table entries
by just creating special Sections that correspond to reserved entries,
the program table header entries for itself, etc, and then move the
section and segment entry writing into Section itself. We also lift
a lot of the same calculations used in subclass construction to the
Section level, and replace the old fields with four different kind
of object members:
* Fields that are known at construction time and thus now const
(e.g., section_type)
* Fields that are not known at construction time that have reasonable
defaults for most instances and so need not be changed from their
default value (e.g., section_link)
* Fields that are not known at construction time which must be set once
(and only once) before use. These are now accessed via getters/setters
that check whether or not the field has been set (e.g., section_name)
* Fields that are calculated from the contents of the particular
subclass, which are now just methods (e.g., FileSize())
We also change the snapshot profile writer test to test the size of
internally stripped ELF output on all platforms without running it
through an external stripping utility (previously untested), and test
assembled or externally stripped output on more platforms where we
support those. Instead of depending on pkg/vm/tool/precompiler2 for
assembling (which always uses gcc), I've added assembleSnapshot and
stripSnapshot to use_flag_test_helper.dart, which mimics the way the
test_runner determines the executable and flags to use.
Change-Id: I4ade45c5caffb443abb3f5c567343504c8085f89
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129083
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-01-10 11:51:57 +00:00
|
|
|
if (assembly_dwarf_ != nullptr) {
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
DwarfAssemblyStream dwarf_stream(assembly_stream_);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
dwarf_stream.AbbreviationsPrologue();
|
|
|
|
assembly_dwarf_->WriteAbbreviations(&dwarf_stream);
|
|
|
|
dwarf_stream.DebugInfoPrologue();
|
|
|
|
assembly_dwarf_->WriteDebugInfo(&dwarf_stream);
|
|
|
|
dwarf_stream.LineNumberProgramPrologue();
|
|
|
|
assembly_dwarf_->WriteLineNumberProgram(&dwarf_stream);
|
[vm/compiler] Clean up ELF creation code.
Instead of making the ELF object handle stripping and keep track of two
possible output stream, just revert ELF objects to only output to a
single stream. Now, layers that use ELF, like the ImageWriters, handle
the stripping by deciding whether or not to add certain sections or
static symbols to the generated ELF, and we create separate DWARF
objects for each unstripped ELF object.
We also avoid duplication of writing segment and section table entries
by just creating special Sections that correspond to reserved entries,
the program table header entries for itself, etc, and then move the
section and segment entry writing into Section itself. We also lift
a lot of the same calculations used in subclass construction to the
Section level, and replace the old fields with four different kind
of object members:
* Fields that are known at construction time and thus now const
(e.g., section_type)
* Fields that are not known at construction time that have reasonable
defaults for most instances and so need not be changed from their
default value (e.g., section_link)
* Fields that are not known at construction time which must be set once
(and only once) before use. These are now accessed via getters/setters
that check whether or not the field has been set (e.g., section_name)
* Fields that are calculated from the contents of the particular
subclass, which are now just methods (e.g., FileSize())
We also change the snapshot profile writer test to test the size of
internally stripped ELF output on all platforms without running it
through an external stripping utility (previously untested), and test
assembled or externally stripped output on more platforms where we
support those. Instead of depending on pkg/vm/tool/precompiler2 for
assembling (which always uses gcc), I've added assembleSnapshot and
stripSnapshot to use_flag_test_helper.dart, which mimics the way the
test_runner determines the executable and flags to use.
Change-Id: I4ade45c5caffb443abb3f5c567343504c8085f89
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129083
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-01-10 11:51:57 +00:00
|
|
|
}
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
if (debug_elf_ != nullptr) {
|
|
|
|
debug_elf_->Finalize();
|
2019-12-20 10:14:10 +00:00
|
|
|
}
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
|
2019-01-23 22:59:47 +00:00
|
|
|
static void EnsureAssemblerIdentifier(char* label) {
|
2017-11-02 00:57:42 +00:00
|
|
|
for (char c = *label; c != '\0'; c = *++label) {
|
|
|
|
if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ||
|
|
|
|
((c >= '0') && (c <= '9'))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*label = '_';
|
|
|
|
}
|
|
|
|
}
|
2019-01-17 17:53:52 +00:00
|
|
|
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
const char* SnapshotTextObjectNamer::SnapshotNameFor(intptr_t code_index,
|
|
|
|
const Code& code) {
|
2019-10-25 11:53:14 +00:00
|
|
|
ASSERT(!code.IsNull());
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
const char* prefix = FLAG_precompiled_mode ? "Precompiled_" : "";
|
2019-10-25 11:53:14 +00:00
|
|
|
owner_ = code.owner();
|
|
|
|
if (owner_.IsNull()) {
|
|
|
|
insns_ = code.instructions();
|
|
|
|
const char* name = StubCode::NameOfStub(insns_.EntryPoint());
|
2019-12-20 10:14:10 +00:00
|
|
|
ASSERT(name != nullptr);
|
2020-06-09 09:08:54 +00:00
|
|
|
return OS::SCreate(zone_, "%sStub_%s", prefix, name);
|
[vm/aot] Drop some Function objects not needed at runtime.
In particular, don't serialize a function if its code is used by the
dispatch table, but there's no need for the function object itself
at runtime like dynamic lookup or dynamic invocation forwarders.
However, just because the owning function is not needed at runtime,
it may be used during serialization for things like assembly label
creation. Thus, instead of just clearing out the Code's owner field,
we add a new WeakSerializationReference (WSR) object whose target is
the original contents of the owner field. The WSR allows the
serializer to access the original owner, but also signals to the
serializer that the target should not be serialized in AOT snapshots
unless there are additional strong (non-WSR) references.
If no strong references are found, then the references to the WSR
in the snapshot are replaced with a reference to a WSR that only
contains the class ID of the original target. The serializer creates
only one WSR per class ID.
If strong references are found, then the target is still serialized.
In this case, the WSR is dropped entirely and any reference to it is
replaced with a direct reference to the serialized target. Thus, WSRs
only exist in the precompiled runtime for targets with no strong
references.
Changes on the Flutter gallery in release mode:
arm7: total size -1.10%, isolate size -6.08%
arm8: total size -1.16%, isolate size -6.09%
Bug: https://github.com/dart-lang/sdk/issues/41052
Change-Id: I5b435ca71ef85f50fe3484789087471a91aa4fe2
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137104
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-03-30 18:33:48 +00:00
|
|
|
}
|
|
|
|
// The weak reference to the Code's owner should never have been removed via
|
|
|
|
// an intermediate serialization, since WSRs are only introduced during
|
|
|
|
// precompilation.
|
|
|
|
owner_ = WeakSerializationReference::Unwrap(owner_);
|
|
|
|
ASSERT(!owner_.IsNull());
|
|
|
|
if (owner_.IsClass()) {
|
2019-10-25 11:53:14 +00:00
|
|
|
string_ = Class::Cast(owner_).Name();
|
|
|
|
const char* name = string_.ToCString();
|
|
|
|
EnsureAssemblerIdentifier(const_cast<char*>(name));
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
return OS::SCreate(zone_, "%sAllocationStub_%s_%" Pd, prefix, name,
|
2019-10-25 11:53:14 +00:00
|
|
|
code_index);
|
|
|
|
} else if (owner_.IsAbstractType()) {
|
|
|
|
const char* name = namer_.StubNameForType(AbstractType::Cast(owner_));
|
2020-04-07 19:13:26 +00:00
|
|
|
return OS::SCreate(zone_, "%s%s_%" Pd, prefix, name, code_index);
|
2019-10-25 11:53:14 +00:00
|
|
|
} else if (owner_.IsFunction()) {
|
|
|
|
const char* name = Function::Cast(owner_).ToQualifiedCString();
|
|
|
|
EnsureAssemblerIdentifier(const_cast<char*>(name));
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
return OS::SCreate(zone_, "%s%s_%" Pd, prefix, name, code_index);
|
2019-10-25 11:53:14 +00:00
|
|
|
} else {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
const char* SnapshotTextObjectNamer::SnapshotNameFor(
|
|
|
|
intptr_t index,
|
|
|
|
const ImageWriter::InstructionsData& data) {
|
|
|
|
if (data.trampoline_bytes != nullptr) {
|
|
|
|
return OS::SCreate(zone_, "Trampoline_%" Pd "", index);
|
|
|
|
}
|
|
|
|
return SnapshotNameFor(index, *data.code_);
|
|
|
|
}
|
|
|
|
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
void AssemblyImageWriter::WriteBss(bool vm) {
|
2020-10-06 17:10:05 +00:00
|
|
|
EnterSection(ProgramSection::Bss, vm, ImageWriter::kBssAlignment);
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
auto const entry_count = vm ? BSS::kVmEntryCount : BSS::kIsolateEntryCount;
|
|
|
|
for (intptr_t i = 0; i < entry_count; i++) {
|
2020-10-06 17:10:05 +00:00
|
|
|
// All bytes in the .bss section must be zero.
|
|
|
|
WriteTargetWord(0);
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
ExitSection(ProgramSection::Bss, vm,
|
|
|
|
entry_count * compiler::target::kWordSize);
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
|
|
|
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
void AssemblyImageWriter::WriteROData(NonStreamingWriteStream* clustered_stream,
|
|
|
|
bool vm) {
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
ImageWriter::WriteROData(clustered_stream, vm);
|
2020-10-06 17:10:05 +00:00
|
|
|
if (!EnterSection(ProgramSection::Data, vm, ImageWriter::kRODataAlignment)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
WriteBytes(clustered_stream->buffer(), clustered_stream->bytes_written());
|
|
|
|
ExitSection(ProgramSection::Data, vm, clustered_stream->bytes_written());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AssemblyImageWriter::EnterSection(ProgramSection section,
|
|
|
|
bool vm,
|
|
|
|
intptr_t alignment) {
|
|
|
|
ASSERT(FLAG_precompiled_mode);
|
|
|
|
ASSERT(current_section_symbol_ == nullptr);
|
|
|
|
bool global_symbol = false;
|
|
|
|
switch (section) {
|
|
|
|
case ProgramSection::Text:
|
|
|
|
assembly_stream_->WriteString(".text\n");
|
|
|
|
global_symbol = true;
|
|
|
|
break;
|
|
|
|
case ProgramSection::Data:
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
|
|
|
|
defined(TARGET_OS_FUCHSIA)
|
2020-10-06 17:10:05 +00:00
|
|
|
assembly_stream_->WriteString(".section .rodata\n");
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#elif defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
|
2020-10-06 17:10:05 +00:00
|
|
|
assembly_stream_->WriteString(".const\n");
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#else
|
2020-10-06 17:10:05 +00:00
|
|
|
UNIMPLEMENTED();
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#endif
|
2020-10-06 17:10:05 +00:00
|
|
|
global_symbol = true;
|
|
|
|
break;
|
|
|
|
case ProgramSection::Bss:
|
|
|
|
assembly_stream_->WriteString(".bss\n");
|
|
|
|
break;
|
|
|
|
case ProgramSection::BuildId:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
current_section_symbol_ = SectionSymbol(section, vm);
|
|
|
|
ASSERT(current_section_symbol_ != nullptr);
|
|
|
|
if (global_symbol) {
|
|
|
|
assembly_stream_->Printf(".globl %s\n", current_section_symbol_);
|
|
|
|
}
|
|
|
|
Align(alignment);
|
|
|
|
assembly_stream_->Printf("%s:\n", current_section_symbol_);
|
|
|
|
return true;
|
|
|
|
}
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
static void ElfAddSection(Elf* elf,
|
|
|
|
ImageWriter::ProgramSection section,
|
|
|
|
const char* symbol,
|
|
|
|
const uint8_t* bytes,
|
|
|
|
intptr_t size) {
|
|
|
|
if (elf == nullptr) return;
|
|
|
|
switch (section) {
|
|
|
|
case ImageWriter::ProgramSection::Text:
|
|
|
|
elf->AddText(symbol, bytes, size);
|
|
|
|
break;
|
|
|
|
case ImageWriter::ProgramSection::Data:
|
|
|
|
elf->AddROData(symbol, bytes, size);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Other sections are handled by the Elf object internally.
|
|
|
|
break;
|
2019-12-20 10:14:10 +00:00
|
|
|
}
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
void AssemblyImageWriter::ExitSection(ProgramSection name,
|
|
|
|
bool vm,
|
|
|
|
intptr_t size) {
|
|
|
|
// We should still be in the same section as the last EnterSection.
|
|
|
|
ASSERT(current_section_symbol_ != nullptr);
|
|
|
|
ASSERT_EQUAL(strcmp(SectionSymbol(name, vm), current_section_symbol_), 0);
|
|
|
|
// We need to generate a text segment of the appropriate size in the ELF
|
|
|
|
// for two reasons:
|
|
|
|
//
|
|
|
|
// * We need unique virtual addresses for each text section in the DWARF
|
|
|
|
// file and that the virtual addresses for payloads within those sections
|
|
|
|
// do not overlap.
|
|
|
|
//
|
|
|
|
// * Our tools for converting DWARF stack traces back to "normal" Dart
|
|
|
|
// stack traces calculate an offset into the appropriate instructions
|
|
|
|
// section, and then add that offset to the virtual address of the
|
|
|
|
// corresponding segment to get the virtual address for the frame.
|
|
|
|
//
|
|
|
|
// Since we don't want to add the actual contents of the segment in the
|
|
|
|
// separate debugging information, we pass nullptr for the bytes, which
|
|
|
|
// creates an appropriate NOBITS section instead of PROGBITS.
|
|
|
|
ElfAddSection(debug_elf_, name, current_section_symbol_, /*bytes=*/nullptr,
|
|
|
|
size);
|
|
|
|
current_section_symbol_ = nullptr;
|
|
|
|
}
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t AssemblyImageWriter::WriteTargetWord(word value) {
|
|
|
|
ASSERT(compiler::target::kBitsPerWord == kBitsPerWord ||
|
|
|
|
Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value));
|
|
|
|
// Padding is helpful for comparing the .S with --disassemble.
|
2020-11-16 23:52:40 +00:00
|
|
|
assembly_stream_->Printf("%s 0x%.*" Px "\n", kWordDirective,
|
2020-10-06 17:10:05 +00:00
|
|
|
2 * compiler::target::kWordSize, value);
|
|
|
|
return compiler::target::kWordSize;
|
|
|
|
}
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t AssemblyImageWriter::Relocation(intptr_t section_offset,
|
|
|
|
const char* source_symbol,
|
|
|
|
intptr_t source_offset,
|
|
|
|
const char* target_symbol,
|
|
|
|
intptr_t target_offset,
|
|
|
|
intptr_t target_addend) {
|
|
|
|
ASSERT(source_symbol != nullptr);
|
|
|
|
ASSERT(target_symbol != nullptr);
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
// TODO(dartbug.com/43274): Remove once we generate consistent build IDs
|
|
|
|
// between assembly snapshots and their debugging information.
|
|
|
|
const char* build_id_symbol =
|
|
|
|
SectionSymbol(ProgramSection::BuildId, /*vm=*/false);
|
|
|
|
if (strcmp(target_symbol, build_id_symbol) == 0) {
|
|
|
|
return WriteTargetWord(Image::kNoBuildId);
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
// All relocations are word-sized.
|
|
|
|
assembly_stream_->Printf("%s ", kWordDirective);
|
|
|
|
if (strcmp(target_symbol, current_section_symbol_) == 0 &&
|
|
|
|
target_offset == section_offset) {
|
|
|
|
assembly_stream_->WriteString("(.)");
|
|
|
|
} else {
|
|
|
|
assembly_stream_->Printf("%s", target_symbol);
|
|
|
|
if (target_offset != 0) {
|
|
|
|
assembly_stream_->Printf(" + %" Pd "", target_offset);
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
if (target_addend != 0) {
|
|
|
|
assembly_stream_->Printf(" + %" Pd "", target_addend);
|
|
|
|
}
|
|
|
|
if (strcmp(source_symbol, current_section_symbol_) == 0 &&
|
|
|
|
source_offset == section_offset) {
|
|
|
|
assembly_stream_->WriteString(" - (.)");
|
|
|
|
} else {
|
|
|
|
assembly_stream_->Printf(" - %s", source_symbol);
|
|
|
|
if (source_offset != 0) {
|
|
|
|
assembly_stream_->Printf(" - %" Pd "", source_offset);
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
assembly_stream_->WriteString("\n");
|
|
|
|
return compiler::target::kWordSize;
|
|
|
|
}
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
void AssemblyImageWriter::AddCodeSymbol(const Code& code,
|
|
|
|
const char* symbol,
|
|
|
|
intptr_t offset) {
|
|
|
|
if (assembly_dwarf_ != nullptr) {
|
|
|
|
assembly_dwarf_->AddCode(code, symbol);
|
|
|
|
}
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
if (debug_elf_ != nullptr) {
|
2020-10-06 17:10:05 +00:00
|
|
|
debug_elf_->dwarf()->AddCode(code, symbol);
|
|
|
|
debug_elf_->AddLocalSymbol(symbol, elf::STT_FUNC, offset, code.Size());
|
2019-12-20 10:14:10 +00:00
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
assembly_stream_->Printf("%s:\n", symbol);
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyImageWriter::FrameUnwindPrologue() {
|
|
|
|
// Creates DWARF's .debug_frame
|
|
|
|
// CFI = Call frame information
|
|
|
|
// CFA = Canonical frame address
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_startproc\n");
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
#if defined(TARGET_ARCH_X64)
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_def_cfa rbp, 0\n"); // CFA is fp+0
|
|
|
|
assembly_stream_->WriteString(
|
|
|
|
".cfi_offset rbp, 0\n"); // saved fp is *(CFA+0)
|
|
|
|
assembly_stream_->WriteString(
|
|
|
|
".cfi_offset rip, 8\n"); // saved pc is *(CFA+8)
|
2017-11-02 00:57:42 +00:00
|
|
|
// saved sp is CFA+16
|
|
|
|
// Should be ".cfi_value_offset rsp, 16", but requires gcc newer than late
|
|
|
|
// 2016 and not supported by Android's libunwind.
|
|
|
|
// DW_CFA_expression 0x10
|
|
|
|
// uleb128 register (rsp) 7 (DWARF register number)
|
|
|
|
// uleb128 size of operation 2
|
|
|
|
// DW_OP_plus_uconst 0x23
|
|
|
|
// uleb128 addend 16
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
#elif defined(TARGET_ARCH_ARM64)
|
2020-12-10 15:51:27 +00:00
|
|
|
COMPILE_ASSERT(R29 == FP);
|
|
|
|
COMPILE_ASSERT(R30 == LINK_REGISTER);
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_def_cfa x29, 0\n"); // CFA is fp+0
|
|
|
|
assembly_stream_->WriteString(
|
|
|
|
".cfi_offset x29, 0\n"); // saved fp is *(CFA+0)
|
|
|
|
assembly_stream_->WriteString(
|
|
|
|
".cfi_offset x30, 8\n"); // saved pc is *(CFA+8)
|
2017-11-02 00:57:42 +00:00
|
|
|
// saved sp is CFA+16
|
|
|
|
// Should be ".cfi_value_offset sp, 16", but requires gcc newer than late
|
|
|
|
// 2016 and not supported by Android's libunwind.
|
|
|
|
// DW_CFA_expression 0x10
|
|
|
|
// uleb128 register (x31) 31
|
|
|
|
// uleb128 size of operation 2
|
|
|
|
// DW_OP_plus_uconst 0x23
|
|
|
|
// uleb128 addend 16
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
#elif defined(TARGET_ARCH_ARM)
|
|
|
|
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
|
|
|
|
COMPILE_ASSERT(FP == R7);
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_def_cfa r7, 0\n"); // CFA is fp+j0
|
|
|
|
assembly_stream_->WriteString(".cfi_offset r7, 0\n"); // saved fp is *(CFA+0)
|
2017-11-02 00:57:42 +00:00
|
|
|
#else
|
|
|
|
COMPILE_ASSERT(FP == R11);
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_def_cfa r11, 0\n"); // CFA is fp+0
|
|
|
|
assembly_stream_->WriteString(
|
|
|
|
".cfi_offset r11, 0\n"); // saved fp is *(CFA+0)
|
2017-11-02 00:57:42 +00:00
|
|
|
#endif
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_offset lr, 4\n"); // saved pc is *(CFA+4)
|
2017-11-02 00:57:42 +00:00
|
|
|
// saved sp is CFA+8
|
|
|
|
// Should be ".cfi_value_offset sp, 8", but requires gcc newer than late
|
|
|
|
// 2016 and not supported by Android's libunwind.
|
|
|
|
// DW_CFA_expression 0x10
|
|
|
|
// uleb128 register (sp) 13
|
|
|
|
// uleb128 size of operation 2
|
|
|
|
// DW_OP_plus_uconst 0x23
|
|
|
|
// uleb128 addend 8
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_escape 0x10, 13, 2, 0x23, 8\n");
|
2017-11-02 00:57:42 +00:00
|
|
|
|
|
|
|
// libunwind on ARM may use .ARM.exidx instead of .debug_frame
|
|
|
|
#if !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_MACOS_IOS)
|
|
|
|
COMPILE_ASSERT(FP == R11);
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".fnstart\n");
|
|
|
|
assembly_stream_->WriteString(".save {r11, lr}\n");
|
|
|
|
assembly_stream_->WriteString(".setfp r11, sp, #0\n");
|
2017-11-02 00:57:42 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void AssemblyImageWriter::FrameUnwindEpilogue() {
|
|
|
|
#if defined(TARGET_ARCH_ARM)
|
|
|
|
#if !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_MACOS_IOS)
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".fnend\n");
|
2017-11-02 00:57:42 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString(".cfi_endproc\n");
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t AssemblyImageWriter::WriteBytes(const void* bytes, intptr_t size) {
|
|
|
|
ASSERT(size >= 0);
|
|
|
|
auto const start = reinterpret_cast<const uint8_t*>(bytes);
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
auto const end_of_words =
|
2020-10-06 17:10:05 +00:00
|
|
|
start + Utils::RoundDown(size, compiler::target::kWordSize);
|
|
|
|
for (auto cursor = reinterpret_cast<const compiler::target::word*>(start);
|
|
|
|
cursor < reinterpret_cast<const compiler::target::word*>(end_of_words);
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
cursor++) {
|
2020-10-06 17:10:05 +00:00
|
|
|
WriteTargetWord(*cursor);
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
auto const end = start + size;
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
if (end != end_of_words) {
|
2020-10-06 17:10:05 +00:00
|
|
|
assembly_stream_->WriteString(kSizeDirectives[kInt8SizeLog2]);
|
|
|
|
for (auto cursor = end_of_words; cursor < end; cursor++) {
|
2020-11-16 23:52:40 +00:00
|
|
|
assembly_stream_->Printf("%s 0x%.2x", cursor != end_of_words ? "," : "",
|
2020-10-06 17:10:05 +00:00
|
|
|
*cursor);
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
}
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->WriteString("\n");
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
return size;
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t AssemblyImageWriter::Align(intptr_t alignment, intptr_t position) {
|
|
|
|
const intptr_t next_position = Utils::RoundUp(position, alignment);
|
2020-09-24 16:58:30 +00:00
|
|
|
assembly_stream_->Printf(".balign %" Pd ", 0\n", alignment);
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
return next_position - position;
|
|
|
|
}
|
[vm] Merge ImageHeader into InstructionsSection.
Before, we only wrapped the Instructions payloads in an
InstructionsSection in precompiled snapshots with bare instructions mode
enabled. This CL changes that to always add an InstructionsSection
wrapper in precompiled snapshots, even when not in bare instructions
mode, and moves all the information from the old ImageHeader object into
the InstructionsSection object instead. Note that in non-bare mode, the
InstructionsSection has no payload, and the Instructions objects follow
the InstructionsSection object instead of being contained by it.
This CL also wraps all implementations of AssemblyImageWriter and
SnapshotTextObjectNamer methods in a single DART_PRECOMPILER ifdef
block, since we only generate assembly in precompiled mode. This
removes the need for the smaller DART_PRECOMPILER ifdef blocks scattered
across the AssemblyImageWriter method implementations.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: I3676fb5c6675845463707acbbb4759a465cfa342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165563
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
#endif // defined(DART_PRECOMPILER)
|
|
|
|
|
2018-11-01 14:22:37 +00:00
|
|
|
BlobImageWriter::BlobImageWriter(Thread* thread,
|
[vm] Simplify symbol naming/address retrieval.
Before, picking a symbol name for a Code object when generating
assembly required adding a placeholder entry in the Dwarf object,
because the Dwarf object separately used a SnapshotTextObjectNamer
to determine the appropriate symbol name to use in relocations.
Instead, now the ImageWriter subclasses are entirely responsible for
creating the symbol name for a given Code object, and that name is
passed when adding the Code object to the Dwarf object.
For Elf output, we eagerly create symbols for sections and Code objects
again in the appropriate symbol table, and so looking up the start of a
given section or Code object can be done simply by asking for the
corresponding symbol's address, removing special case methods and other
workarounds.
We also clean up the generated static and dynamic symbol tables by
only generating local symbols for Code objects and BSS sections (these
are local in assembly output also), and only adding global symbols to
the dynamic symbol table.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ie40c0c836681e98f345483136bb6860e5588ef30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166002
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
NonStreamingWriteStream* vm_instructions,
|
|
|
|
NonStreamingWriteStream* isolate_instructions,
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
Elf* debug_elf,
|
|
|
|
Elf* elf)
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
: ImageWriter(thread),
|
[vm] Simplify symbol naming/address retrieval.
Before, picking a symbol name for a Code object when generating
assembly required adding a placeholder entry in the Dwarf object,
because the Dwarf object separately used a SnapshotTextObjectNamer
to determine the appropriate symbol name to use in relocations.
Instead, now the ImageWriter subclasses are entirely responsible for
creating the symbol name for a given Code object, and that name is
passed when adding the Code object to the Dwarf object.
For Elf output, we eagerly create symbols for sections and Code objects
again in the appropriate symbol table, and so looking up the start of a
given section or Code object can be done simply by asking for the
corresponding symbol's address, removing special case methods and other
workarounds.
We also clean up the generated static and dynamic symbol tables by
only generating local symbols for Code objects and BSS sections (these
are local in assembly output also), and only adding global symbols to
the dynamic symbol table.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ie40c0c836681e98f345483136bb6860e5588ef30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166002
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
vm_instructions_(vm_instructions),
|
|
|
|
isolate_instructions_(isolate_instructions),
|
2019-05-28 18:48:57 +00:00
|
|
|
elf_(elf),
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
debug_elf_(debug_elf) {
|
2019-12-20 10:14:10 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
2020-10-06 17:10:05 +00:00
|
|
|
ASSERT_EQUAL(FLAG_precompiled_mode, elf_ != nullptr);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
ASSERT(debug_elf_ == nullptr || debug_elf_->dwarf() != nullptr);
|
2019-12-20 10:14:10 +00:00
|
|
|
#else
|
2019-05-28 18:48:57 +00:00
|
|
|
RELEASE_ASSERT(elf_ == nullptr);
|
|
|
|
#endif
|
2018-04-27 17:42:16 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t BlobImageWriter::WriteBytes(const void* bytes, intptr_t size) {
|
|
|
|
current_section_stream_->WriteBytes(bytes, size);
|
2019-07-17 23:03:18 +00:00
|
|
|
return size;
|
2019-01-17 12:32:38 +00:00
|
|
|
}
|
|
|
|
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
void BlobImageWriter::WriteBss(bool vm) {
|
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
// We don't actually write a BSS segment, it's created as part of the
|
|
|
|
// Elf constructor, but make sure it has an non-zero start.
|
[vm] Simplify symbol naming/address retrieval.
Before, picking a symbol name for a Code object when generating
assembly required adding a placeholder entry in the Dwarf object,
because the Dwarf object separately used a SnapshotTextObjectNamer
to determine the appropriate symbol name to use in relocations.
Instead, now the ImageWriter subclasses are entirely responsible for
creating the symbol name for a given Code object, and that name is
passed when adding the Code object to the Dwarf object.
For Elf output, we eagerly create symbols for sections and Code objects
again in the appropriate symbol table, and so looking up the start of a
given section or Code object can be done simply by asking for the
corresponding symbol's address, removing special case methods and other
workarounds.
We also clean up the generated static and dynamic symbol tables by
only generating local symbols for Code objects and BSS sections (these
are local in assembly output also), and only adding global symbols to
the dynamic symbol table.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-mac-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ie40c0c836681e98f345483136bb6860e5588ef30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166002
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-10-06 17:10:05 +00:00
|
|
|
ASSERT(elf_ == nullptr ||
|
|
|
|
elf_->SymbolAddress(vm ? kVmSnapshotBssAsmSymbol
|
|
|
|
: kIsolateSnapshotBssAsmSymbol) != 0);
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
[vm] Consolidate the *WriteStream hierarchy.
All *WriteStream classes are now part of the same hierarchy:
class BaseWriteStream : ValueObject;
Base class for all *WriteStreams. Provides all the methods from
the old WriteStream except for buffer() and SetPosition()
(relegated to NonStreamingWriteStreams). Has one pure virtual
method Realloc that must be overridden by concrete subclasses.
class NonStreamingWriteStream : BaseWriteStream;
Base class for all *WriteStreams where the entire stream is available
at all times (i.e., no flushing to an external sink). Extends the
public BaseWriteStream API with buffer() (for accessing the stream
contents) and SetPosition() (for changing the current stream pointer
to the given absolute position in the stream).
class MallocWriteStream : NonStreamingWriteStream;
Uses realloc to reallocate the internal buffer. Almost the same as
the old WriteStream, except that it only takes an initial size. Adds
one public method Steal() for taking ownership of the current buffer
contents (after which the buffer is reset to an empty state). Instead
of passing a pointer to a buffer, the internal buffer must be accessed
via either Steal() or buffer(), which allows access to the current
stream contents without changing ownership or resetting the stream.
The internal buffer is freed on stream destruction.
class ZoneWriteStream: NonStreamingWriteStream;
Takes a zone and reallocates the internal buffer in that zone. No
additional public methods beyond those available from
NonStreamingWriteStream.
class StreamingWriteStream : BaseWriteStream;
Uses realloc to reallocate the internal buffer. Generally same as
before, where the contents of the stream are periodically flushed
using Dart_StreamingWriteCallback. Since it extends BaseWriteStream,
there are now more methods available for writing data to the stream
than just Print/VPrint/WriteBytes. Since portions of the stream may be
flushed and thus no longer in the internal buffer, does not provide
access to the contents of the stream or a way to reposition the
current stream pointer. Flushes any unflushed data and frees the
internal buffer on stream destruction.
Also refactor things so that write streams are passed to appropriate
recipients, instead of the recipients taking arguments they only used to
create a WriteStream internally. Thus, recipients now can just specify
the appropriate base class for the public API used:
* BaseWriteStream for just writing to the stream, or
* NonStreamingWriteStream if re-positioning or the stream contents are
needed.
Change-Id: I419096ecd9331483d168b079fca55b69ef397f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
|
|
|
void BlobImageWriter::WriteROData(NonStreamingWriteStream* clustered_stream,
|
|
|
|
bool vm) {
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
ImageWriter::WriteROData(clustered_stream, vm);
|
2020-10-06 17:10:05 +00:00
|
|
|
current_section_stream_ = clustered_stream;
|
|
|
|
if (!EnterSection(ProgramSection::Data, vm, ImageWriter::kRODataAlignment)) {
|
|
|
|
return;
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
ExitSection(ProgramSection::Data, vm, clustered_stream->bytes_written());
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
bool BlobImageWriter::EnterSection(ProgramSection section,
|
|
|
|
bool vm,
|
|
|
|
intptr_t alignment) {
|
2020-06-10 11:29:27 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
2020-10-06 17:10:05 +00:00
|
|
|
ASSERT_EQUAL(elf_ != nullptr, FLAG_precompiled_mode);
|
2020-06-10 11:29:27 +00:00
|
|
|
#endif
|
2020-10-06 17:10:05 +00:00
|
|
|
// For now, we set current_section_stream_ in ::WriteData.
|
|
|
|
ASSERT(section == ProgramSection::Data || current_section_stream_ == nullptr);
|
|
|
|
ASSERT(current_section_symbol_ == nullptr);
|
|
|
|
switch (section) {
|
|
|
|
case ProgramSection::Text:
|
|
|
|
current_section_stream_ =
|
|
|
|
ASSERT_NOTNULL(vm ? vm_instructions_ : isolate_instructions_);
|
|
|
|
break;
|
|
|
|
case ProgramSection::Data:
|
|
|
|
break;
|
|
|
|
case ProgramSection::Bss:
|
|
|
|
// The BSS section is pre-made in the Elf object for precompiled snapshots
|
|
|
|
// and unused otherwise, so there's no work that needs doing here.
|
|
|
|
return false;
|
|
|
|
case ProgramSection::BuildId:
|
|
|
|
// The GNU build ID is handled specially in the Elf object, and does not
|
|
|
|
// get used for non-precompiled snapshots.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
current_section_symbol_ = SectionSymbol(section, vm);
|
|
|
|
current_section_stream_->Align(alignment);
|
|
|
|
return true;
|
|
|
|
}
|
2020-06-10 11:29:27 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
void BlobImageWriter::ExitSection(ProgramSection name, bool vm, intptr_t size) {
|
|
|
|
// We should still be in the same section as the last EnterSection.
|
|
|
|
ASSERT(current_section_symbol_ != nullptr);
|
|
|
|
ASSERT_EQUAL(strcmp(SectionSymbol(name, vm), current_section_symbol_), 0);
|
2020-06-10 11:29:27 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
2020-10-06 17:10:05 +00:00
|
|
|
ElfAddSection(elf_, name, current_section_symbol_,
|
|
|
|
current_section_stream_->buffer(), size);
|
|
|
|
// We create the corresponding segment in the debugging information as well,
|
|
|
|
// since it needs the contents to create the correct build ID.
|
|
|
|
ElfAddSection(debug_elf_, name, current_section_symbol_,
|
|
|
|
current_section_stream_->buffer(), size);
|
2020-06-10 11:29:27 +00:00
|
|
|
#endif
|
2020-10-06 17:10:05 +00:00
|
|
|
current_section_symbol_ = nullptr;
|
|
|
|
current_section_stream_ = nullptr;
|
|
|
|
}
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t BlobImageWriter::WriteTargetWord(word value) {
|
|
|
|
current_section_stream_->WriteTargetWord(value);
|
|
|
|
return compiler::target::kWordSize;
|
|
|
|
}
|
2018-12-13 12:10:59 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t BlobImageWriter::Align(intptr_t alignment, intptr_t offset) {
|
|
|
|
const intptr_t stream_padding = current_section_stream_->Align(alignment);
|
|
|
|
// Double-check that the offset has the same alignment.
|
|
|
|
ASSERT_EQUAL(Utils::RoundUp(offset, alignment) - offset, stream_padding);
|
|
|
|
return stream_padding;
|
|
|
|
}
|
2019-10-25 11:53:14 +00:00
|
|
|
|
2020-10-06 07:59:33 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
2020-10-06 17:10:05 +00:00
|
|
|
intptr_t BlobImageWriter::Relocation(intptr_t section_offset,
|
|
|
|
const char* source_symbol,
|
|
|
|
intptr_t source_offset,
|
|
|
|
const char* target_symbol,
|
|
|
|
intptr_t target_offset,
|
|
|
|
intptr_t target_addend) {
|
|
|
|
ASSERT(FLAG_precompiled_mode);
|
|
|
|
const uword source_address = RelocatedAddress(source_symbol) + source_offset;
|
|
|
|
const uword target_address = RelocatedAddress(target_symbol) + target_offset;
|
|
|
|
return WriteTargetWord(target_address + target_addend - source_address);
|
|
|
|
}
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
uword BlobImageWriter::RelocatedAddress(const char* symbol) {
|
|
|
|
ASSERT(FLAG_precompiled_mode);
|
|
|
|
ASSERT(symbol != nullptr);
|
|
|
|
if (strcmp(symbol, current_section_symbol_) == 0) {
|
|
|
|
// Cheating a bit here, assuming that the current section will go into its
|
|
|
|
// own load segment (and that the load segment alignment is the same as
|
|
|
|
// the text section alignment).
|
|
|
|
return elf_->NextMemoryOffset(ImageWriter::kTextAlignment);
|
|
|
|
}
|
|
|
|
const uword start = elf_->SymbolAddress(symbol);
|
|
|
|
ASSERT(start != Elf::kNoSectionStart);
|
|
|
|
return start;
|
|
|
|
}
|
2019-09-18 14:56:27 +00:00
|
|
|
|
2020-10-06 17:10:05 +00:00
|
|
|
void BlobImageWriter::AddCodeSymbol(const Code& code,
|
|
|
|
const char* symbol,
|
|
|
|
intptr_t offset) {
|
|
|
|
if (elf_ != nullptr && elf_->dwarf() != nullptr) {
|
|
|
|
elf_->dwarf()->AddCode(code, symbol);
|
|
|
|
elf_->AddLocalSymbol(symbol, elf::STT_FUNC, offset, code.Size());
|
2020-02-14 06:40:31 +00:00
|
|
|
}
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
if (debug_elf_ != nullptr) {
|
2020-10-06 17:10:05 +00:00
|
|
|
debug_elf_->dwarf()->AddCode(code, symbol);
|
|
|
|
debug_elf_->AddLocalSymbol(symbol, elf::STT_FUNC, offset, code.Size());
|
[vm/compiler] Clean up ELF creation code.
Instead of making the ELF object handle stripping and keep track of two
possible output stream, just revert ELF objects to only output to a
single stream. Now, layers that use ELF, like the ImageWriters, handle
the stripping by deciding whether or not to add certain sections or
static symbols to the generated ELF, and we create separate DWARF
objects for each unstripped ELF object.
We also avoid duplication of writing segment and section table entries
by just creating special Sections that correspond to reserved entries,
the program table header entries for itself, etc, and then move the
section and segment entry writing into Section itself. We also lift
a lot of the same calculations used in subclass construction to the
Section level, and replace the old fields with four different kind
of object members:
* Fields that are known at construction time and thus now const
(e.g., section_type)
* Fields that are not known at construction time that have reasonable
defaults for most instances and so need not be changed from their
default value (e.g., section_link)
* Fields that are not known at construction time which must be set once
(and only once) before use. These are now accessed via getters/setters
that check whether or not the field has been set (e.g., section_name)
* Fields that are calculated from the contents of the particular
subclass, which are now just methods (e.g., FileSize())
We also change the snapshot profile writer test to test the size of
internally stripped ELF output on all platforms without running it
through an external stripping utility (previously untested), and test
assembled or externally stripped output on more platforms where we
support those. Instead of depending on pkg/vm/tool/precompiler2 for
assembling (which always uses gcc), I've added assembleSnapshot and
stripSnapshot to use_flag_test_helper.dart, which mimics the way the
test_runner determines the executable and flags to use.
Change-Id: I4ade45c5caffb443abb3f5c567343504c8085f89
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129083
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-01-10 11:51:57 +00:00
|
|
|
}
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
2020-10-06 17:10:05 +00:00
|
|
|
#endif // defined(DART_PRECOMPILER)
|
2019-09-25 17:09:16 +00:00
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2018-04-27 17:42:16 +00:00
|
|
|
ImageReader::ImageReader(const uint8_t* data_image,
|
2019-10-22 19:02:26 +00:00
|
|
|
const uint8_t* instructions_image)
|
[vm] Add build ID to non-symbolic stack traces.
Since we've run out of room for more fields in the Image object header
on 64-bit architectures, the serializer instead creates an ImageHeader
object for precompiled snapshots that is placed at the start of text
segments. The new ImageHeader object contains the following information:
* The offset of the BSS segment from the text segment, previously
stored in the Image object header.
* The relocated address of the text segment in the dynamic shared
object. Due to restrictions when generating assembly snapshots, this
field is only set for ELF snapshots, and so it can also be used to
detect whether a snapshot was compiled to assembly or ELF.
* The offset of the build ID description field from the text segment.
* The length of the build ID description field.
We replace the BSS offset in the Image object header with the offset of
the ImageHeader object within the text segment, so that we can detect
when a given Image has an ImageHeader object available.
There are no methods available on ImageHeader objects, but instead the
Image itself controls access to the information. In particular, the
relocated address method either returns the relocated address
information from the ImageHeader object or from the initialized BSS
depending on the type of snapshot, so the caller need not do this work.
Also, instead of returning the raw offset to the BSS section and having
the caller turn that into an appropriate pointer, the method for
accessing the BSS segment now returns a pointer to the segment.
Bug: https://github.com/dart-lang/sdk/issues/43274
Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try
Change-Id: I15eae4ad0a088260b127f3d07da79374215b7f56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163207
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-09-22 17:14:44 +00:00
|
|
|
: data_image_(ASSERT_NOTNULL(data_image)),
|
|
|
|
instructions_image_(ASSERT_NOTNULL(instructions_image)) {}
|
2018-04-30 21:12:41 +00:00
|
|
|
|
2020-04-25 05:21:27 +00:00
|
|
|
ApiErrorPtr ImageReader::VerifyAlignment() const {
|
2018-04-30 21:12:41 +00:00
|
|
|
if (!Utils::IsAligned(data_image_, kObjectAlignment) ||
|
2019-10-22 19:02:26 +00:00
|
|
|
!Utils::IsAligned(instructions_image_, kMaxObjectAlignment)) {
|
2018-04-30 21:12:41 +00:00
|
|
|
return ApiError::New(
|
|
|
|
String::Handle(String::New("Snapshot is misaligned", Heap::kOld)),
|
|
|
|
Heap::kOld);
|
|
|
|
}
|
|
|
|
return ApiError::null();
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
uword ImageReader::GetBareInstructionsAt(uint32_t offset) const {
|
2020-10-06 07:59:33 +00:00
|
|
|
ASSERT(FLAG_use_bare_instructions);
|
|
|
|
ASSERT(Utils::IsAligned(offset, Instructions::kBarePayloadAlignment));
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
return reinterpret_cast<uword>(instructions_image_) + offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
uword ImageReader::GetBareInstructionsEnd() const {
|
2020-10-06 07:59:33 +00:00
|
|
|
ASSERT(FLAG_use_bare_instructions);
|
Reland "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
Now, when writing an AOT snapshot in bare instructions mode, only
the actual instructions in the RawInstructions payload are serialized
instead of the entire RawInstructions object.
Since there are no longer RawInstructions objects in these AOT
snapshots, we also change how Code objects are serialized. Instead
of just containing a reference to the RawInstructions object, we
serialize two pieces of information: where the instructions
payload for this Code object begins and whether there was a single
entry for the instructions payload. (To save space, the single
entry bit is serialized as the low order bit of the unchecked
offset, which was already being serialized).
While we also need the length of the instructions payload, we
approximate it for all but the last Code object by subtracting
the next Code object's payload start from this Code object's
payload start. For the last Code object, we assume it extends
to the end of the instructions image.
Changes on flutter gallery in release mode:
armv7: instructions size -2.70%, total size -1.73%
armv8: instructions size -6.04%, total size -3.63%
Fixes https://github.com/dart-lang/sdk/issues/38451.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 15:08:04 +00:00
|
|
|
Image image(instructions_image_);
|
|
|
|
return reinterpret_cast<uword>(image.object_start()) + image.object_size();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-04-25 05:21:27 +00:00
|
|
|
InstructionsPtr ImageReader::GetInstructionsAt(uint32_t offset) const {
|
2020-10-06 07:59:33 +00:00
|
|
|
ASSERT(!FLAG_precompiled_mode || !FLAG_use_bare_instructions);
|
2019-10-17 21:45:38 +00:00
|
|
|
ASSERT(Utils::IsAligned(offset, kObjectAlignment));
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2021-01-15 23:32:02 +00:00
|
|
|
ObjectPtr result = UntaggedObject::FromAddr(
|
2019-10-22 19:02:26 +00:00
|
|
|
reinterpret_cast<uword>(instructions_image_) + offset);
|
2017-11-02 00:57:42 +00:00
|
|
|
ASSERT(result->IsInstructions());
|
2021-01-15 23:32:02 +00:00
|
|
|
ASSERT(result->untag()->IsMarked());
|
2017-11-02 00:57:42 +00:00
|
|
|
|
2018-04-27 17:42:16 +00:00
|
|
|
return Instructions::RawCast(result);
|
2017-11-02 00:57:42 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 05:21:27 +00:00
|
|
|
ObjectPtr ImageReader::GetObjectAt(uint32_t offset) const {
|
2018-04-27 17:42:16 +00:00
|
|
|
ASSERT(Utils::IsAligned(offset, kObjectAlignment));
|
|
|
|
|
2020-04-25 05:21:27 +00:00
|
|
|
ObjectPtr result =
|
2021-01-15 23:32:02 +00:00
|
|
|
UntaggedObject::FromAddr(reinterpret_cast<uword>(data_image_) + offset);
|
|
|
|
ASSERT(result->untag()->IsMarked());
|
2018-04-27 17:42:16 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-11-02 00:57:42 +00:00
|
|
|
} // namespace dart
|