Codegen support for debugger

Add the ability to generate code with support for debugging.
This involves generating a callout to an equivalent of the
old "updateDebugger()" before each Dalvik opcode, method
entry and method exit.

The added code is fairly compact - 8 bytes per Dalvik opcode,
plus 4 additional bytes per safe point.

I dislike the idea of always making this call, so I'm reusing
the dedicated register rSUSPEND to hold the address of the callout.
rSUSPEND is normally used to reduce the frequency of full suspend
checks, but when debugging this isn't necessary - allowing
us to resuse this register to hold the address of the callout.
If it is non-null we make the callout, otherwise we continue.  I refresh
this register from a slot in the Thread structure on method entry
and also following the return of taken suspend checks.  In this way,
the debugger has the ability to control updates on a per-thread basis,
and the performance penalty is greatly reduced for threads that don't
have any pending debugger requests.  Once the debugger attaches,
it would suspend all threads, walk through the thread list, set
thread->pUpdateDebuggerFromCode to art_update_debugger and then
turn everything loose.

One thing I'm not doing, though, is debugger updates before and after
calls to native methods.  This is something that will have to be done
by the stubs, because I don't know which invokes are native.  Oh, and
there will also need to be an artUpdateDebugger call on the exception
path.

I'm passing the DalvikPC to the stub, and am using special
codes (-1 and -2) to denote method entry and exit.  The stub
recovers the current Method* and Thread* and passes them on to
artUpdateDebugger().

When we're compiling in this special mode, all optimizations which
might result in code motion or suppressed load/store of a Dalvik
register are turned off.  No register promotion is done, so everything
will be in its home location.

Change-Id: Iaf66f4d0d094a1699269d0a1ad1ed33e7613aef8
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 2a3b807..db51fb8 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -574,6 +574,29 @@
     }
 }
 
+/*
+ * Generate callout to updateDebugger. Note: genIT will automatically
+ * create a scheduling barrier, which we need to prevent code motion that
+ * might confuse the debugger.  Note: Return registers r0/r1 are
+ * handled specially during code generation following function calls.
+ * Typically, temp registers are not live between opcodes, but we keep
+ * r0/r1 live following invokes, where they are consumed by the immediately
+ * following op_move_result_xxx.  Thus, we must preserve and restore r0/r1
+ * when making a call to update the debugger.  This is handled by the stub.
+ */
+STATIC void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset)
+{
+    // Following DCHECK verifies that dPC is in range of single load immediate
+    DCHECK((offset == DEBUGGER_METHOD_ENTRY) ||
+           (offset == DEBUGGER_METHOD_EXIT) || ((offset & 0xffff) == offset));
+    oatClobberCalleeSave(cUnit);
+    opRegImm(cUnit, kOpCmp, rSUSPEND, 0);
+    genIT(cUnit, kArmCondNe, "T");
+    loadConstant(cUnit, r2, offset);     // arg2 <- Entry code
+    opReg(cUnit, kOpBlx, rSUSPEND);
+    oatFreeTemp(cUnit, r2);
+}
+
 STATIC void genConstString(CompilationUnit* cUnit, MIR* mir,
                            RegLocation rlDest, RegLocation rlSrc)
 {
@@ -875,7 +898,8 @@
     oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
     // Keep special registers from being allocated
     for (int i = 0; i < numReserved; i++) {
-        if (NO_SUSPEND && (reservedRegs[i] == rSUSPEND)) {
+        if (NO_SUSPEND && !cUnit->genDebugger &&
+            (reservedRegs[i] == rSUSPEND)) {
             //To measure cost of suspend check
             continue;
         }
@@ -1738,8 +1762,15 @@
         return;
     }
     oatFlushAllRegs(cUnit);
-    newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1);
-    ArmLIR* branch = opCondBranch(cUnit, kArmCondEq);
+    ArmLIR* branch;
+    if (cUnit->genDebugger) {
+        // If generating code for the debugger, always check for suspension
+        branch = genUnconditionalBranch(cUnit, NULL);
+    } else {
+        // In non-debug case, only check periodically
+        newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1);
+        branch = opCondBranch(cUnit, kArmCondEq);
+    }
     ArmLIR* retLab = newLIR0(cUnit, kArmPseudoTargetLabel);
     retLab->defMask = ENCODE_ALL;
     ArmLIR* target = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);