[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:
Teagan Strickland 2020-02-14 17:57:47 +00:00 committed by commit-bot@chromium.org
parent 6d04a0db25
commit bccd3f7aab
5 changed files with 69 additions and 58 deletions

View file

@ -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 {

View file

@ -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);
}
};

View file

@ -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_);

View file

@ -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;

View file

@ -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;
}
};