Add an ImtConflictTable to better resolve IMT conflicts.
- Attach a ImtConflictTable to conflict runtime ArtMethod.
- Initially 0, a new one will be created at the first hit of
the conflict method.
- If the assembly code does not find a target method in the table,
we will create a new one again, copying the data from the previous
table and adding the new mapping.
Implemented for arm/arm64/x86/x64.
bug:27556801
bug:24769046
Change-Id: Ie74d1c77cf73d451a1142bdc5e3683f9f84bb4e7
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 82ec0b7..5a901f1 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -1225,11 +1225,35 @@
END art_quick_proxy_invoke_handler
/*
- * Called to resolve an imt conflict. r12 is a hidden argument that holds the target method's
- * dex method index.
+ * Called to resolve an imt conflict.
+ * r0 is the conflict ArtMethod.
+ * r12 is a hidden argument that holds the target interface method's dex method index.
+ *
+ * Note that this stub writes to r0, r4, and r12.
*/
ENTRY art_quick_imt_conflict_trampoline
- mov r0, r12
+ ldr r4, [sp, #0] // Load referrer
+ ldr r4, [r4, #ART_METHOD_DEX_CACHE_METHODS_OFFSET_32] // Load dex cache methods array
+ ldr r12, [r4, r12, lsl #POINTER_SIZE_SHIFT] // Load interface method
+ ldr r0, [r0, #ART_METHOD_JNI_OFFSET_32] // Load ImtConflictTable
+ ldr r4, [r0] // Load first entry in ImtConflictTable.
+.Limt_table_iterate:
+ cmp r4, r12
+ // Branch if found. Benchmarks have shown doing a branch here is better.
+ beq .Limt_table_found
+ // If the entry is null, the interface method is not in the ImtConflictTable.
+ cbz r4, .Lconflict_trampoline
+ // Iterate over the entries of the ImtConflictTable.
+ ldr r4, [r0, #(2 * __SIZEOF_POINTER__)]!
+ b .Limt_table_iterate
+.Limt_table_found:
+ // We successuflly hit an entry in the table. Load the target method
+ // and jump to it.
+ ldr r0, [r0, #__SIZEOF_POINTER__]
+ ldr pc, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]
+.Lconflict_trampoline:
+ // Call the runtime stub to populate the ImtConflictTable and jump to the
+ // resolved method.
INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline
END art_quick_imt_conflict_trampoline