Added "dexopt for SMP" flag.

Currently, dexopt always runs on the target device, which means that
decisions about whether or not to convert certain opcodes to SMP-safe
variants could be made based on #ifdefs.

Since we are planning to run dexopt on the host, we need to be able
to configure SMP-mode independently.  This change adds a global variable
that the dexopt code can check.

There is currently no command-line argument to set this, since it will
be set by "dexopt" rather than "dalvikvm", and the exact method of
launching dexopt from the host build is still mildly TBD.

Bug 2981136.

Change-Id: If20aa6f513896fd8b35394388eaca6214f0449a7
diff --git a/vm/Globals.h b/vm/Globals.h
index 93300f5..3c98872 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -118,6 +118,8 @@
     DexOptimizerMode    dexOptMode;
     DexClassVerifyMode  classVerifyMode;
 
+    bool        dexOptForSmp;
+
     /*
      * GC option flags.
      */
diff --git a/vm/Init.c b/vm/Init.c
index 1a3d359..2b21130 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -1067,6 +1067,12 @@
 #else
     gDvm.executionMode = kExecutionModeInterpFast;
 #endif
+
+    /*
+     * SMP support is a compile-time define, but we may want to have
+     * dexopt target a differently-configured device.
+     */
+    gDvm.dexOptForSmp = (ANDROID_SMP != 0);
 }
 
 
diff --git a/vm/analysis/Optimize.c b/vm/analysis/Optimize.c
index 4ac19f3..7ad4e45 100644
--- a/vm/analysis/Optimize.c
+++ b/vm/analysis/Optimize.c
@@ -191,6 +191,7 @@
 
         inst = *insns & 0xff;
 
+        /* "essential" substitutions, always checked */
         switch (inst) {
         case OP_IGET:
         case OP_IGET_BOOLEAN:
@@ -198,7 +199,7 @@
         case OP_IGET_CHAR:
         case OP_IGET_SHORT:
             quickOpc = OP_IGET_QUICK;
-            if (ANDROID_SMP != 0)
+            if (gDvm.dexOptForSmp)
                 volatileOpc = OP_IGET_VOLATILE;
             goto rewrite_inst_field;
         case OP_IGET_WIDE:
@@ -207,7 +208,7 @@
             goto rewrite_inst_field;
         case OP_IGET_OBJECT:
             quickOpc = OP_IGET_OBJECT_QUICK;
-            if (ANDROID_SMP != 0)
+            if (gDvm.dexOptForSmp)
                 volatileOpc = OP_IGET_OBJECT_VOLATILE;
             goto rewrite_inst_field;
         case OP_IPUT:
@@ -216,7 +217,7 @@
         case OP_IPUT_CHAR:
         case OP_IPUT_SHORT:
             quickOpc = OP_IPUT_QUICK;
-            if (ANDROID_SMP != 0)
+            if (gDvm.dexOptForSmp)
                 volatileOpc = OP_IPUT_VOLATILE;
             goto rewrite_inst_field;
         case OP_IPUT_WIDE:
@@ -225,7 +226,7 @@
             goto rewrite_inst_field;
         case OP_IPUT_OBJECT:
             quickOpc = OP_IPUT_OBJECT_QUICK;
-            if (ANDROID_SMP != 0)
+            if (gDvm.dexOptForSmp)
                 volatileOpc = OP_IPUT_OBJECT_VOLATILE;
 rewrite_inst_field:
             if (essentialOnly)
@@ -234,28 +235,6 @@
                 rewriteInstField(method, insns, quickOpc, volatileOpc);
             break;
 
-#if ANDROID_SMP != 0
-        case OP_SGET:
-        case OP_SGET_BOOLEAN:
-        case OP_SGET_BYTE:
-        case OP_SGET_CHAR:
-        case OP_SGET_SHORT:
-            volatileOpc = OP_SGET_VOLATILE;
-            goto rewrite_static_field;
-        case OP_SGET_OBJECT:
-            volatileOpc = OP_SGET_OBJECT_VOLATILE;
-            goto rewrite_static_field;
-        case OP_SPUT:
-        case OP_SPUT_BOOLEAN:
-        case OP_SPUT_BYTE:
-        case OP_SPUT_CHAR:
-        case OP_SPUT_SHORT:
-            volatileOpc = OP_SPUT_VOLATILE;
-            goto rewrite_static_field;
-        case OP_SPUT_OBJECT:
-            volatileOpc = OP_SPUT_OBJECT_VOLATILE;
-            goto rewrite_static_field;
-#endif
         case OP_SGET_WIDE:
             volatileOpc = OP_SGET_WIDE_VOLATILE;
             goto rewrite_static_field;
@@ -264,12 +243,44 @@
 rewrite_static_field:
             rewriteStaticField(method, insns, volatileOpc);
             break;
-
         default:
-            /* not one of the "essential" replacements; check for more */
             notMatched = true;
+            break;
         }
 
+        if (notMatched && gDvm.dexOptForSmp) {
+            /* additional "essential" substitutions for an SMP device */
+            switch (inst) {
+            case OP_SGET:
+            case OP_SGET_BOOLEAN:
+            case OP_SGET_BYTE:
+            case OP_SGET_CHAR:
+            case OP_SGET_SHORT:
+                volatileOpc = OP_SGET_VOLATILE;
+                goto rewrite_static_field2;
+            case OP_SGET_OBJECT:
+                volatileOpc = OP_SGET_OBJECT_VOLATILE;
+                goto rewrite_static_field2;
+            case OP_SPUT:
+            case OP_SPUT_BOOLEAN:
+            case OP_SPUT_BYTE:
+            case OP_SPUT_CHAR:
+            case OP_SPUT_SHORT:
+                volatileOpc = OP_SPUT_VOLATILE;
+                goto rewrite_static_field2;
+            case OP_SPUT_OBJECT:
+                volatileOpc = OP_SPUT_OBJECT_VOLATILE;
+rewrite_static_field2:
+                rewriteStaticField(method, insns, volatileOpc);
+                notMatched = false;
+                break;
+            default:
+                assert(notMatched);
+                break;
+            }
+        }
+
+        /* non-essential substitutions */
         if (notMatched && !essentialOnly) {
             switch (inst) {
             case OP_INVOKE_VIRTUAL: