[vm] Follow up to 4a4eedd860

* Avoid calling memmove(dst, nullptr, 0) as this is flagged by UBSAN.
* Avoid hitting a bug[1] in the linker: LLD's identical code folding
(ICF) happens to replace RecordCoverageInstr::DebugName() with
DispatchTable::LargestSmallOffset() because they happen to contain
the same machine code, ICF fails to accomodate that DebugName also
contains a relocation to constant string. To avoid this we simply
eliminate LargestSmallOffset and replace it with a constant. Same for
OriginElement.

TEST=manually tested previously failing tests

[1]: reported https://github.com/llvm/llvm-project/issues/57693

Change-Id: I38637df6475c7670081b7af0a2de75ca37f6f07c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/258801
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
Vyacheslav Egorov 2022-09-12 12:33:57 +00:00 committed by Commit Bot
parent 727e792e77
commit 912577baec
9 changed files with 56 additions and 58 deletions

View file

@ -238,7 +238,7 @@ void DumpObjectPoolJSON(Thread* thread, dart::JSONWriter* js) {
// auto dispatch = thread->isolate_group()->dispatch_table();
// auto length = dispatch->length();
// We must unbias the array entries so we don't crash on null access.
// auto entries = dispatch->ArrayOrigin() - DispatchTable::OriginElement();
// auto entries = dispatch->ArrayOrigin() - DispatchTable::kOriginElement;
// for (intptr_t i = 0; i < length; i++) {
// OS::Print("0x%lx at %ld\n", entries[i], i);
// }

View file

@ -98,6 +98,10 @@ class ClassTableAllocator : public ValueObject {
// Clone the given |array| with |size| elements.
template <class T>
inline T* Clone(T* array, intptr_t size) {
if (array == nullptr) {
ASSERT(size == 0);
return nullptr;
}
auto result = Alloc<T>(size);
memmove(result, array, size * sizeof(T));
return result;
@ -112,7 +116,10 @@ class ClassTableAllocator : public ValueObject {
inline T* Realloc(T* array, intptr_t size, intptr_t new_size) {
ASSERT(size < new_size);
auto result = AllocZeroInitialized<T>(new_size);
memmove(result, array, size * sizeof(T));
if (size != 0) {
ASSERT(result != nullptr);
memmove(result, array, size * sizeof(T));
}
Free(array);
return result;
}

View file

@ -629,7 +629,7 @@ void DispatchTableGenerator::ComputeSelectorOffsets() {
table_rows_.Sort(PopularitySorter::Compare);
// Try to allocate at optimal offset.
const int32_t optimal_offset = DispatchTable::OriginElement();
const int32_t optimal_offset = DispatchTable::kOriginElement;
for (intptr_t i = 0; i < table_rows_.length(); i++) {
fitter.FitAndAllocate(table_rows_[i], optimal_offset, optimal_offset);
}
@ -644,7 +644,7 @@ void DispatchTableGenerator::ComputeSelectorOffsets() {
table_rows_.Sort(PopularitySizeRatioSorter::Compare);
// Try to allocate at small offsets.
const int32_t max_offset = DispatchTable::LargestSmallOffset();
const int32_t max_offset = DispatchTable::kLargestSmallOffset;
for (intptr_t i = 0; i < table_rows_.length(); i++) {
fitter.FitAndAllocate(table_rows_[i], 0, max_offset);
}
@ -658,7 +658,7 @@ void DispatchTableGenerator::ComputeSelectorOffsets() {
table_rows_.Sort(SizeSorter::Compare);
// Allocate remaining rows at large offsets.
const int32_t min_large_offset = DispatchTable::LargestSmallOffset() + 1;
const int32_t min_large_offset = DispatchTable::kLargestSmallOffset + 1;
for (intptr_t i = 0; i < table_rows_.length(); i++) {
fitter.FitAndAllocate(table_rows_[i], min_large_offset);
}

View file

@ -695,7 +695,7 @@ void FlowGraphCompiler::EmitDispatchTableCall(
if (!arguments_descriptor.IsNull()) {
__ LoadObject(ARGS_DESC_REG, arguments_descriptor);
}
intptr_t offset = (selector_offset - DispatchTable::OriginElement()) *
intptr_t offset = (selector_offset - DispatchTable::kOriginElement) *
compiler::target::kWordSize;
CLOBBERS_LR({
// Would like cid_reg to be available on entry to the target function

View file

@ -696,7 +696,7 @@ void FlowGraphCompiler::EmitDispatchTableCall(
if (!arguments_descriptor.IsNull()) {
__ LoadObject(ARGS_DESC_REG, arguments_descriptor);
}
const intptr_t offset = selector_offset - DispatchTable::OriginElement();
const intptr_t offset = selector_offset - DispatchTable::kOriginElement;
CLOBBERS_LR({
// Would like cid_reg to be available on entry to the target function
// for checking purposes.

View file

@ -666,7 +666,7 @@ void FlowGraphCompiler::EmitDispatchTableCall(
if (!arguments_descriptor.IsNull()) {
__ LoadObject(ARGS_DESC_REG, arguments_descriptor);
}
const intptr_t offset = selector_offset - DispatchTable::OriginElement();
const intptr_t offset = selector_offset - DispatchTable::kOriginElement;
// Would like cid_reg to be available on entry to the target function
// for checking purposes.
ASSERT(cid_reg != TMP);

View file

@ -682,7 +682,7 @@ void FlowGraphCompiler::EmitDispatchTableCall(
if (!arguments_descriptor.IsNull()) {
__ LoadObject(ARGS_DESC_REG, arguments_descriptor);
}
const intptr_t offset = (selector_offset - DispatchTable::OriginElement()) *
const intptr_t offset = (selector_offset - DispatchTable::kOriginElement) *
compiler::target::kWordSize;
__ LoadDispatchTable(table_reg);
__ call(compiler::Address(table_reg, cid_reg, TIMES_8, offset));

View file

@ -8,54 +8,8 @@
namespace dart {
intptr_t DispatchTable::OriginElement() {
#if defined(TARGET_ARCH_X64)
// Max negative byte offset / 8
return 16;
#elif defined(TARGET_ARCH_ARM)
// Max negative load offset / 4
return 1023;
#elif defined(TARGET_ARCH_ARM64)
// Max consecutive sub immediate value
return 4096;
#elif defined(TARGET_ARCH_RISCV32)
// Max consecutive sub immediate value
return 2048 / 4;
#elif defined(TARGET_ARCH_RISCV64)
// Max consecutive sub immediate value
return 2048 / 8;
#else
// No AOT on IA32
UNREACHABLE();
return 0;
#endif
}
intptr_t DispatchTable::LargestSmallOffset() {
#if defined(TARGET_ARCH_X64)
// Origin + Max positive byte offset / 8
return 31;
#elif defined(TARGET_ARCH_ARM)
// Origin + Max positive load offset / 4
return 2046;
#elif defined(TARGET_ARCH_ARM64)
// Origin + Max consecutive add immediate value
return 8192;
#elif defined(TARGET_ARCH_RISCV32)
// Origin + Max consecutive add immediate value
return 4096 / 4;
#elif defined(TARGET_ARCH_RISCV64)
// Origin + Max consecutive add immediate value
return 4096 / 8;
#else
// No AOT on IA32
UNREACHABLE();
return 0;
#endif
}
const uword* DispatchTable::ArrayOrigin() const {
return &array_.get()[OriginElement()];
return &array_.get()[kOriginElement];
}
} // namespace dart

View file

@ -20,8 +20,45 @@ class DispatchTable {
// The element of the dispatch table array to which the dispatch table
// register points.
static intptr_t OriginElement();
static intptr_t LargestSmallOffset();
#if defined(TARGET_ARCH_X64)
// Max negative byte offset / 8
static constexpr intptr_t kOriginElement = 16;
#elif defined(TARGET_ARCH_ARM)
// Max negative load offset / 4
static constexpr intptr_t kOriginElement = 1023;
#elif defined(TARGET_ARCH_ARM64)
// Max consecutive sub immediate value
static constexpr intptr_t kOriginElement = 4096;
#elif defined(TARGET_ARCH_RISCV32)
// Max consecutive sub immediate value
static constexpr intptr_t kOriginElement = 2048 / 4;
#elif defined(TARGET_ARCH_RISCV64)
// Max consecutive sub immediate value
static constexpr intptr_t kOriginElement = 2048 / 8;
#else
static constexpr intptr_t kOriginElement = 0;
#endif
#if defined(TARGET_ARCH_X64)
// Origin + Max positive byte offset / 8
static constexpr intptr_t kLargestSmallOffset = 31;
#elif defined(TARGET_ARCH_ARM)
// Origin + Max positive load offset / 4
static constexpr intptr_t kLargestSmallOffset = 2046;
#elif defined(TARGET_ARCH_ARM64)
// Origin + Max consecutive add immediate value
static constexpr intptr_t kLargestSmallOffset = 8192;
#elif defined(TARGET_ARCH_RISCV32)
// Origin + Max consecutive add immediate value
static constexpr intptr_t kLargestSmallOffset = 4096 / 4;
#elif defined(TARGET_ARCH_RISCV64)
// Origin + Max consecutive add immediate value
static constexpr intptr_t kLargestSmallOffset = 4096 / 8;
#else
// No AOT on IA32
static constexpr intptr_t kLargestSmallOffset = 0;
#endif
// Dispatch table array pointer to put into the dispatch table register.
const uword* ArrayOrigin() const;