mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm] Create an abstraction for updating object size info in tags for target.
Change-Id: I8661af9834f2ff97f036cf4f1612c20515148949 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-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/+/135652 Commit-Queue: Teagan Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
6d04a0db25
commit
bccd3f7aab
|
@ -128,6 +128,12 @@
|
|||
#define DEBUG_ONLY(code)
|
||||
#endif // defined(DEBUG)
|
||||
|
||||
#if defined(DEBUG)
|
||||
#define UNLESS_DEBUG(code)
|
||||
#else // defined(DEBUG)
|
||||
#define UNLESS_DEBUG(code) code
|
||||
#endif // defined(DEBUG)
|
||||
|
||||
namespace dart {
|
||||
|
||||
struct simd128_value_t {
|
||||
|
|
|
@ -25,7 +25,7 @@ class BitField {
|
|||
static const intptr_t kNextBit = position + size;
|
||||
|
||||
// Tells whether the provided value fits into the bit field.
|
||||
static bool is_valid(T value) {
|
||||
static constexpr bool is_valid(T value) {
|
||||
return (static_cast<S>(value) & ~((kUwordOne << size) - 1)) == 0;
|
||||
}
|
||||
|
||||
|
@ -46,21 +46,21 @@ class BitField {
|
|||
static constexpr int bitsize() { return size; }
|
||||
|
||||
// Returns an S with the bit field value encoded.
|
||||
static S encode(T value) {
|
||||
ASSERT(is_valid(value));
|
||||
static UNLESS_DEBUG(constexpr) S encode(T value) {
|
||||
DEBUG_ASSERT(is_valid(value));
|
||||
return static_cast<S>(value) << position;
|
||||
}
|
||||
|
||||
// Extracts the bit field from the value.
|
||||
static T decode(S value) {
|
||||
static constexpr T decode(S value) {
|
||||
return static_cast<T>((value >> position) & ((kUwordOne << size) - 1));
|
||||
}
|
||||
|
||||
// Returns an S with the bit field value encoded based on the
|
||||
// original value. Only the bits corresponding to this bit field
|
||||
// will be changed.
|
||||
static S update(T value, S original) {
|
||||
ASSERT(is_valid(value));
|
||||
static UNLESS_DEBUG(constexpr) S update(T value, S original) {
|
||||
DEBUG_ASSERT(is_valid(value));
|
||||
return (static_cast<S>(value) << position) | (~mask_in_place() & original);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -377,7 +377,6 @@ void ImageWriter::WriteROData(WriteStream* stream) {
|
|||
|
||||
NoSafepointScope no_safepoint;
|
||||
uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
|
||||
uword end = start + obj.raw()->HeapSize();
|
||||
|
||||
// Write object header with the mark and read-only bits set.
|
||||
uword marked_tags = obj.raw()->ptr()->tags_;
|
||||
|
@ -390,10 +389,6 @@ void ImageWriter::WriteROData(WriteStream* stream) {
|
|||
#endif
|
||||
|
||||
#if defined(IS_SIMARM_X64)
|
||||
static_assert(
|
||||
kObjectAlignment ==
|
||||
compiler::target::ObjectAlignment::kObjectAlignment * 2,
|
||||
"host object alignment is not double target object alignment");
|
||||
if (obj.IsCompressedStackMaps()) {
|
||||
const CompressedStackMaps& map = CompressedStackMaps::Cast(obj);
|
||||
auto const object_start = stream->Position();
|
||||
|
@ -401,7 +396,7 @@ void ImageWriter::WriteROData(WriteStream* stream) {
|
|||
const intptr_t payload_size = map.payload_size();
|
||||
const intptr_t size_in_bytes =
|
||||
CompressedStackMapsSizeInSnapshot(payload_size);
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
|
||||
|
||||
stream->WriteTargetWord(marked_tags);
|
||||
stream->WriteFixed<uint32_t>(map.raw()->ptr()->flags_and_size_);
|
||||
|
@ -415,7 +410,7 @@ void ImageWriter::WriteROData(WriteStream* stream) {
|
|||
RELEASE_ASSERT(str.IsOneByteString() || str.IsTwoByteString());
|
||||
const intptr_t size_in_bytes =
|
||||
StringSizeInSnapshot(str.Length(), str.IsOneByteString());
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
|
||||
|
||||
stream->WriteTargetWord(marked_tags);
|
||||
stream->WriteTargetWord(
|
||||
|
@ -427,9 +422,8 @@ void ImageWriter::WriteROData(WriteStream* stream) {
|
|||
stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
} else if (obj.IsCodeSourceMap()) {
|
||||
const CodeSourceMap& map = CodeSourceMap::Cast(obj);
|
||||
|
||||
const intptr_t size_in_bytes = CodeSourceMapSizeInSnapshot(map.Length());
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
|
||||
|
||||
stream->WriteTargetWord(marked_tags);
|
||||
stream->WriteTargetWord(map.Length());
|
||||
|
@ -439,7 +433,7 @@ void ImageWriter::WriteROData(WriteStream* stream) {
|
|||
const PcDescriptors& desc = PcDescriptors::Cast(obj);
|
||||
|
||||
const intptr_t size_in_bytes = PcDescriptorsSizeInSnapshot(desc.Length());
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
|
||||
|
||||
stream->WriteTargetWord(marked_tags);
|
||||
stream->WriteTargetWord(desc.Length());
|
||||
|
@ -449,9 +443,9 @@ void ImageWriter::WriteROData(WriteStream* stream) {
|
|||
const Class& clazz = Class::Handle(obj.clazz());
|
||||
FATAL1("Unsupported class %s in rodata section.\n", clazz.ToCString());
|
||||
}
|
||||
USE(start);
|
||||
USE(end);
|
||||
#else // defined(IS_SIMARM_X64)
|
||||
const uword end = start + obj.raw()->HeapSize();
|
||||
|
||||
stream->WriteWord(marked_tags);
|
||||
start += sizeof(uword);
|
||||
for (uword* cursor = reinterpret_cast<uword*>(start);
|
||||
|
@ -623,21 +617,13 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
if (bare_instruction_payloads) {
|
||||
const intptr_t section_size = image_size - Image::kHeaderSize;
|
||||
// Add the RawInstructionsSection header.
|
||||
uword marked_tags = 0;
|
||||
marked_tags = RawObject::OldBit::update(true, marked_tags);
|
||||
marked_tags = RawObject::OldAndNotRememberedBit::update(true, marked_tags);
|
||||
#if defined(IS_SIMARM_X64)
|
||||
static_assert(
|
||||
kObjectAlignment ==
|
||||
compiler::target::ObjectAlignment::kObjectAlignment * 2,
|
||||
"host object alignment is not double target object alignment");
|
||||
marked_tags = RawObject::SizeTag::update(2 * section_size, marked_tags);
|
||||
#else
|
||||
marked_tags = RawObject::SizeTag::update(section_size, marked_tags);
|
||||
#endif
|
||||
marked_tags =
|
||||
RawObject::ClassIdTag::update(kInstructionsSectionCid, marked_tags);
|
||||
|
||||
const compiler::target::uword marked_tags =
|
||||
RawObject::OldBit::encode(true) |
|
||||
RawObject::OldAndNotMarkedBit::encode(false) |
|
||||
RawObject::OldAndNotRememberedBit::encode(true) |
|
||||
RawObject::NewBit::encode(false) |
|
||||
RawObject::SizeTag::encode(AdjustObjectSizeForTarget(section_size)) |
|
||||
RawObject::ClassIdTag::encode(kInstructionsSectionCid);
|
||||
WriteWordLiteralText(marked_tags);
|
||||
// Calculated using next_text_offset_, which doesn't include post-payload
|
||||
// padding to object alignment.
|
||||
|
@ -743,7 +729,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
|
||||
#if defined(IS_SIMARM_X64)
|
||||
const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
|
||||
WriteWordLiteralText(marked_tags);
|
||||
text_offset += sizeof(compiler::target::uword);
|
||||
WriteWordLiteralText(insns.raw_ptr()->size_and_flags_);
|
||||
|
@ -1076,21 +1062,13 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
if (bare_instruction_payloads) {
|
||||
const intptr_t section_size = image_size - Image::kHeaderSize;
|
||||
// Add the RawInstructionsSection header.
|
||||
uword marked_tags = 0;
|
||||
marked_tags = RawObject::OldBit::update(true, marked_tags);
|
||||
marked_tags = RawObject::OldAndNotRememberedBit::update(true, marked_tags);
|
||||
#if defined(IS_SIMARM_X64)
|
||||
static_assert(
|
||||
kObjectAlignment ==
|
||||
compiler::target::ObjectAlignment::kObjectAlignment * 2,
|
||||
"host object alignment is not double target object alignment");
|
||||
marked_tags = RawObject::SizeTag::update(2 * section_size, marked_tags);
|
||||
#else
|
||||
marked_tags = RawObject::SizeTag::update(section_size, marked_tags);
|
||||
#endif
|
||||
marked_tags =
|
||||
RawObject::ClassIdTag::update(kInstructionsSectionCid, marked_tags);
|
||||
|
||||
const compiler::target::uword marked_tags =
|
||||
RawObject::OldBit::encode(true) |
|
||||
RawObject::OldAndNotMarkedBit::encode(false) |
|
||||
RawObject::OldAndNotRememberedBit::encode(true) |
|
||||
RawObject::NewBit::encode(false) |
|
||||
RawObject::SizeTag::encode(AdjustObjectSizeForTarget(section_size)) |
|
||||
RawObject::ClassIdTag::encode(kInstructionsSectionCid);
|
||||
instructions_blob_stream_.WriteTargetWord(marked_tags);
|
||||
// Uses next_text_offset_ to avoid any post-payload padding.
|
||||
const intptr_t instructions_length =
|
||||
|
@ -1167,9 +1145,7 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
|
||||
if (!bare_instruction_payloads) {
|
||||
const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
|
||||
ASSERT_EQUAL(kObjectAlignment,
|
||||
compiler::target::ObjectAlignment::kObjectAlignment * 2);
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
|
||||
instructions_blob_stream_.WriteTargetWord(marked_tags);
|
||||
instructions_blob_stream_.WriteFixed<uint32_t>(
|
||||
insns.raw_ptr()->size_and_flags_);
|
||||
|
|
|
@ -186,6 +186,35 @@ class ImageWriter : public ValueObject {
|
|||
static intptr_t SizeInSnapshot(RawObject* object);
|
||||
static const intptr_t kBareInstructionsAlignment = 4;
|
||||
|
||||
static_assert(
|
||||
(kObjectAlignmentLog2 -
|
||||
compiler::target::ObjectAlignment::kObjectAlignmentLog2) >= 0,
|
||||
"Target object alignment is larger than the host object alignment");
|
||||
|
||||
// Converts the target object size (in bytes) to an appropriate argument for
|
||||
// RawObject::SizeTag methods on the host machine.
|
||||
//
|
||||
// RawObject::SizeTag expects a size divisible by kObjectAlignment and
|
||||
// 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.
|
||||
//
|
||||
// If target_size = n, we convert it to n * m, where m is the host alignment
|
||||
// divided by the target alignment. This means AdjustObjectSizeForTarget(n)
|
||||
// encodes on the host machine to the same bits that decode to n on the target
|
||||
// machine. That is:
|
||||
// n * (host align / target align) / host align => n / target align
|
||||
static constexpr intptr_t AdjustObjectSizeForTarget(intptr_t target_size) {
|
||||
return target_size
|
||||
<< (kObjectAlignmentLog2 -
|
||||
compiler::target::ObjectAlignment::kObjectAlignmentLog2);
|
||||
}
|
||||
|
||||
static UNLESS_DEBUG(constexpr) compiler::target::uword
|
||||
UpdateObjectSizeForTarget(intptr_t size, uword marked_tags) {
|
||||
return RawObject::SizeTag::update(AdjustObjectSizeForTarget(size),
|
||||
marked_tags);
|
||||
}
|
||||
|
||||
protected:
|
||||
void WriteROData(WriteStream* stream);
|
||||
virtual void WriteText(WriteStream* clustered_stream, bool vm) = 0;
|
||||
|
|
|
@ -154,15 +154,15 @@ class RawObject {
|
|||
static constexpr intptr_t kMaxSizeTag =
|
||||
kMaxSizeTagInUnitsOfAlignment * kObjectAlignment;
|
||||
|
||||
static uword encode(intptr_t size) {
|
||||
static UNLESS_DEBUG(constexpr) uword encode(intptr_t size) {
|
||||
return SizeBits::encode(SizeToTagValue(size));
|
||||
}
|
||||
|
||||
static intptr_t decode(uword tag) {
|
||||
static constexpr uword decode(uword tag) {
|
||||
return TagValueToSize(SizeBits::decode(tag));
|
||||
}
|
||||
|
||||
static uword update(intptr_t size, uword tag) {
|
||||
static UNLESS_DEBUG(constexpr) uword update(intptr_t size, uword tag) {
|
||||
return SizeBits::update(SizeToTagValue(size), tag);
|
||||
}
|
||||
|
||||
|
@ -171,11 +171,11 @@ class RawObject {
|
|||
class SizeBits
|
||||
: public BitField<uint32_t, intptr_t, kSizeTagPos, kSizeTagSize> {};
|
||||
|
||||
static intptr_t SizeToTagValue(intptr_t size) {
|
||||
ASSERT(Utils::IsAligned(size, kObjectAlignment));
|
||||
static UNLESS_DEBUG(constexpr) intptr_t SizeToTagValue(intptr_t size) {
|
||||
DEBUG_ASSERT(Utils::IsAligned(size, kObjectAlignment));
|
||||
return (size > kMaxSizeTag) ? 0 : (size >> kObjectAlignmentLog2);
|
||||
}
|
||||
static intptr_t TagValueToSize(intptr_t value) {
|
||||
static constexpr intptr_t TagValueToSize(intptr_t value) {
|
||||
return value << kObjectAlignmentLog2;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue