Add execute-inline/range instruction.

Like "execute-inline", this is an instruction generated by dexopt that
replaces a method invoke instruction.  It's useful for small, frequently
called methods in the core libs.

As with execute-inline, we allow at most 4 arguments, but with /range
we're no longer limited to the low 16 registers.

Also: marked execute-inline as being able to throw an exception.

Needed: native x86 implementation; support in JIT.

For bug 2268232.
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 911775c..942ac60 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -5412,6 +5412,7 @@
      * type, which is acceptable for any operation.
      */
     case OP_EXECUTE_INLINE:
+    case OP_EXECUTE_INLINE_RANGE:
     case OP_INVOKE_DIRECT_EMPTY:
     case OP_IGET_QUICK:
     case OP_IGET_WIDE_QUICK:
@@ -5446,7 +5447,6 @@
     case OP_UNUSED_EA:
     case OP_UNUSED_EB:
     case OP_BREAKPOINT:
-    case OP_UNUSED_EF:
     case OP_UNUSED_F1:
     case OP_UNUSED_FC:
     case OP_UNUSED_FD:
diff --git a/vm/analysis/DexOptimize.c b/vm/analysis/DexOptimize.c
index b3e2d40..369d707 100644
--- a/vm/analysis/DexOptimize.c
+++ b/vm/analysis/DexOptimize.c
@@ -64,9 +64,11 @@
 static bool optimizeMethod(Method* method, const InlineSub* inlineSubs);
 static void rewriteInstField(Method* method, u2* insns, OpCode newOpc);
 static bool rewriteVirtualInvoke(Method* method, u2* insns, OpCode newOpc);
-static bool rewriteDirectInvoke(Method* method, u2* insns);
+static bool rewriteEmptyDirectInvoke(Method* method, u2* insns);
 static bool rewriteExecuteInline(Method* method, u2* insns,
     MethodType methodType, const InlineSub* inlineSubs);
+static bool rewriteExecuteInlineRange(Method* method, u2* insns,
+    MethodType methodType, const InlineSub* inlineSubs);
 
 
 /*
@@ -1565,8 +1567,15 @@
             }
             break;
         case OP_INVOKE_VIRTUAL_RANGE:
-            if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_VIRTUAL_QUICK_RANGE))
-                return false;
+            if (!rewriteExecuteInlineRange(method, insns, METHOD_VIRTUAL,
+                    inlineSubs))
+            {
+                if (!rewriteVirtualInvoke(method, insns,
+                        OP_INVOKE_VIRTUAL_QUICK_RANGE))
+                {
+                    return false;
+                }
+            }
             break;
         case OP_INVOKE_SUPER:
             if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK))
@@ -1580,13 +1589,20 @@
         case OP_INVOKE_DIRECT:
             if (!rewriteExecuteInline(method, insns, METHOD_DIRECT, inlineSubs))
             {
-                if (!rewriteDirectInvoke(method, insns))
+                if (!rewriteEmptyDirectInvoke(method, insns))
                     return false;
             }
             break;
+        case OP_INVOKE_DIRECT_RANGE:
+            rewriteExecuteInlineRange(method, insns, METHOD_DIRECT, inlineSubs);
+            break;
+
         case OP_INVOKE_STATIC:
             rewriteExecuteInline(method, insns, METHOD_STATIC, inlineSubs);
             break;
+        case OP_INVOKE_STATIC_RANGE:
+            rewriteExecuteInlineRange(method, insns, METHOD_STATIC, inlineSubs);
+            break;
 
         default:
             // ignore this instruction
@@ -2107,7 +2123,7 @@
  * This must only be used when the invoked method does nothing and has
  * no return value (the latter being very important for verification).
  */
-static bool rewriteDirectInvoke(Method* method, u2* insns)
+static bool rewriteEmptyDirectInvoke(Method* method, u2* insns)
 {
     ClassObject* clazz = method->clazz;
     Method* calledMethod;
@@ -2226,6 +2242,7 @@
 
     return resMethod;
 }
+
 /*
  * See if the method being called can be rewritten as an inline operation.
  * Works for invoke-virtual, invoke-direct, and invoke-static.
@@ -2276,3 +2293,42 @@
     return false;
 }
 
+/*
+ * See if the method being called can be rewritten as an inline operation.
+ * Works for invoke-virtual/range, invoke-direct/range, and invoke-static/range.
+ *
+ * Returns "true" if we replace it.
+ */
+static bool rewriteExecuteInlineRange(Method* method, u2* insns,
+    MethodType methodType, const InlineSub* inlineSubs)
+{
+    ClassObject* clazz = method->clazz;
+    Method* calledMethod;
+    u2 methodIdx = insns[1];
+
+    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
+    if (calledMethod == NULL) {
+        LOGV("+++ DexOpt inline/range: can't find %d\n", methodIdx);
+        return false;
+    }
+
+    while (inlineSubs->method != NULL) {
+        if (inlineSubs->method == calledMethod) {
+            assert((insns[0] & 0xff) == OP_INVOKE_DIRECT_RANGE ||
+                   (insns[0] & 0xff) == OP_INVOKE_STATIC_RANGE ||
+                   (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE);
+            insns[0] = (insns[0] & 0xff00) | (u2) OP_EXECUTE_INLINE_RANGE;
+            insns[1] = (u2) inlineSubs->inlineIdx;
+
+            //LOGI("DexOpt: execute-inline/range %s.%s --> %s.%s\n",
+            //    method->clazz->descriptor, method->name,
+            //    calledMethod->clazz->descriptor, calledMethod->name);
+            return true;
+        }
+
+        inlineSubs++;
+    }
+
+    return false;
+}
+
diff --git a/vm/analysis/RegisterMap.c b/vm/analysis/RegisterMap.c
index bc314a2..758ebea 100644
--- a/vm/analysis/RegisterMap.c
+++ b/vm/analysis/RegisterMap.c
@@ -3000,6 +3000,7 @@
      * quickened.  This is feasible but not currently supported.
      */
     case OP_EXECUTE_INLINE:
+    case OP_EXECUTE_INLINE_RANGE:
     case OP_INVOKE_DIRECT_EMPTY:
     case OP_IGET_QUICK:
     case OP_IGET_WIDE_QUICK:
@@ -3036,7 +3037,6 @@
     case OP_UNUSED_EB:
     case OP_BREAKPOINT:
     case OP_UNUSED_ED:
-    case OP_UNUSED_EF:
     case OP_UNUSED_F1:
     case OP_UNUSED_FC:
     case OP_UNUSED_FD: