[LEGACY MM] Escape making extra increments and decrements during coping to the same array (#4731)

(cherry picked from commit 8b601d8e2c6bc772386ebd88d303a032a6f54237)
This commit is contained in:
LepilkinaElena
2021-03-04 13:54:49 +03:00
committed by Space
parent f9f948fea6
commit fcbb921194
7 changed files with 70 additions and 8 deletions
@@ -2192,6 +2192,37 @@ void updateHeapRef(ObjHeader** location, const ObjHeader* object) {
}
}
template <bool Strict>
void updateHeapRefsInsideOneArray(const ArrayHeader* array, int fromIndex, int toIndex, int count) {
// In case of coping inside same array number of decrements and increments of RC can be decreased.
auto countIndex = [=](int i) { return (fromIndex < toIndex) ? count - 1 - i : i; };
int rewrittenElementsNumber = std::abs(fromIndex - toIndex);
// Release rewritten elements.
for (int i = 0; i < rewrittenElementsNumber; i++) {
int index = countIndex(i);
ObjHeader* old = *ArrayAddressOfElementAt(array, toIndex + index);
*const_cast<const ObjHeader**>(ArrayAddressOfElementAt(array, toIndex + index)) =
*ArrayAddressOfElementAt(array, fromIndex + index);
if (old != nullptr) {
releaseHeapRef<Strict>(old);
}
}
for (int i = rewrittenElementsNumber; i < count - rewrittenElementsNumber; i++) {
int index = countIndex(i);
*const_cast<const ObjHeader**>(ArrayAddressOfElementAt(array, toIndex + index)) =
*ArrayAddressOfElementAt(array, fromIndex + index);
}
for (int i = count - rewrittenElementsNumber; i < count; i++) {
int index = countIndex(i);
ObjHeader* object = *ArrayAddressOfElementAt(array, fromIndex + index);
// Add extra heap ref for copied elements.
if (object != nullptr) {
addHeapRef(object);
}
*const_cast<const ObjHeader**>(ArrayAddressOfElementAt(array, toIndex + index)) = object;
}
}
template <bool Strict>
void updateStackRef(ObjHeader** location, const ObjHeader* object) {
UPDATE_REF_EVENT(memoryState, *location, object, location, 1)
@@ -3367,6 +3398,15 @@ RUNTIME_NOTHROW void UpdateHeapRefRelaxed(ObjHeader** location, const ObjHeader*
updateHeapRef<false>(location, object);
}
RUNTIME_NOTHROW void UpdateHeapRefsInsideOneArrayStrict(const ArrayHeader* array, int fromIndex, int toIndex,
int count) {
updateHeapRefsInsideOneArray<true>(array, fromIndex, toIndex, count);
}
RUNTIME_NOTHROW void UpdateHeapRefsInsideOneArrayRelaxed(const ArrayHeader* array, int fromIndex, int toIndex,
int count) {
updateHeapRefsInsideOneArray<false>(array, fromIndex, toIndex, count);
}
RUNTIME_NOTHROW void UpdateReturnRefStrict(ObjHeader** returnSlot, const ObjHeader* value) {
updateReturnRef<true>(returnSlot, value);
}
@@ -322,6 +322,8 @@ MODEL_VARIANTS(void, UpdateStackRef, ObjHeader** location, const ObjHeader* obje
MODEL_VARIANTS(void, UpdateHeapRef, ObjHeader** location, const ObjHeader* object);
MODEL_VARIANTS(void, UpdateHeapRefIfNull, ObjHeader** location, const ObjHeader* object);
MODEL_VARIANTS(void, UpdateReturnRef, ObjHeader** returnSlot, const ObjHeader* object);
MODEL_VARIANTS(void, UpdateHeapRefsInsideOneArray, const ArrayHeader* array, int fromIndex, int toIndex,
int count);
MODEL_VARIANTS(void, EnterFrame, ObjHeader** start, int parameters, int count);
MODEL_VARIANTS(void, LeaveFrame, ObjHeader** start, int parameters, int count);
+13 -8
View File
@@ -133,15 +133,20 @@ void Kotlin_Array_copyImpl(KConstRef thiz, KInt fromIndex,
ThrowArrayIndexOutOfBoundsException();
}
mutabilityCheck(destination);
if (fromIndex >= toIndex) {
for (int index = 0; index < count; index++) {
UpdateHeapRef(ArrayAddressOfElementAt(destinationArray, toIndex + index),
*ArrayAddressOfElementAt(array, fromIndex + index));
}
if (CurrentMemoryModel != MemoryModel::kExperimental && array == destinationArray &&
std::abs(fromIndex - toIndex) < count) {
UpdateHeapRefsInsideOneArray(array, fromIndex, toIndex, count);
} else {
for (int index = count - 1; index >= 0; index--) {
UpdateHeapRef(ArrayAddressOfElementAt(destinationArray, toIndex + index),
*ArrayAddressOfElementAt(array, fromIndex + index));
if (fromIndex >= toIndex) {
for (int index = 0; index < count; index++) {
UpdateHeapRef(ArrayAddressOfElementAt(destinationArray, toIndex + index),
*ArrayAddressOfElementAt(array, fromIndex + index));
}
} else {
for (int index = count - 1; index >= 0; index--) {
UpdateHeapRef(ArrayAddressOfElementAt(destinationArray, toIndex + index),
*ArrayAddressOfElementAt(array, fromIndex + index));
}
}
}
}
@@ -210,6 +210,8 @@ void ZeroStackRef(ObjHeader** location) RUNTIME_NOTHROW;
void UpdateStackRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW;
// Updates heap/static data location.
void UpdateHeapRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW;
// Updates heap/static data in one array.
void UpdateHeapRefsInsideOneArray(const ArrayHeader* array, int fromIndex, int toIndex, int count) RUNTIME_NOTHROW;
// Updates location if it is null, atomically.
void UpdateHeapRefIfNull(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW;
// Updates reference in return slot.
@@ -189,6 +189,11 @@ extern "C" ALWAYS_INLINE RUNTIME_NOTHROW void UpdateHeapRefIfNull(ObjHeader** lo
mm::CompareAndSwapHeapRef(location, nullptr, const_cast<ObjHeader*>(object), &result);
}
extern "C" ALWAYS_INLINE RUNTIME_NOTHROW void UpdateHeapRefsInsideOneArray(const ArrayHeader* array, int fromIndex,
int toIndex, int count) {
RuntimeFail("Only for legacy MM");
}
extern "C" ALWAYS_INLINE RUNTIME_NOTHROW void UpdateReturnRef(ObjHeader** returnSlot, const ObjHeader* object) {
mm::SetStackRef(returnSlot, const_cast<ObjHeader*>(object));
}
@@ -67,4 +67,8 @@ RUNTIME_NOTHROW void UpdateStackRef(ObjHeader** location, const ObjHeader* objec
UpdateStackRefRelaxed(location, object);
}
RUNTIME_NOTHROW void UpdateHeapRefsInsideOneArray(const ArrayHeader* array, int fromIndex, int toIndex, int count) {
UpdateHeapRefsInsideOneArrayRelaxed(array, fromIndex, toIndex, count);
}
} // extern "C"
@@ -67,4 +67,8 @@ RUNTIME_NOTHROW void UpdateStackRef(ObjHeader** location, const ObjHeader* objec
UpdateStackRefStrict(location, object);
}
RUNTIME_NOTHROW void UpdateHeapRefsInsideOneArray(const ArrayHeader* array, int fromIndex, int toIndex, int count) {
UpdateHeapRefsInsideOneArrayStrict(array, fromIndex, toIndex, count);
}
} // extern "C"