[vm] Follow up to 4a4eedd860a8af2b1cb27e68d9feae5550d0f511
* 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>
diff --git a/runtime/vm/analyze_snapshot_api_impl.cc b/runtime/vm/analyze_snapshot_api_impl.cc
index fa45dd6..7f340ab 100644
--- a/runtime/vm/analyze_snapshot_api_impl.cc
+++ b/runtime/vm/analyze_snapshot_api_impl.cc
@@ -238,7 +238,7 @@
// 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);
// }
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index e4c21f7..a6fa4cb 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -98,6 +98,10 @@
// 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 @@
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;
}
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.cc b/runtime/vm/compiler/aot/dispatch_table_generator.cc
index 1245c38..6d8694f 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.cc
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.cc
@@ -629,7 +629,7 @@
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 @@
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 @@
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);
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 5a9918a..26d1a71 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -695,7 +695,7 @@
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
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index fd697f2..9603a4f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -696,7 +696,7 @@
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.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
index 1decc19..97e7da8 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
@@ -666,7 +666,7 @@
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);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index ba0add49..e8c2a7d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -682,7 +682,7 @@
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));
diff --git a/runtime/vm/dispatch_table.cc b/runtime/vm/dispatch_table.cc
index 7aa3eca..8ec4661 100644
--- a/runtime/vm/dispatch_table.cc
+++ b/runtime/vm/dispatch_table.cc
@@ -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
diff --git a/runtime/vm/dispatch_table.h b/runtime/vm/dispatch_table.h
index 8d02cdf..6ba4369 100644
--- a/runtime/vm/dispatch_table.h
+++ b/runtime/vm/dispatch_table.h
@@ -20,8 +20,45 @@
// 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;