Introduce more compact ReadBarrierMark slow-paths.

Replace entry point ReadBarrierMark with 32
ReadBarrierMarkRegX entry points, using register
number X as input and output (instead of the standard
runtime calling convention) to save two moves in Baker's
read barrier mark slow-path code.

Test: ART host and target (ARM, ARM64) tests.
Bug: 29506760
Bug: 12687968
Change-Id: I73cfb82831cf040b8b018e984163c865cc44ed87
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 6234f0f..e75fecb 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -1908,7 +1908,10 @@
     UNREACHABLE
 END_FUNCTION art_nested_signal_return
 
-DEFINE_FUNCTION art_quick_read_barrier_mark
+// Call the ReadBarrierMark entry point, getting input and returning
+// result through EAX (register 0), following the standard runtime
+// calling convention.
+DEFINE_FUNCTION art_quick_read_barrier_mark_reg00
     subl LITERAL(8), %esp            // alignment padding
     CFI_ADJUST_CFA_OFFSET(8)
     PUSH eax                         // pass arg1 - obj
@@ -1916,7 +1919,38 @@
     addl LITERAL(12), %esp           // pop argument and remove padding
     CFI_ADJUST_CFA_OFFSET(-12)
     ret
-END_FUNCTION art_quick_read_barrier_mark
+END_FUNCTION art_quick_read_barrier_mark_reg00
+
+// Create a function `name` calling the ReadBarrier::Mark routine,
+// getting its argument and returning its result through register
+// `reg`, thus following a non-standard runtime calling convention:
+// - `reg` is used to pass the (sole) argument of this function
+//   (instead of EAX);
+// - `reg` is used to return the result of this function (instead of EAX);
+// - EAX is treated like a normal (non-argument) caller-save register;
+// - everything else is the same as in the standard runtime calling
+//   convention (e.g. same callee-save registers).
+MACRO2(READ_BARRIER_MARK_REG, name, reg)
+    DEFINE_FUNCTION VAR(name)
+    subl LITERAL(8), %esp            // alignment padding
+    CFI_ADJUST_CFA_OFFSET(8)
+    PUSH RAW_VAR(reg)                // pass arg1 - obj from `reg`
+    call SYMBOL(artReadBarrierMark)  // artReadBarrierMark(obj)
+    movl %eax, REG_VAR(reg)          // return result into `reg`
+    addl LITERAL(12), %esp           // pop argument and remove padding
+    CFI_ADJUST_CFA_OFFSET(-12)
+    ret
+    END_FUNCTION VAR(name)
+END_MACRO
+
+READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg01, ecx
+READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg02, edx
+READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg03, ebx
+READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg05, ebp
+// Note: There is no art_quick_read_barrier_mark_reg04, as register 4 (ESP)
+// cannot be used to pass arguments.
+READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg06, esi
+READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg07, edi
 
 DEFINE_FUNCTION art_quick_read_barrier_slow
     PUSH edx                         // pass arg3 - offset