From fca36cae39afc1556c494a9ea08230c841cf44d6 Mon Sep 17 00:00:00 2001 From: Tess Strickland Date: Tue, 6 Oct 2020 17:10:05 +0000 Subject: [PATCH] [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 Reviewed-by: Martin Kustermann Reviewed-by: Ryan Macnak --- runtime/platform/globals.h | 162 ++++--- runtime/vm/bss_relocs.cc | 2 +- runtime/vm/class_id.h | 3 +- runtime/vm/compiler/runtime_api.cc | 22 +- runtime/vm/compiler/runtime_api.h | 14 +- .../vm/compiler/runtime_offsets_extracted.h | 48 +- runtime/vm/compiler/runtime_offsets_list.h | 1 - runtime/vm/elf.cc | 8 +- runtime/vm/elf.h | 4 +- runtime/vm/image_snapshot.cc | 412 ++++++++---------- runtime/vm/image_snapshot.h | 55 +-- runtime/vm/object.cc | 4 - runtime/vm/object.h | 40 +- runtime/vm/object_service.cc | 4 - runtime/vm/raw_object.cc | 5 - runtime/vm/raw_object.h | 35 +- runtime/vm/raw_object_snapshot.cc | 1 - runtime/vm/tagged_pointer.h | 1 - 18 files changed, 366 insertions(+), 455 deletions(-) diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h index 46ea17bb7fd..1796c339110 100644 --- a/runtime/platform/globals.h +++ b/runtime/platform/globals.h @@ -449,112 +449,136 @@ typedef simd128_value_t fpu_register_t; #define strtoll _strtoi64 #endif +// Byte sizes. +constexpr int kInt8SizeLog2 = 0; +constexpr int kInt8Size = 1 << kInt8SizeLog2; +static_assert(kInt8Size == sizeof(int8_t), "Mismatched int8 size constant"); +constexpr int kInt16SizeLog2 = 1; +constexpr int kInt16Size = 1 << kInt16SizeLog2; +static_assert(kInt16Size == sizeof(int16_t), "Mismatched int16 size constant"); +constexpr int kInt32SizeLog2 = 2; +constexpr int kInt32Size = 1 << kInt32SizeLog2; +static_assert(kInt32Size == sizeof(int32_t), "Mismatched int32 size constant"); +constexpr int kInt64SizeLog2 = 3; +constexpr int kInt64Size = 1 << kInt64SizeLog2; +static_assert(kInt64Size == sizeof(int64_t), "Mismatched int64 size constant"); + +constexpr int kDoubleSize = sizeof(double); +constexpr int kFloatSize = sizeof(float); +constexpr int kQuadSize = 4 * kFloatSize; +constexpr int kSimd128Size = sizeof(simd128_value_t); + +// Bit sizes. +constexpr int kBitsPerByteLog2 = 3; +constexpr int kBitsPerByte = 1 << kBitsPerByteLog2; +constexpr int kBitsPerInt8 = kInt8Size * kBitsPerByte; +constexpr int kBitsPerInt16 = kInt16Size * kBitsPerByte; +constexpr int kBitsPerInt32 = kInt32Size * kBitsPerByte; +constexpr int kBitsPerInt64 = kInt64Size * kBitsPerByte; + // The following macro works on both 32 and 64-bit platforms. // Usage: instead of writing 0x1234567890123456ULL // write DART_2PART_UINT64_C(0x12345678,90123456); #define DART_2PART_UINT64_C(a, b) \ - (((static_cast(a) << 32) + 0x##b##u)) + (((static_cast(a) << kBitsPerInt32) + 0x##b##u)) // Integer constants. -const int8_t kMinInt8 = 0x80; -const int8_t kMaxInt8 = 0x7F; -const uint8_t kMaxUint8 = 0xFF; -const int16_t kMinInt16 = 0x8000; -const int16_t kMaxInt16 = 0x7FFF; -const uint16_t kMaxUint16 = 0xFFFF; -const int32_t kMinInt32 = 0x80000000; -const int32_t kMaxInt32 = 0x7FFFFFFF; -const uint32_t kMaxUint32 = 0xFFFFFFFF; -const int64_t kMinInt64 = DART_INT64_C(0x8000000000000000); -const int64_t kMaxInt64 = DART_INT64_C(0x7FFFFFFFFFFFFFFF); -const int kMinInt = INT_MIN; -const int kMaxInt = INT_MAX; -const int64_t kMinInt64RepresentableAsDouble = kMinInt64; -const int64_t kMaxInt64RepresentableAsDouble = DART_INT64_C(0x7FFFFFFFFFFFFC00); -const uint64_t kMaxUint64 = DART_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF); -const int64_t kSignBitDouble = DART_INT64_C(0x8000000000000000); +constexpr int8_t kMinInt8 = 0x80; +constexpr int8_t kMaxInt8 = 0x7F; +constexpr uint8_t kMaxUint8 = 0xFF; +constexpr int16_t kMinInt16 = 0x8000; +constexpr int16_t kMaxInt16 = 0x7FFF; +constexpr uint16_t kMaxUint16 = 0xFFFF; +constexpr int32_t kMinInt32 = 0x80000000; +constexpr int32_t kMaxInt32 = 0x7FFFFFFF; +constexpr uint32_t kMaxUint32 = 0xFFFFFFFF; +constexpr int64_t kMinInt64 = DART_INT64_C(0x8000000000000000); +constexpr int64_t kMaxInt64 = DART_INT64_C(0x7FFFFFFFFFFFFFFF); +constexpr uint64_t kMaxUint64 = DART_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF); + +constexpr int kMinInt = INT_MIN; +constexpr int kMaxInt = INT_MAX; +constexpr int kMaxUint = UINT_MAX; + +constexpr int64_t kMinInt64RepresentableAsDouble = kMinInt64; +constexpr int64_t kMaxInt64RepresentableAsDouble = + DART_INT64_C(0x7FFFFFFFFFFFFC00); +constexpr int64_t kSignBitDouble = DART_INT64_C(0x8000000000000000); // Types for native machine words. Guaranteed to be able to hold pointers and // integers. typedef intptr_t word; typedef uintptr_t uword; +// Byte sizes for native machine words. +#ifdef ARCH_IS_32_BIT +constexpr int kWordSizeLog2 = kInt32SizeLog2; +#else +constexpr int kWordSizeLog2 = kInt64SizeLog2; +#endif +constexpr int kWordSize = 1 << kWordSizeLog2; +static_assert(kWordSize == sizeof(word), "Mismatched word size constant"); + +// Bit sizes for native machine words. +constexpr int kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2; +constexpr int kBitsPerWord = 1 << kBitsPerWordLog2; + +// Integer constants for native machine words. +constexpr word kWordMin = static_cast(1) << (kBitsPerWord - 1); +constexpr word kWordMax = (static_cast(1) << (kBitsPerWord - 1)) - 1; +constexpr uword kUwordMax = static_cast(-1); + // Size of a class id assigned to concrete, abstract and top-level classes. // // We use a signed integer type here to make it comparable with intptr_t. typedef int32_t classid_t; -// Byte sizes. -const int kWordSize = sizeof(word); -const int kDoubleSize = sizeof(double); // NOLINT -const int kFloatSize = sizeof(float); // NOLINT -const int kQuadSize = 4 * kFloatSize; -const int kSimd128Size = sizeof(simd128_value_t); // NOLINT -const int kInt64Size = sizeof(int64_t); // NOLINT -const int kInt32Size = sizeof(int32_t); // NOLINT -const int kInt16Size = sizeof(int16_t); // NOLINT -#ifdef ARCH_IS_32_BIT -const int kWordSizeLog2 = 2; -const uword kUwordMax = kMaxUint32; -#else -const int kWordSizeLog2 = 3; -const uword kUwordMax = kMaxUint64; -#endif - -// Bit sizes. -const int kBitsPerByte = 8; -const int kBitsPerByteLog2 = 3; -const int kBitsPerInt32 = kInt32Size * kBitsPerByte; -const int kBitsPerInt64 = kInt64Size * kBitsPerByte; -const int kBitsPerWord = kWordSize * kBitsPerByte; -const int kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2; - // System-wide named constants. -const intptr_t KB = 1024; -const intptr_t KBLog2 = 10; -const intptr_t MB = KB * KB; -const intptr_t MBLog2 = KBLog2 + KBLog2; -const intptr_t GB = MB * KB; -const intptr_t GBLog2 = MBLog2 + KBLog2; +constexpr intptr_t KBLog2 = 10; +constexpr intptr_t KB = 1 << KBLog2; +constexpr intptr_t MBLog2 = KBLog2 + KBLog2; +constexpr intptr_t MB = 1 << MBLog2; +constexpr intptr_t GBLog2 = MBLog2 + KBLog2; +constexpr intptr_t GB = 1 << GBLog2; -const intptr_t KBInWords = KB >> kWordSizeLog2; -const intptr_t KBInWordsLog2 = KBLog2 - kWordSizeLog2; -const intptr_t MBInWords = KB * KBInWords; -const intptr_t MBInWordsLog2 = KBLog2 + KBInWordsLog2; -const intptr_t GBInWords = MB * KBInWords; -const intptr_t GBInWordsLog2 = MBLog2 + KBInWordsLog2; +constexpr intptr_t KBInWordsLog2 = KBLog2 - kWordSizeLog2; +constexpr intptr_t KBInWords = 1 << KBInWordsLog2; +constexpr intptr_t MBInWordsLog2 = KBLog2 + KBInWordsLog2; +constexpr intptr_t MBInWords = 1 << MBInWordsLog2; +constexpr intptr_t GBInWordsLog2 = MBLog2 + KBInWordsLog2; +constexpr intptr_t GBInWords = 1 << GBInWordsLog2; // Helpers to round memory sizes to human readable values. -inline intptr_t RoundWordsToKB(intptr_t size_in_words) { +constexpr intptr_t RoundWordsToKB(intptr_t size_in_words) { return (size_in_words + (KBInWords >> 1)) >> KBInWordsLog2; } -inline intptr_t RoundWordsToMB(intptr_t size_in_words) { +constexpr intptr_t RoundWordsToMB(intptr_t size_in_words) { return (size_in_words + (MBInWords >> 1)) >> MBInWordsLog2; } -inline intptr_t RoundWordsToGB(intptr_t size_in_words) { +constexpr intptr_t RoundWordsToGB(intptr_t size_in_words) { return (size_in_words + (GBInWords >> 1)) >> GBInWordsLog2; } -const intptr_t kIntptrOne = 1; -const intptr_t kIntptrMin = (kIntptrOne << (kBitsPerWord - 1)); -const intptr_t kIntptrMax = ~kIntptrMin; +constexpr intptr_t kIntptrOne = 1; +constexpr intptr_t kIntptrMin = (kIntptrOne << (kBitsPerWord - 1)); +constexpr intptr_t kIntptrMax = ~kIntptrMin; // Time constants. -const int kMillisecondsPerSecond = 1000; -const int kMicrosecondsPerMillisecond = 1000; -const int kMicrosecondsPerSecond = +constexpr int kMillisecondsPerSecond = 1000; +constexpr int kMicrosecondsPerMillisecond = 1000; +constexpr int kMicrosecondsPerSecond = (kMicrosecondsPerMillisecond * kMillisecondsPerSecond); -const int kNanosecondsPerMicrosecond = 1000; -const int kNanosecondsPerMillisecond = +constexpr int kNanosecondsPerMicrosecond = 1000; +constexpr int kNanosecondsPerMillisecond = (kNanosecondsPerMicrosecond * kMicrosecondsPerMillisecond); -const int kNanosecondsPerSecond = +constexpr int kNanosecondsPerSecond = (kNanosecondsPerMicrosecond * kMicrosecondsPerSecond); // Helpers to scale micro second times to human understandable values. -inline double MicrosecondsToSeconds(int64_t micros) { +constexpr double MicrosecondsToSeconds(int64_t micros) { return static_cast(micros) / kMicrosecondsPerSecond; } -inline double MicrosecondsToMilliseconds(int64_t micros) { +constexpr double MicrosecondsToMilliseconds(int64_t micros) { return static_cast(micros) / kMicrosecondsPerMillisecond; } diff --git a/runtime/vm/bss_relocs.cc b/runtime/vm/bss_relocs.cc index 2cb3157a560..867d82a6112 100644 --- a/runtime/vm/bss_relocs.cc +++ b/runtime/vm/bss_relocs.cc @@ -32,7 +32,7 @@ void BSS::Initialize(Thread* current, uword* bss_start, bool vm) { current->isolate_group()->source()->snapshot_instructions); uword dso_base; // Needed for assembly snapshots. For ELF snapshots, we set up the relocated - // address information directly in the text segment ImageHeader. + // address information directly in the text segment InstructionsSection. if (NativeSymbolResolver::LookupSharedObject(instructions, &dso_base)) { InitializeBSSEntry(Relocation::InstructionsRelocatedAddress, instructions - dso_base, bss_start); diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h index 97f932542d7..0664cbb4d9f 100644 --- a/runtime/vm/class_id.h +++ b/runtime/vm/class_id.h @@ -91,8 +91,7 @@ typedef uint16_t ClassIdTagType; V(FutureOr) \ V(UserTag) \ V(TransferableTypedData) \ - V(WeakSerializationReference) \ - V(ImageHeader) + V(WeakSerializationReference) #define CLASS_LIST_ARRAYS(V) \ V(Array) \ diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc index 06bf60ce9b8..d3627d0718d 100644 --- a/runtime/vm/compiler/runtime_api.cc +++ b/runtime/vm/compiler/runtime_api.cc @@ -664,19 +664,19 @@ const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize; // For InstructionsSections and Instructions, we define these by hand, because // they depend on flags or #defines. +// Used for InstructionsSection and Instructions methods, since we don't +// serialize Instructions objects in bare instructions mode, just payloads. +DART_FORCE_INLINE static bool BareInstructionsPayloads() { + return FLAG_precompiled_mode && FLAG_use_bare_instructions; +} + word InstructionsSection::HeaderSize() { // We only create InstructionsSections in precompiled mode. ASSERT(FLAG_precompiled_mode); - return Utils::RoundUp(UnalignedHeaderSize(), + return Utils::RoundUp(InstructionsSection::UnalignedHeaderSize(), Instructions::kBarePayloadAlignment); } -// Used for Instructions methods, since we don't serialize Instructions objects -// in bare instructions mode, just payloads. -DART_FORCE_INLINE static bool BareInstructionsPayloads() { - return FLAG_precompiled_mode && FLAG_use_bare_instructions; -} - word Instructions::HeaderSize() { return BareInstructionsPayloads() ? 0 @@ -842,10 +842,6 @@ word ForwardingCorpse::FakeInstance::InstanceSize() { return 0; } -word ImageHeader::InstanceSize() { - return RoundedAllocationSize(UnroundedSize()); -} - word Instance::NextFieldOffset() { return TranslateOffsetInWords(dart::Instance::NextFieldOffset()); } @@ -854,10 +850,6 @@ word Pointer::NextFieldOffset() { return TranslateOffsetInWords(dart::Pointer::NextFieldOffset()); } -word ImageHeader::NextFieldOffset() { - return -kWordSize; -} - word WeakSerializationReference::NextFieldOffset() { return -kWordSize; } diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h index e4468ab61d6..ac5ff81185f 100644 --- a/runtime/vm/compiler/runtime_api.h +++ b/runtime/vm/compiler/runtime_api.h @@ -68,9 +68,16 @@ class InvalidClass {}; extern InvalidClass kWordSize; extern InvalidClass kWordSizeLog2; extern InvalidClass kBitsPerWord; +extern InvalidClass kBitsPerWordLog2; +extern InvalidClass kWordMin; +extern InvalidClass kWordMax; +extern InvalidClass kUWordMax; extern InvalidClass kNewObjectAlignmentOffset; extern InvalidClass kOldObjectAlignmentOffset; extern InvalidClass kNewObjectBitPosition; +extern InvalidClass kOldPageSize; +extern InvalidClass kOldPageSizeInWords; +extern InvalidClass kOldPageMask; extern InvalidClass kObjectAlignment; extern InvalidClass kObjectAlignmentLog2; extern InvalidClass kObjectAlignmentMask; @@ -1191,13 +1198,6 @@ class Code : public AllStatic { static word NextFieldOffset(); }; -class ImageHeader : public AllStatic { - public: - static word UnroundedSize(); - static word InstanceSize(); - static word NextFieldOffset(); -}; - class WeakSerializationReference : public AllStatic { public: static word InstanceSize(); diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index 349f146cd3c..4a6d9e00b1f 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -456,12 +456,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 16; static constexpr dart::compiler::target::word ICData_InstanceSize = 32; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 20; static constexpr dart::compiler::target::word Instance_InstanceSize = 4; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 8; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 8; + InstructionsSection_UnalignedHeaderSize = 20; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -968,12 +967,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word ICData_InstanceSize = 56; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 40; static constexpr dart::compiler::target::word Instance_InstanceSize = 8; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 16; + InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -1471,12 +1469,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 16; static constexpr dart::compiler::target::word ICData_InstanceSize = 32; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 20; static constexpr dart::compiler::target::word Instance_InstanceSize = 4; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 8; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 8; + InstructionsSection_UnalignedHeaderSize = 20; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -1984,12 +1981,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word ICData_InstanceSize = 56; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 40; static constexpr dart::compiler::target::word Instance_InstanceSize = 8; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 16; + InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -2486,12 +2482,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 16; static constexpr dart::compiler::target::word ICData_InstanceSize = 32; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 20; static constexpr dart::compiler::target::word Instance_InstanceSize = 4; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 8; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 8; + InstructionsSection_UnalignedHeaderSize = 20; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -2992,12 +2987,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word ICData_InstanceSize = 56; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 40; static constexpr dart::compiler::target::word Instance_InstanceSize = 8; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 16; + InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -3489,12 +3483,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 16; static constexpr dart::compiler::target::word ICData_InstanceSize = 32; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 20; static constexpr dart::compiler::target::word Instance_InstanceSize = 4; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 8; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 8; + InstructionsSection_UnalignedHeaderSize = 20; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 4; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -3996,12 +3989,11 @@ static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word ICData_InstanceSize = 56; -static constexpr dart::compiler::target::word ImageHeader_UnroundedSize = 40; static constexpr dart::compiler::target::word Instance_InstanceSize = 8; static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - InstructionsSection_UnalignedHeaderSize = 16; + InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word Integer_InstanceSize = 8; static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize = @@ -4543,13 +4535,11 @@ static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 8; static constexpr dart::compiler::target::word AOT_GrowableObjectArray_InstanceSize = 16; static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 24; -static constexpr dart::compiler::target::word AOT_ImageHeader_UnroundedSize = - 20; static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4; static constexpr dart::compiler::target::word AOT_Instructions_UnalignedHeaderSize = 8; static constexpr dart::compiler::target::word - AOT_InstructionsSection_UnalignedHeaderSize = 8; + AOT_InstructionsSection_UnalignedHeaderSize = 20; static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4; static constexpr dart::compiler::target::word @@ -5105,13 +5095,11 @@ static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word AOT_GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_ImageHeader_UnroundedSize = - 40; static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8; static constexpr dart::compiler::target::word AOT_Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - AOT_InstructionsSection_UnalignedHeaderSize = 16; + AOT_InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8; static constexpr dart::compiler::target::word @@ -5671,13 +5659,11 @@ static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word AOT_GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_ImageHeader_UnroundedSize = - 40; static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8; static constexpr dart::compiler::target::word AOT_Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - AOT_InstructionsSection_UnalignedHeaderSize = 16; + AOT_InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8; static constexpr dart::compiler::target::word @@ -6225,13 +6211,11 @@ static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 8; static constexpr dart::compiler::target::word AOT_GrowableObjectArray_InstanceSize = 16; static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 24; -static constexpr dart::compiler::target::word AOT_ImageHeader_UnroundedSize = - 20; static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4; static constexpr dart::compiler::target::word AOT_Instructions_UnalignedHeaderSize = 8; static constexpr dart::compiler::target::word - AOT_InstructionsSection_UnalignedHeaderSize = 8; + AOT_InstructionsSection_UnalignedHeaderSize = 20; static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4; static constexpr dart::compiler::target::word @@ -6780,13 +6764,11 @@ static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word AOT_GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_ImageHeader_UnroundedSize = - 40; static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8; static constexpr dart::compiler::target::word AOT_Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - AOT_InstructionsSection_UnalignedHeaderSize = 16; + AOT_InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8; static constexpr dart::compiler::target::word @@ -7339,13 +7321,11 @@ static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16; static constexpr dart::compiler::target::word AOT_GrowableObjectArray_InstanceSize = 32; static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48; -static constexpr dart::compiler::target::word AOT_ImageHeader_UnroundedSize = - 40; static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8; static constexpr dart::compiler::target::word AOT_Instructions_UnalignedHeaderSize = 12; static constexpr dart::compiler::target::word - AOT_InstructionsSection_UnalignedHeaderSize = 16; + AOT_InstructionsSection_UnalignedHeaderSize = 40; static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24; static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8; static constexpr dart::compiler::target::word diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h index fca139ca40b..76eb49fb5d2 100644 --- a/runtime/vm/compiler/runtime_offsets_list.h +++ b/runtime/vm/compiler/runtime_offsets_list.h @@ -315,7 +315,6 @@ SIZEOF(FutureOr, InstanceSize, FutureOrLayout) \ SIZEOF(GrowableObjectArray, InstanceSize, GrowableObjectArrayLayout) \ SIZEOF(ICData, InstanceSize, ICDataLayout) \ - SIZEOF(ImageHeader, UnroundedSize, ImageHeaderLayout) \ SIZEOF(Instance, InstanceSize, InstanceLayout) \ SIZEOF(Instructions, UnalignedHeaderSize, InstructionsLayout) \ SIZEOF(InstructionsSection, UnalignedHeaderSize, InstructionsSectionLayout) \ diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc index 30c25bf065e..7ec28906a9e 100644 --- a/runtime/vm/elf.cc +++ b/runtime/vm/elf.cc @@ -852,7 +852,7 @@ Elf::Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf) new (zone_) ProgramTableLoadSegment(zone_, kProgramTableSegmentSize); segments_.Add(start_segment); // We allocate an initial build ID of all zeroes, since we need the build ID - // memory offset during ImageHeader creation (see BlobImageWriter::WriteText). + // memory offset for the InstructionsSection (see BlobImageWriter::WriteText). // We replace it with the real build ID during finalization. (We add this // prior to BSS because we make the BuildID section writable also, so they are // placed in the same segment before any non-writable ones, and if we add it @@ -1338,11 +1338,9 @@ static uint32_t HashBitsContainer(const BitsContainer* bits) { return FinalizeHash(hash, 32); } -uword Elf::BuildIdStart(intptr_t* size) { - ASSERT(size != nullptr); +uword Elf::BuildIdStart() const { ASSERT(build_id_ != nullptr); - *size = kBuildIdDescriptionLength; - return build_id_->memory_offset() + kBuildIdDescriptionOffset; + return build_id_->memory_offset(); } Section* Elf::GenerateBuildId() { diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h index 37b2fc89c48..6d3760b87b6 100644 --- a/runtime/vm/elf.h +++ b/runtime/vm/elf.h @@ -41,7 +41,7 @@ class Elf : public ZoneAllocated { Dwarf* dwarf() { return dwarf_; } uword BssStart(bool vm) const; - uword BuildIdStart(intptr_t* size); + uword BuildIdStart() const; // What the next memory offset for an appropriately aligned section would be. // @@ -123,7 +123,7 @@ class Elf : public ZoneAllocated { SymbolTable* symtab_ = nullptr; // We always create a GNU build ID for all Elf files. In order to create - // the appropriate offset to it in an ImageHeader object, we create an + // the appropriate offset to it in an InstructionsSection object, we create an // initial build ID section as a placeholder and then replace that section // during finalization once we have the information to calculate the real one. Section* build_id_; diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc index ba8217521a6..2035a87702a 100644 --- a/runtime/vm/image_snapshot.cc +++ b/runtime/vm/image_snapshot.cc @@ -6,6 +6,7 @@ #include "include/dart_api.h" #include "platform/assert.h" +#include "platform/elf.h" #include "vm/bss_relocs.h" #include "vm/class_id.h" #include "vm/compiler/runtime_api.h" @@ -41,14 +42,24 @@ DEFINE_FLAG(charp, "Print sizes of all instruction objects to the given file"); #endif -const ImageHeaderLayout* Image::ExtraInfo(const uword raw_memory, - const uword size) { +const InstructionsSectionLayout* Image::ExtraInfo(const uword raw_memory, + const uword size) { #if defined(DART_PRECOMPILED_RUNTIME) - auto const raw_value = FieldValue(raw_memory, HeaderField::ImageHeaderOffset); - if (raw_value != kNoImageHeader) { + auto const raw_value = + FieldValue(raw_memory, HeaderField::InstructionsSectionOffset); + if (raw_value != kNoInstructionsSection) { ASSERT(raw_value >= kHeaderSize); - ASSERT(raw_value <= size - ImageHeader::InstanceSize()); - return reinterpret_cast(raw_memory + raw_value); + ASSERT(raw_value <= size - InstructionsSection::HeaderSize()); + auto const layout = reinterpret_cast( + 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; } #endif return nullptr; @@ -87,8 +98,9 @@ const uint8_t* Image::build_id() const { #if defined(DART_PRECOMPILED_RUNTIME) ASSERT(extra_info_ != nullptr); if (extra_info_->build_id_offset_ != kNoBuildId) { - return reinterpret_cast(raw_memory_ + - extra_info_->build_id_offset_); + auto const note = reinterpret_cast( + raw_memory_ + extra_info_->build_id_offset_); + return note->data + note->name_size; } #endif return nullptr; @@ -97,10 +109,13 @@ const uint8_t* Image::build_id() const { intptr_t Image::build_id_length() const { #if defined(DART_PRECOMPILED_RUNTIME) ASSERT(extra_info_ != nullptr); - return extra_info_->build_id_length_; -#else - return 0; + if (extra_info_->build_id_offset_ != kNoBuildId) { + auto const note = reinterpret_cast( + raw_memory_ + extra_info_->build_id_offset_); + return note->description_size; + } #endif + return 0; } bool Image::compiled_to_elf() const { @@ -164,7 +179,6 @@ ImageWriter::ImageWriter(Thread* t) objects_(), instructions_(), image_type_(TagObjectTypeAsReadOnly(t->zone(), "Image")), - image_header_type_(TagObjectTypeAsReadOnly(t->zone(), "ImageHeader")), instructions_section_type_( TagObjectTypeAsReadOnly(t->zone(), "InstructionsSection")), instructions_type_(TagObjectTypeAsReadOnly(t->zone(), "Instructions")), @@ -423,7 +437,7 @@ void ImageWriter::Write(NonStreamingWriteStream* clustered_stream, bool vm) { } // Needs to happen before WriteText, as we add information about the - // BSSsection in the text section as an initial ImageHeader object. + // BSSsection in the text section as an initial InstructionsSection object. WriteBss(vm); offset_space_ = vm ? V8SnapshotProfileWriter::kVmText @@ -449,7 +463,7 @@ void ImageWriter::WriteROData(NonStreamingWriteStream* stream, bool vm) { intptr_t section_start = stream->Position(); stream->WriteWord(next_data_offset_); // Data length. - stream->WriteWord(0); // No ImageHeader object in data sections. + stream->WriteWord(Image::kNoInstructionsSection); // Zero values for the rest of the Image object header bytes. stream->Align(Image::kHeaderSize); ASSERT(stream->Position() - section_start == Image::kHeaderSize); @@ -538,6 +552,14 @@ uword ImageWriter::GetMarkedTags(const Object& obj) { } #if defined(DART_PRECOMPILER) + +// Indices are log2(size in bytes). +static constexpr const char* kSizeDirectives[] = {".byte", ".2byte", ".long", + ".quad"}; + +static constexpr const char* kWordDirective = + kSizeDirectives[compiler::target::kWordSizeLog2]; + class DwarfAssemblyStream : public DwarfWriteStream { public: explicit DwarfAssemblyStream(BaseWriteStream* stream) @@ -547,11 +569,19 @@ class DwarfAssemblyStream : public DwarfWriteStream { void uleb128(uintptr_t value) { stream_->Printf(".uleb128 %" Pd "\n", value); } - void u1(uint8_t value) { stream_->Printf(".byte %u\n", value); } - void u2(uint16_t value) { stream_->Printf(".2byte %u\n", value); } - void u4(uint32_t value) { stream_->Printf(".4byte %" Pu32 "\n", value); } - void u8(uint64_t value) { stream_->Printf(".8byte %" Pu64 "\n", value); } - void string(const char* cstr) { // NOLINT + 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 stream_->Printf(".string \"%s\"\n", cstr); // NOLINT } // Uses labels, so doesn't output to start or return a useful fixup position. @@ -559,7 +589,7 @@ class DwarfAssemblyStream : public DwarfWriteStream { // Assignment to temp works around buggy Mac assembler. stream_->Printf("L%s_size = .L%s_end - .L%s_start\n", prefix, prefix, prefix); - stream_->Printf(".4byte L%s_size\n", prefix); + stream_->Printf("%s L%s_size\n", kSizeDirectives[kInt32SizeLog2], prefix); stream_->Printf(".L%s_start:\n", prefix); return -1; } @@ -593,7 +623,8 @@ class DwarfAssemblyStream : public DwarfWriteStream { // Assignment to temp works around buggy Mac assembler. stream_->Printf("Ltemp%" Pd " = .Lfunc%" Pd " - %s\n", temp_, index, kDebugInfoLabel); - stream_->Printf(".4byte Ltemp%" Pd "\n", temp_); + stream_->Printf("%s Ltemp%" Pd "\n", kSizeDirectives[kInt32SizeLog2], + temp_); temp_++; } @@ -634,17 +665,11 @@ class DwarfAssemblyStream : public DwarfWriteStream { private: static constexpr const char* kDebugInfoLabel = ".Ldebug_info"; -#if defined(TARGET_ARCH_IS_32_BIT) -#define FORM_ADDR ".4byte" -#elif defined(TARGET_ARCH_IS_64_BIT) -#define FORM_ADDR ".8byte" -#endif - void PrintNamedAddress(const char* name) { - stream_->Printf(FORM_ADDR " %s\n", name); + stream_->Printf("%s %s\n", kWordDirective, name); } void PrintNamedAddressWithOffset(const char* name, intptr_t offset) { - stream_->Printf(FORM_ADDR " %s + %" Pd "\n", name, offset); + stream_->Printf("%s %s + %" Pd "\n", kWordDirective, name, offset); } #undef FORM_ADDR @@ -654,10 +679,8 @@ class DwarfAssemblyStream : public DwarfWriteStream { DISALLOW_COPY_AND_ASSIGN(DwarfAssemblyStream); }; -#endif static inline Dwarf* AddDwarfIfUnstripped(Zone* zone, bool strip, Elf* elf) { -#if defined(DART_PRECOMPILER) if (!strip) { if (elf != nullptr) { // Reuse the existing DWARF object. @@ -666,7 +689,6 @@ static inline Dwarf* AddDwarfIfUnstripped(Zone* zone, bool strip, Elf* elf) { } return new (zone) Dwarf(zone); } -#endif return nullptr; } @@ -680,7 +702,6 @@ AssemblyImageWriter::AssemblyImageWriter(Thread* thread, debug_elf_(debug_elf) {} void AssemblyImageWriter::Finalize() { -#if defined(DART_PRECOMPILER) if (assembly_dwarf_ != nullptr) { DwarfAssemblyStream dwarf_stream(assembly_stream_); dwarf_stream.AbbreviationsPrologue(); @@ -693,7 +714,6 @@ void AssemblyImageWriter::Finalize() { if (debug_elf_ != nullptr) { debug_elf_->Finalize(); } -#endif } #if !defined(DART_PRECOMPILED_RUNTIME) @@ -751,14 +771,11 @@ const char* SnapshotTextObjectNamer::SnapshotNameFor( return SnapshotNameFor(index, *data.code_); } -#if defined(DART_PRECOMPILER) static const char* const kVmSnapshotBssAsmSymbol = "_kDartVmSnapshotBss"; static const char* const kIsolateSnapshotBssAsmSymbol = "_kDartIsolateSnapshotBss"; -#endif void AssemblyImageWriter::WriteBss(bool vm) { -#if defined(DART_PRECOMPILER) auto const bss_symbol = vm ? kVmSnapshotBssAsmSymbol : kIsolateSnapshotBssAsmSymbol; assembly_stream_->WriteString(".bss\n"); @@ -770,15 +787,11 @@ void AssemblyImageWriter::WriteBss(bool vm) { for (intptr_t i = 0; i < entry_count; i++) { WriteWordLiteralText(0); } -#endif } void AssemblyImageWriter::WriteROData(NonStreamingWriteStream* clustered_stream, bool vm) { ImageWriter::WriteROData(clustered_stream, vm); -#if defined(DART_PRECOMPILED_RUNTIME) - UNREACHABLE(); -#else #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ defined(TARGET_OS_FUCHSIA) assembly_stream_->WriteString(".section .rodata\n"); @@ -796,24 +809,16 @@ void AssemblyImageWriter::WriteROData(NonStreamingWriteStream* clustered_stream, const uword buffer = reinterpret_cast(clustered_stream->buffer()); const intptr_t length = clustered_stream->bytes_written(); WriteByteSequence(buffer, buffer + length); -#if defined(DART_PRECOMPILER) if (debug_elf_ != nullptr) { // Add a NoBits section for the ROData as well. debug_elf_->AddROData(data_symbol, clustered_stream->buffer(), length); } -#endif // defined(DART_PRECOMPILER) -#endif // !defined(DART_PRECOMPILED_RUNTIME) } void AssemblyImageWriter::WriteText(bool vm) { -#if defined(DART_PRECOMPILED_RUNTIME) - UNREACHABLE(); -#else + ASSERT(FLAG_precompiled_mode); Zone* zone = Thread::Current()->zone(); - const bool bare_instruction_payloads = - FLAG_precompiled_mode && FLAG_use_bare_instructions; - const char* instructions_symbol = vm ? kVmSnapshotInstructionsAsmSymbol : kIsolateSnapshotInstructionsAsmSymbol; assembly_stream_->WriteString(".text\n"); @@ -824,7 +829,6 @@ void AssemblyImageWriter::WriteText(bool vm) { Align(ImageWriter::kTextAlignment); assembly_stream_->Printf("%s:\n", instructions_symbol); -#if defined(DART_PRECOMPILER) auto const bss_symbol = vm ? kVmSnapshotBssAsmSymbol : kIsolateSnapshotBssAsmSymbol; intptr_t debug_segment_base = 0; @@ -832,123 +836,95 @@ void AssemblyImageWriter::WriteText(bool vm) { debug_segment_base = debug_elf_->NextMemoryOffset(ImageWriter::kTextAlignment); } -#endif 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 += WriteWordLiteralText(image_size); - if (FLAG_precompiled_mode) { - // Output the offset to the ImageHeader object from the start of the image. - text_offset += WriteWordLiteralText(Image::kHeaderSize); - } else { - text_offset += WriteWordLiteralText(Image::kNoImageHeader); - } + // Output the offset to the InstructionsSection object from the Image start. + text_offset += WriteWordLiteralText(Image::kHeaderSize); // 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) - if (FLAG_precompiled_mode) { - if (profile_writer_ != nullptr) { - profile_writer_->SetObjectTypeAndName(parent_id, image_type_, - instructions_symbol); - // Assign post-instruction padding to the Image, unless we're writing bare - // instruction payloads, in which case we'll assign it to the - // InstructionsSection object. - const intptr_t padding = - bare_instruction_payloads ? 0 : image_size - next_text_offset_; - profile_writer_->AttributeBytesTo(parent_id, - Image::kHeaderSize + padding); - profile_writer_->AddRoot(parent_id); - } + 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); + } - // Write the ImageHeader object, starting with the header. - const intptr_t image_header_size = - compiler::target::ImageHeader::InstanceSize(); - if (profile_writer_ != nullptr) { - const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset); - profile_writer_->SetObjectTypeAndName(id, image_header_type_, - instructions_symbol); - profile_writer_->AttributeBytesTo(id, image_header_size); - const intptr_t element_offset = id.second - parent_id.second; - profile_writer_->AttributeReferenceTo( - parent_id, - {id, V8SnapshotProfileWriter::Reference::kElement, element_offset}); - } - text_offset += - WriteWordLiteralText(GetMarkedTags(kImageHeaderCid, image_header_size)); + 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 = + FLAG_use_bare_instructions + ? next_text_offset_ - text_offset - section_header_length + : 0; + const intptr_t section_size = + compiler::target::InstructionsSection::InstanceSize( + section_payload_length); - // An ImageHeader has four fields: - // 1) The BSS offset from this section. - assembly_stream_->Printf("%s %s - %s\n", kLiteralPrefix, bss_symbol, - instructions_symbol); - text_offset += compiler::target::kWordSize; - // 2) The relocated address of the instructions. - // - // For assembly snapshots, we can't generate assembly to get the absolute - // address of the text section, as using the section symbol gives us a - // relative offset from the section start, which is 0. Instead, depend on - // the BSS initialization to retrieve this for us at runtime. As a side - // effect, this field also doubles as a way to detect whether we compiled to - // assembly or directly to ELF. - text_offset += WriteWordLiteralText(Image::kNoRelocatedAddress); - // TODO(dartbug.com/43274): Change once we generate consistent build IDs - // between assembly snapshots and their debugging information. - // 3) The GNU build ID offset from this section. - text_offset += WriteWordLiteralText(Image::kNoBuildId); - // 4) The GNU build ID length. - text_offset += WriteWordLiteralText(0); - text_offset += - Align(compiler::target::ObjectAlignment::kObjectAlignment, text_offset); - - ASSERT_EQUAL(text_offset, Image::kHeaderSize + image_header_size); - - if (bare_instruction_payloads) { - if (profile_writer_ != nullptr) { - const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset); - profile_writer_->SetObjectTypeAndName(id, instructions_section_type_, - instructions_symbol); - const intptr_t padding = image_size - next_text_offset_; - profile_writer_->AttributeBytesTo( - id, compiler::target::InstructionsSection::HeaderSize() + padding); - const intptr_t element_offset = id.second - parent_id.second; - profile_writer_->AttributeReferenceTo( - parent_id, - {id, V8SnapshotProfileWriter::Reference::kElement, element_offset}); - // Later objects will have the InstructionsSection as a parent. - parent_id = id; - } - const intptr_t section_size = image_size - text_offset; - // Calculated using next_text_offset_, which doesn't include post-payload - // padding to object alignment. - const intptr_t instructions_length = - next_text_offset_ - text_offset - - compiler::target::InstructionsSection::HeaderSize(); - // Add the RawInstructionsSection header. - text_offset += WriteWordLiteralText( - GetMarkedTags(kInstructionsSectionCid, section_size)); - text_offset += WriteWordLiteralText(instructions_length); - text_offset += Align( - compiler::target::Instructions::kBarePayloadAlignment, text_offset); + if (profile_writer_ != nullptr) { + const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset); + profile_writer_->SetObjectTypeAndName(id, instructions_section_type_, + instructions_symbol); + profile_writer_->AttributeBytesTo(id, + section_size - section_payload_length); + const intptr_t element_offset = id.second - parent_id.second; + profile_writer_->AttributeReferenceTo( + parent_id, + {id, V8SnapshotProfileWriter::Reference::kElement, element_offset}); + // Later objects will have the InstructionsSection as a parent if in + // bare instructions mode, otherwise the image. + if (FLAG_use_bare_instructions) { + parent_id = id; } } -#endif + + // Add the RawInstructionsSection header. + text_offset += WriteWordLiteralText( + GetMarkedTags(kInstructionsSectionCid, section_size)); + // An InstructionsSection has five fields: + // 1) The length of the payload. + text_offset += WriteWordLiteralText(section_payload_length); + // 2) The BSS offset from this section. + assembly_stream_->Printf("%s %s - %s\n", kWordDirective, bss_symbol, + instructions_symbol); + text_offset += compiler::target::kWordSize; + // 3) The relocated address of the instructions. + // + // For assembly snapshots, we can't generate assembly to get the absolute + // address of the text section, as using the section symbol gives us a + // relative offset from the section start, which is 0. Instead, depend on + // the BSS initialization to retrieve this for us at runtime. As a side + // effect, this field also doubles as a way to detect whether we compiled to + // assembly or directly to ELF. + text_offset += WriteWordLiteralText(Image::kNoRelocatedAddress); + // 4) The GNU build ID note offset from this section. + // + // TODO(dartbug.com/43274): Change once we generate consistent build IDs + // between assembly snapshots and their debugging information. + text_offset += WriteWordLiteralText(Image::kNoBuildId); + + const intptr_t section_contents_alignment = + FLAG_use_bare_instructions + ? compiler::target::Instructions::kBarePayloadAlignment + : compiler::target::ObjectAlignment::kObjectAlignment; + text_offset += Align(section_contents_alignment, text_offset); FrameUnwindPrologue(); -#if defined(DART_PRECOMPILER) PcDescriptors& descriptors = PcDescriptors::Handle(zone); -#endif SnapshotTextObjectNamer namer(zone); ASSERT(offset_space_ != V8SnapshotProfileWriter::kSnapshot); @@ -958,15 +934,12 @@ void AssemblyImageWriter::WriteText(bool vm) { ASSERT_EQUAL(data.text_offset_, text_offset); intptr_t dwarf_index = i; -#if defined(DART_PRECOMPILER) if (!is_trampoline && assembly_dwarf_ != nullptr) { dwarf_index = assembly_dwarf_->AddCode(*data.code_, SegmentRelativeOffset(vm)); } -#endif const auto object_name = namer.SnapshotNameFor(dwarf_index, data); -#if defined(DART_PRECOMPILER) if (profile_writer_ != nullptr) { const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset); auto const type = is_trampoline ? trampoline_type_ : instructions_type_; @@ -979,7 +952,6 @@ void AssemblyImageWriter::WriteText(bool vm) { parent_id, {id, V8SnapshotProfileWriter::Reference::kElement, element_offset}); } -#endif if (is_trampoline) { const auto start = reinterpret_cast(data.trampoline_bytes); @@ -996,7 +968,7 @@ void AssemblyImageWriter::WriteText(bool vm) { // 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) { + if (!FLAG_use_bare_instructions) { NoSafepointScope no_safepoint; // Write Instructions with the mark and read-only bits set. @@ -1010,20 +982,19 @@ void AssemblyImageWriter::WriteText(bool vm) { ASSERT_EQUAL(text_offset - instr_start, compiler::target::Instructions::HeaderSize()); -#if defined(DART_PRECOMPILER) const auto& code = *data.code_; if (debug_elf_ != nullptr) { debug_elf_->dwarf()->AddCode(code, {vm, text_offset}); } -#endif // 2. Write a label at the entry point. // Linux's perf uses these labels. assembly_stream_->Printf("%s:\n", object_name); { + NoSafepointScope no_safepoint; + // 3. Write from the payload start to payload end. For AOT snapshots // with bare instructions, this is the only non-padding part serialized. - NoSafepointScope no_safepoint; const uword payload_start = insns.PayloadStart(); // Double-check the payload alignment, since we will load and write // target-sized words starting from that address. @@ -1031,7 +1002,6 @@ void AssemblyImageWriter::WriteText(bool vm) { const uword payload_size = insns.Size(); const uword payload_end = payload_start + payload_size; -#if defined(DART_PRECOMPILER) descriptors = code.pc_descriptors(); PcDescriptors::Iterator iterator(descriptors, PcDescriptorsLayout::kBSSRelocation); @@ -1046,15 +1016,12 @@ void AssemblyImageWriter::WriteText(bool vm) { text_offset += WriteByteSequence(cursor, next_reloc_address); const word addend = *reinterpret_cast(next_reloc_address); - assembly_stream_->Printf("%s %s - (.) + %" Pd "\n", kLiteralPrefix, + assembly_stream_->Printf("%s %s - (.) + %" Pd "\n", kWordDirective, bss_symbol, addend); text_offset += compiler::target::kWordSize; cursor = next_reloc_address + compiler::target::kWordSize; } text_offset += WriteByteSequence(cursor, payload_end); -#else - text_offset += WriteByteSequence(payload_start, payload_end); -#endif } // 4. Write from the payload end to object end. Note we can't simply copy @@ -1090,6 +1057,9 @@ void AssemblyImageWriter::WriteText(bool vm) { // Should be a no-op unless writing bare instruction payloads, in which case // we need to add post-payload padding to the object alignment. The alignment // needs to match the one we used for image_size above. + ASSERT(FLAG_use_bare_instructions || + Utils::IsAligned(text_offset, + compiler::target::ObjectAlignment::kObjectAlignment)); text_offset += Align(compiler::target::ObjectAlignment::kObjectAlignment, text_offset); @@ -1097,7 +1067,6 @@ void AssemblyImageWriter::WriteText(bool vm) { FrameUnwindEpilogue(); -#if defined(DART_PRECOMPILER) if (debug_elf_ != nullptr) { // We need to generate a text segment of the appropriate size in the ELF // for two reasons: @@ -1120,8 +1089,6 @@ void AssemblyImageWriter::WriteText(bool vm) { // writing the text section. ASSERT(debug_segment_base2 == debug_segment_base); } -#endif -#endif // !defined(DART_PRECOMPILED_RUNTIME) } void AssemblyImageWriter::FrameUnwindPrologue() { @@ -1236,6 +1203,16 @@ intptr_t AssemblyImageWriter::Align(intptr_t alignment, uword position) { return next_position - position; } +intptr_t AssemblyImageWriter::WriteWordLiteralText(word value) { + ASSERT(compiler::target::kBitsPerWord == kBitsPerWord || + Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value)); + // Padding is helpful for comparing the .S with --disassemble. + assembly_stream_->Printf("%s 0x%0.*" Px "\n", kWordDirective, + 2 * compiler::target::kWordSize, value); + return compiler::target::kWordSize; +} +#endif // defined(DART_PRECOMPILER) + BlobImageWriter::BlobImageWriter(Thread* thread, NonStreamingWriteStream* stream, Elf* debug_elf, @@ -1322,12 +1299,11 @@ void BlobImageWriter::WriteText(bool vm) { const intptr_t image_size = Utils::RoundUp( next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment); instructions_blob_stream_->WriteTargetWord(image_size); - if (FLAG_precompiled_mode) { - // Output the offset to the ImageHeader object from the start of the image. - instructions_blob_stream_->WriteTargetWord(Image::kHeaderSize); - } else { - instructions_blob_stream_->WriteTargetWord(0); // No ImageHeader object. - } + // Output the offset to the InstructionsSection object from the start of the + // image, if there is one. + instructions_blob_stream_->WriteTargetWord( + FLAG_precompiled_mode ? Image::kHeaderSize + : Image::kNoInstructionsSection); // Zero values for the rest of the Image object header bytes. instructions_blob_stream_->Align(Image::kHeaderSize); ASSERT_EQUAL(instructions_blob_stream_->Position(), Image::kHeaderSize); @@ -1338,90 +1314,73 @@ void BlobImageWriter::WriteText(bool vm) { if (profile_writer_ != nullptr) { profile_writer_->SetObjectTypeAndName(parent_id, image_type_, instructions_symbol); - // Assign post-instruction padding to the Image, unless we're writing bare - // instruction payloads, in which case we'll assign it to the - // InstructionsSection object. - const intptr_t padding = - bare_instruction_payloads ? 0 : image_size - next_text_offset_; - profile_writer_->AttributeBytesTo(parent_id, - Image::kHeaderSize + padding); + profile_writer_->AttributeBytesTo(parent_id, Image::kHeaderSize); profile_writer_->AddRoot(parent_id); } - // Write the ImageHeader object, starting with the header. - const intptr_t image_header_size = - compiler::target::ImageHeader::InstanceSize(); + // 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 - + compiler::target::InstructionsSection::HeaderSize() + : 0; + const intptr_t section_size = + compiler::target::InstructionsSection::InstanceSize( + section_payload_length); + if (profile_writer_ != nullptr) { const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset); - profile_writer_->SetObjectTypeAndName(id, image_header_type_, + profile_writer_->SetObjectTypeAndName(id, instructions_section_type_, instructions_symbol); - profile_writer_->AttributeBytesTo(id, image_header_size); + profile_writer_->AttributeBytesTo(id, + section_size - section_payload_length); const intptr_t element_offset = id.second - parent_id.second; profile_writer_->AttributeReferenceTo( parent_id, {id, V8SnapshotProfileWriter::Reference::kElement, element_offset}); + // If in bare instructions mode, later objects will have the + // InstructionsSection as a parent. + if (bare_instruction_payloads) { + parent_id = id; + } } - instructions_blob_stream_->WriteTargetWord( - GetMarkedTags(kImageHeaderCid, image_header_size)); + // Add the RawInstructionsSection header. + instructions_blob_stream_->WriteTargetWord( + GetMarkedTags(kInstructionsSectionCid, section_size)); ASSERT(elf_ != nullptr); - // An ImageHeader has four fields: - // 1) The BSS offset from this section. + // An InstructionsSection has five fields: + // 1) The size of the payload. + instructions_blob_stream_->WriteTargetWord(section_payload_length); + // 2) The BSS offset from this section. const word bss_offset = elf_->BssStart(vm) - segment_base; ASSERT(bss_offset != Image::kNoBssSection); instructions_blob_stream_->WriteTargetWord(bss_offset); - // 2) The relocated address of the instructions. + // 3) The relocated address of the instructions. // // Since we set this to a non-zero value for ELF snapshots, we also use this // to detect compiled-to-ELF snapshots. ASSERT(segment_base != Image::kNoRelocatedAddress); instructions_blob_stream_->WriteTargetWord(segment_base); - // 3) The GNU build ID offset from this section. - intptr_t build_id_length = 0; - const word build_id_offset = - elf_->BuildIdStart(&build_id_length) - segment_base; + // 4) The GNU build ID note offset from this section. + const word build_id_offset = elf_->BuildIdStart() - segment_base; ASSERT(build_id_offset != Image::kNoBuildId); instructions_blob_stream_->WriteTargetWord(build_id_offset); - // 4) The GNU build ID length. - ASSERT(build_id_length != 0); - instructions_blob_stream_->WriteTargetWord(build_id_length); - instructions_blob_stream_->Align( - compiler::target::ObjectAlignment::kObjectAlignment); + 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); + instructions_blob_stream_->Align(section_contents_alignment); ASSERT_EQUAL(instructions_blob_stream_->Position() - text_offset, - image_header_size); - text_offset += image_header_size; - - if (bare_instruction_payloads) { - if (profile_writer_ != nullptr) { - const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset); - profile_writer_->SetObjectTypeAndName(id, instructions_section_type_, - instructions_symbol); - const intptr_t padding = image_size - next_text_offset_; - profile_writer_->AttributeBytesTo( - id, compiler::target::InstructionsSection::HeaderSize() + padding); - const intptr_t element_offset = id.second - parent_id.second; - profile_writer_->AttributeReferenceTo( - parent_id, - {id, V8SnapshotProfileWriter::Reference::kElement, element_offset}); - // Later objects will have the InstructionsSection as a parent. - parent_id = id; - } - const intptr_t section_size = image_size - text_offset; - // Uses next_text_offset_ to avoid any post-payload padding. - const intptr_t instructions_length = - next_text_offset_ - text_offset - - compiler::target::InstructionsSection::HeaderSize(); - // Add the RawInstructionsSection header. - instructions_blob_stream_->WriteTargetWord( - GetMarkedTags(kInstructionsSectionCid, section_size)); - instructions_blob_stream_->WriteTargetWord(instructions_length); - instructions_blob_stream_->Align( - compiler::target::Instructions::kBarePayloadAlignment); - ASSERT_EQUAL(instructions_blob_stream_->Position() - text_offset, - compiler::target::InstructionsSection::HeaderSize()); - text_offset += compiler::target::InstructionsSection::HeaderSize(); - } + expected_size); + text_offset += expected_size; } #endif @@ -1572,6 +1531,9 @@ void BlobImageWriter::WriteText(bool vm) { // Should be a no-op unless writing bare instruction payloads, in which case // we need to add post-payload padding to the object alignment. The alignment // should match the alignment used in image_size above. + ASSERT(bare_instruction_payloads || + Utils::IsAligned(text_offset, + compiler::target::ObjectAlignment::kObjectAlignment)); instructions_blob_stream_->Align( compiler::target::ObjectAlignment::kObjectAlignment); text_offset = Utils::RoundUp( diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h index 0190caee6f8..f77842bbec6 100644 --- a/runtime/vm/image_snapshot.h +++ b/runtime/vm/image_snapshot.h @@ -82,10 +82,10 @@ class Image : ValueObject { enum class HeaderField : intptr_t { // The size of the image (total of header and payload). ImageSize, - // The offset of the ImageHeader object in the image. Note this offset - // is from the start of the _image_, _not_ from its payload start, so we - // can detect images without ImageHeaders by a 0 value here. - ImageHeaderOffset, + // The offset of the InstructionsSection object in the image. Note this + // offset is from the start of the _image_, _not_ from its payload start, + // so we can detect images without an InstructionsSection by a 0 value here. + InstructionsSectionOffset, // If adding more fields, updating kHeaderFields below. (However, more // fields _can't_ be added on 64-bit architectures, see the restrictions // on kHeaderSize below.) @@ -93,7 +93,7 @@ class Image : ValueObject { // Number of fields described by the HeaderField enum. static constexpr intptr_t kHeaderFields = - static_cast(HeaderField::ImageHeaderOffset) + 1; + static_cast(HeaderField::InstructionsSectionOffset) + 1; static uword FieldValue(uword raw_memory, HeaderField field) { return reinterpret_cast( @@ -101,8 +101,8 @@ class Image : ValueObject { } // Constants used to denote special values for the offsets in the Image - // object header and the fields of the ImageHeader object. - static constexpr intptr_t kNoImageHeader = 0; + // object header and the fields of the InstructionsSection object. + static constexpr intptr_t kNoInstructionsSection = 0; static constexpr intptr_t kNoBssSection = 0; static constexpr intptr_t kNoRelocatedAddress = 0; static constexpr intptr_t kNoBuildId = 0; @@ -126,13 +126,13 @@ class Image : ValueObject { // We don't use a handle or the tagged pointer because this object cannot be // moved in memory by the GC. - static const ImageHeaderLayout* ExtraInfo(const uword raw_memory, - const uword size); + static const InstructionsSectionLayout* ExtraInfo(const uword raw_memory, + const uword size); // Most internal uses would cast this to uword, so just store it as such. const uword raw_memory_; const intptr_t snapshot_size_; - const ImageHeaderLayout* const extra_info_; + const InstructionsSectionLayout* const extra_info_; // For access to private constants. friend class AssemblyImageWriter; @@ -249,15 +249,15 @@ class ImageWriter : public ValueObject { next_text_offset_ = Image::kHeaderSize; #if defined(DART_PRECOMPILER) if (FLAG_precompiled_mode) { - // We reserve space for the initial ImageHeader object. It is manually - // serialized since it involves offsets to other parts of the snapshot. - next_text_offset_ += compiler::target::ImageHeader::InstanceSize(); - if (FLAG_use_bare_instructions) { - // For bare instructions mode, we wrap all the instruction payloads - // in a single InstructionsSection object. - next_text_offset_ += - compiler::target::InstructionsSection::HeaderSize(); - } + // We reserve space for the initial InstructionsSection object. It is + // manually serialized since it includes offsets to other snapshot parts. + // In bare instructions mode, it contains all the payloads and so we + // start after the header, whereas in non-bare mode, it contains no + // payload and Instructions start after it. + next_text_offset_ += + FLAG_use_bare_instructions + ? compiler::target::InstructionsSection::HeaderSize() + : compiler::target::InstructionsSection::InstanceSize(0); } #endif objects_.Clear(); @@ -363,7 +363,6 @@ class ImageWriter : public ValueObject { V8SnapshotProfileWriter::kSnapshot; V8SnapshotProfileWriter* profile_writer_ = nullptr; const char* const image_type_; - const char* const image_header_type_; const char* const instructions_section_type_; const char* const instructions_type_; const char* const trampoline_type_; @@ -453,21 +452,7 @@ class AssemblyImageWriter : public ImageWriter { void FrameUnwindEpilogue(); intptr_t WriteByteSequence(uword start, uword end); intptr_t Align(intptr_t alignment, uword position = 0); - -#if defined(TARGET_ARCH_IS_64_BIT) - const char* kLiteralPrefix = ".quad"; -#else - const char* kLiteralPrefix = ".long"; -#endif - - intptr_t WriteWordLiteralText(word value) { - ASSERT(compiler::target::kBitsPerWord == kBitsPerWord || - Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value)); - // Padding is helpful for comparing the .S with --disassemble. - assembly_stream_->Printf("%s 0x%0.*" Px "\n", kLiteralPrefix, - 2 * compiler::target::kWordSize, value); - return compiler::target::kWordSize; - } + intptr_t WriteWordLiteralText(word value); BaseWriteStream* const assembly_stream_; Dwarf* const assembly_dwarf_; diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index c9be18c997b..2b1195da238 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -16051,10 +16051,6 @@ ICDataPtr ICData::Clone(const ICData& from) { } #endif -const char* ImageHeader::ToCString() const { - return "ImageHeader"; -} - const char* WeakSerializationReference::ToCString() const { #if defined(DART_PRECOMPILED_RUNTIME) return Symbols::OptimizedOut().ToCString(); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 9577ff4d71e..9a9702f8bdc 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -5601,12 +5601,19 @@ class Instructions : public Object { friend class ImageWriter; }; -// Used only to provide memory accounting for the bare instruction payloads -// we serialize, since they are no longer part of RawInstructions objects. +// An InstructionsSection contains extra information about serialized AOT +// snapshots. +// +// To avoid changing the embedder to return more information about an AOT +// snapshot and possibly disturbing existing clients of that interface, we +// serialize a single InstructionsSection object at the start of any text +// segments. In bare instructions mode, it also has the benefit of providing +// memory accounting for the instructions payloads and avoiding special casing +// Images with bare instructions payloads in the GC. Otherwise, it is empty +// and the Instructions objects come after it in the Image. class InstructionsSection : public Object { public: // Excludes HeaderSize(). - intptr_t Size() const { return raw_ptr()->payload_length_; } static intptr_t Size(const InstructionsSectionPtr instr) { return instr->ptr()->payload_length_; } @@ -5625,7 +5632,14 @@ class InstructionsSection : public Object { Instructions::kBarePayloadAlignment); } + // There are no public instance methods for the InstructionsSection class, as + // all access to the contents is handled by methods on the Image class. + private: + // Note there are no New() methods for InstructionsSection. Instead, the + // serializer writes the InstructionsSectionLayout object manually at the + // start of instructions Images in precompiled snapshots. + FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection, Object); friend class Class; }; @@ -5988,26 +6002,6 @@ class ExceptionHandlers : public Object { friend class Object; }; -// An ImageHeader contains extra information about serialized AOT snapshots. -// -// To avoid changing the embedder to return more information about an AOT -// snapshot and possibly disturbing existing clients of that interface, we -// serialize a single ImageHeader object at the start of any text segments. -class ImageHeader : public Object { - public: - static intptr_t InstanceSize() { - return RoundedAllocationSize(sizeof(ImageHeaderLayout)); - } - // There are no public methods for the ImageHeader contents, because - // all access to the contents is handled by methods on the Image class. - - private: - // Note there are no New() methods for ImageHeaders. Unstead, the serializer - // writes the ImageHeaderLayout object manually at the start of the text - // segment in precompiled snapshots. - FINAL_HEAP_OBJECT_IMPLEMENTATION(ImageHeader, Object); -}; - // A WeakSerializationReference (WSR) denotes a type of weak reference to a // target object. In particular, objects that can only be reached from roots via // WSR edges during serialization of AOT snapshots should not be serialized. Of diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc index 80eb1e8f855..c70282b5b6f 100644 --- a/runtime/vm/object_service.cc +++ b/runtime/vm/object_service.cc @@ -684,10 +684,6 @@ void InstructionsSection::PrintJSONImpl(JSONStream* stream, bool ref) const { Object::PrintJSONImpl(stream, ref); } -void ImageHeader::PrintJSONImpl(JSONStream* stream, bool ref) const { - Object::PrintJSONImpl(stream, ref); -} - void WeakSerializationReference::PrintJSONImpl(JSONStream* stream, bool ref) const { JSONObject jsobj(stream); diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc index de63846419c..3dfd910f058 100644 --- a/runtime/vm/raw_object.cc +++ b/runtime/vm/raw_object.cc @@ -223,10 +223,6 @@ intptr_t ObjectLayout::HeapSizeFromClass(uint32_t tags) const { instance_size = element->HeapSize(); break; } - case kImageHeaderCid: { - instance_size = ImageHeader::InstanceSize(); - break; - } case kWeakSerializationReferenceCid: { instance_size = WeakSerializationReference::InstanceSize(); break; @@ -568,7 +564,6 @@ NULL_VISITOR(Bool) NULL_VISITOR(Capability) NULL_VISITOR(SendPort) NULL_VISITOR(TransferableTypedData) -NULL_VISITOR(ImageHeader) REGULAR_VISITOR(Pointer) NULL_VISITOR(DynamicLibrary) VARIABLE_NULL_VISITOR(Instructions, Instructions::Size(raw_obj)) diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index cb853c66e1f..9dd7f8f3550 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -1415,25 +1415,6 @@ class KernelProgramInfoLayout : public ObjectLayout { } }; -class ImageHeaderLayout : public ObjectLayout { - RAW_HEAP_OBJECT_IMPLEMENTATION(ImageHeader); - - VISIT_NOTHING(); - // The offset of the corresponding BSS section from this text section. - uword bss_offset_; - // The relocated address of this text section in the shared object. Properly - // filled for ELF snapshots, always 0 in assembly snapshots. (For the latter, - // we instead get the value during BSS initialization and store it there.) - uword instructions_relocated_address_; - // The offset of the GNU build ID section description field from this text - // section. - uword build_id_offset_; - // The length of the GNU build ID section description field. - uword build_id_length_; - - friend class Image; -}; - class WeakSerializationReferenceLayout : public ObjectLayout { RAW_HEAP_OBJECT_IMPLEMENTATION(WeakSerializationReference); @@ -1649,17 +1630,29 @@ class InstructionsLayout : public ObjectLayout { friend class BlobImageWriter; }; -// Used only to provide memory accounting for the bare instruction payloads -// we serialize, since they are no longer part of RawInstructions objects. +// Used to carry extra information to the VM without changing the embedder +// interface, to provide memory accounting for the bare instruction payloads +// we serialize, since they are no longer part of RawInstructions objects, +// and to avoid special casing bare instructions payload Images in the GC. class InstructionsSectionLayout : public ObjectLayout { RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection); VISIT_NOTHING(); // Instructions section payload length in bytes. uword payload_length_; + // The offset of the corresponding BSS section from this text section. + word bss_offset_; + // The relocated address of this text section in the shared object. Properly + // filled for ELF snapshots, always 0 in assembly snapshots. (For the latter, + // we instead get the value during BSS initialization and store it there.) + uword instructions_relocated_address_; + // The offset of the GNU build ID note section from this text section. + word build_id_offset_; // Variable length data follows here. uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); } + + friend class Image; }; class PcDescriptorsLayout : public ObjectLayout { diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc index 83e457d8220..2f36c97dd05 100644 --- a/runtime/vm/raw_object_snapshot.cc +++ b/runtime/vm/raw_object_snapshot.cc @@ -582,7 +582,6 @@ MESSAGE_SNAPSHOT_UNREACHABLE(MonomorphicSmiableCall); MESSAGE_SNAPSHOT_UNREACHABLE(UnwindError); MESSAGE_SNAPSHOT_UNREACHABLE(FutureOr); MESSAGE_SNAPSHOT_UNREACHABLE(WeakSerializationReference); -MESSAGE_SNAPSHOT_UNREACHABLE(ImageHeader); MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary); MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference); diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h index 0cd85484fe2..6a8ce0379ec 100644 --- a/runtime/vm/tagged_pointer.h +++ b/runtime/vm/tagged_pointer.h @@ -241,7 +241,6 @@ DEFINE_TAGGED_POINTER(Script, Object) DEFINE_TAGGED_POINTER(Library, Object) DEFINE_TAGGED_POINTER(Namespace, Object) DEFINE_TAGGED_POINTER(KernelProgramInfo, Object) -DEFINE_TAGGED_POINTER(ImageHeader, Object) DEFINE_TAGGED_POINTER(WeakSerializationReference, Object) DEFINE_TAGGED_POINTER(Code, Object) DEFINE_TAGGED_POINTER(Bytecode, Object)