am 381868f3: (-s ours) am 840d233c: am 800e4320: am 63c34b5e: am 68719a17: (-s ours) Reconcile with jb-mr1-release - do not merge

* commit '381868f347d413a671a6ad9c0af64d258a060b99':
diff --git a/dexlist/Android.mk b/dexlist/Android.mk
index 55602dd..279c82b 100644
--- a/dexlist/Android.mk
+++ b/dexlist/Android.mk
@@ -45,6 +45,6 @@
 LOCAL_SRC_FILES := $(dexdump_src_files)
 LOCAL_C_INCLUDES := $(dexdump_c_includes)
 LOCAL_SHARED_LIBRARIES := $(dexdump_shared_libraries)
-LOCAL_STATIC_LIBRARIES := $(dexdump_static_libraries) libcutils
+LOCAL_STATIC_LIBRARIES := $(dexdump_static_libraries) libcutils liblog
 LOCAL_LDLIBS += -lpthread -lz
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/dx/junit-tests/Android.mk b/dx/junit-tests/Android.mk
index 3f2c611..ee5e31b 100644
--- a/dx/junit-tests/Android.mk
+++ b/dx/junit-tests/Android.mk
@@ -4,6 +4,5 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_JAVA_LIBRARIES := dx junit
-LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE:= dx-tests
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tests/302-float-conversion/expected.txt b/tests/302-float-conversion/expected.txt
new file mode 100644
index 0000000..6939a5c
--- /dev/null
+++ b/tests/302-float-conversion/expected.txt
@@ -0,0 +1 @@
+Result is as expected
diff --git a/tests/302-float-conversion/info.txt b/tests/302-float-conversion/info.txt
new file mode 100644
index 0000000..2b8bc21
--- /dev/null
+++ b/tests/302-float-conversion/info.txt
@@ -0,0 +1,4 @@
+Tests whether constant conversions of double values to long values are
+properly handled by the VM. For example, x86 systems using the x87 stack
+ should not overflow under constant conversions.
+
diff --git a/tests/302-float-conversion/src/Main.java b/tests/302-float-conversion/src/Main.java
new file mode 100644
index 0000000..dc512c5
--- /dev/null
+++ b/tests/302-float-conversion/src/Main.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+    static final long NUM_ITERATIONS = 50000;
+    static volatile double negInfinity = Double.NEGATIVE_INFINITY;
+
+    public static void main(String args[]) {
+
+        long sumInf = 0;
+        long sumRes = 0;
+
+        for (long i = 0 ; i < NUM_ITERATIONS ; i++) {
+            //Every second iteration, sumInf becomes 0
+            sumInf += (long) negInfinity;
+
+            //Some extra work for compilers to make this
+            //loop seem important
+            if (sumInf == Long.MIN_VALUE) {
+                sumRes++;
+            }
+        }
+
+        if (sumRes == NUM_ITERATIONS / 2) {
+            System.out.println("Result is as expected");
+        } else {
+            System.out.println("Conversions failed over " + NUM_ITERATIONS + " iterations");
+        }
+    }
+}
diff --git a/vm/Android.mk b/vm/Android.mk
index 0af62e8..c9b510b 100644
--- a/vm/Android.mk
+++ b/vm/Android.mk
@@ -65,6 +65,8 @@
 include $(LOCAL_PATH)/ReconfigureDvm.mk
 LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT \
                 -DWITH_JIT_TUNING $(target_smp_flag)
+# TODO: split out the asflags.
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
 LOCAL_MODULE := libdvm_assert
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/vm/Init.cpp b/vm/Init.cpp
index 11d884e..9169a5d 100644
--- a/vm/Init.cpp
+++ b/vm/Init.cpp
@@ -28,6 +28,9 @@
 #include <linux/fs.h>
 #include <cutils/fs.h>
 #include <unistd.h>
+#ifdef HAVE_ANDROID_OS
+#include <sys/prctl.h>
+#endif
 
 #include "Dalvik.h"
 #include "test/Test.h"
@@ -1629,6 +1632,33 @@
     return true;
 }
 
+/*
+ * Copied and modified slightly from system/core/toolbox/mount.c
+ */
+static std::string getMountsDevDir(const char *arg)
+{
+    char mount_dev[256];
+    char mount_dir[256];
+    int match;
+
+    FILE *fp = fopen("/proc/self/mounts", "r");
+    if (fp == NULL) {
+        ALOGE("Could not open /proc/self/mounts: %s", strerror(errno));
+        return "";
+    }
+
+    while ((match = fscanf(fp, "%255s %255s %*s %*s %*d %*d\n", mount_dev, mount_dir)) != EOF) {
+        mount_dev[255] = 0;
+        mount_dir[255] = 0;
+        if (match == 2 && (strcmp(arg, mount_dir) == 0)) {
+            fclose(fp);
+            return mount_dev;
+        }
+    }
+
+    fclose(fp);
+    return "";
+}
 
 /*
  * Do zygote-mode-only initialization.
@@ -1664,6 +1694,40 @@
         }
     }
 
+    // Mark /system as NOSUID | NODEV
+    const char* android_root = getenv("ANDROID_ROOT");
+
+    if (android_root == NULL) {
+        SLOGE("environment variable ANDROID_ROOT does not exist?!?!");
+        return -1;
+    }
+
+    std::string mountDev(getMountsDevDir(android_root));
+    if (mountDev.empty()) {
+        SLOGE("Unable to find mount point for %s", android_root);
+        return -1;
+    }
+
+    if (mount(mountDev.c_str(), android_root, "none",
+            MS_REMOUNT | MS_NOSUID | MS_NODEV | MS_RDONLY | MS_BIND, NULL) == -1) {
+        SLOGE("Remount of %s failed: %s", android_root, strerror(errno));
+        return -1;
+    }
+
+#ifdef HAVE_ANDROID_OS
+    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+        if (errno == EINVAL) {
+            SLOGW("PR_SET_NO_NEW_PRIVS failed. "
+                  "Is your kernel compiled correctly?: %s", strerror(errno));
+            // Don't return -1 here, since it's expected that not all
+            // kernels will support this option.
+        } else {
+            SLOGW("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
+            return -1;
+        }
+    }
+#endif
+
     return true;
 }
 
diff --git a/vm/InitRefs.cpp b/vm/InitRefs.cpp
index d8f0697..9c1e1cb 100644
--- a/vm/InitRefs.cpp
+++ b/vm/InitRefs.cpp
@@ -332,7 +332,7 @@
           "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;"
           "Ljava/lang/String;I)V" },
         { &gDvm.methJavaNioDirectByteBuffer_init, "Ljava/nio/DirectByteBuffer;",
-          "(II)V" },
+          "(JI)V" },
         { &gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
           "Lorg/apache/harmony/lang/annotation/AnnotationMember;",
           "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V" },
diff --git a/vm/Jni.cpp b/vm/Jni.cpp
index f235835..e571ad8 100644
--- a/vm/Jni.cpp
+++ b/vm/Jni.cpp
@@ -2739,7 +2739,7 @@
     jobject result = addLocalReference(ts.self(), newObj);
     JValue unused;
     dvmCallMethod(ts.self(), gDvm.methJavaNioDirectByteBuffer_init,
-            newObj, &unused, (jint) address, (jint) capacity);
+            newObj, &unused, (jlong) address, (jint) capacity);
     if (dvmGetException(ts.self()) != NULL) {
         deleteLocalReference(ts.self(), result);
         return NULL;
diff --git a/vm/SignalCatcher.cpp b/vm/SignalCatcher.cpp
index a4beb6b..d4302aa 100644
--- a/vm/SignalCatcher.cpp
+++ b/vm/SignalCatcher.cpp
@@ -191,7 +191,7 @@
             ALOGE("Unable to open stack trace file '%s': %s",
                 gDvm.stackTraceFile, strerror(errno));
         } else {
-            ssize_t actual = write(fd, traceBuf, traceLen);
+            ssize_t actual = TEMP_FAILURE_RETRY(write(fd, traceBuf, traceLen));
             if (actual != (ssize_t) traceLen) {
                 ALOGE("Failed to write stack traces to %s (%d of %zd): %s",
                     gDvm.stackTraceFile, (int) actual, traceLen,
diff --git a/vm/Thread.cpp b/vm/Thread.cpp
index ded6f0f..9671b84 100644
--- a/vm/Thread.cpp
+++ b/vm/Thread.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+
 /*
  * Thread support.
  */
@@ -27,13 +29,10 @@
 #include <sys/resource.h>
 #include <sys/mman.h>
 #include <signal.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 
-#ifdef HAVE_ANDROID_OS
-#include <dirent.h>
-#endif
-
 #if defined(HAVE_PRCTL)
 #include <sys/prctl.h>
 #endif
@@ -42,6 +41,7 @@
 #include "interp/Jit.h"         // need for self verification
 #endif
 
+ #include <cutils/trace.h>
 
 /* desktop Linux needs a little help with gettid() */
 #if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
@@ -1311,10 +1311,10 @@
          * resource limits.  VirtualMachineError is probably too severe,
          * so use OutOfMemoryError.
          */
-        ALOGE("pthread_create (stack size %d bytes) failed: %s", stackSize, strerror(cc));
 
         dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread, NULL);
 
+        ALOGE("pthread_create (stack size %d bytes) failed: %s", stackSize, strerror(cc));
         dvmThrowExceptionFmt(gDvm.exOutOfMemoryError,
                              "pthread_create (stack size %d bytes) failed: %s",
                              stackSize, strerror(cc));
@@ -2857,6 +2857,7 @@
         ThreadStatus oldStatus = self->status;      /* should be RUNNING */
         self->status = THREAD_SUSPENDED;
 
+        ATRACE_BEGIN("DVM Suspend");
         while (self->suspendCount != 0) {
             /*
              * Wait for wakeup signal, releasing lock.  The act of releasing
@@ -2866,6 +2867,7 @@
             dvmWaitCond(&gDvm.threadSuspendCountCond,
                     &gDvm.threadSuspendCountLock);
         }
+        ATRACE_END();
         assert(self->suspendCount == 0 && self->dbgSuspendCount == 0);
         self->status = oldStatus;
         LOG_THREAD("threadid=%d: self-reviving, status=%d",
@@ -3272,6 +3274,36 @@
     }
 }
 
+static bool shouldShowNativeStack(Thread* thread) {
+    // In native code somewhere in the VM? That's interesting.
+    if (thread->status == THREAD_VMWAIT) {
+        return true;
+    }
+
+    // In an Object.wait variant? That's not interesting.
+    if (thread->status == THREAD_TIMED_WAIT || thread->status == THREAD_WAIT) {
+        return false;
+    }
+
+    // The Signal Catcher thread? That's not interesting.
+    if (thread->status == THREAD_RUNNING) {
+        return false;
+    }
+
+    // In some other native method? That's interesting.
+    // We don't just check THREAD_NATIVE because native methods will be in
+    // state THREAD_SUSPENDED if they're calling back into the VM, or THREAD_MONITOR
+    // if they're blocked on a monitor, or one of the thread-startup states if
+    // it's early enough in their life cycle (http://b/7432159).
+    u4* fp = thread->interpSave.curFrame;
+    if (fp == NULL) {
+        // The thread has no managed frames, so native frames are all there is.
+        return true;
+    }
+    const Method* currentMethod = SAVEAREA_FROM_FP(fp)->method;
+    return currentMethod != NULL && dvmIsNativeMethod(currentMethod);
+}
+
 /*
  * Print information about the specified thread.
  *
@@ -3350,16 +3382,7 @@
 
     dumpSchedStat(target, thread->systemTid);
 
-    /*
-     * Grab the native stack, if possible.
-     *
-     * The native thread is still running, even if the Dalvik side is
-     * suspended.  This means the thread can move itself out of NATIVE state
-     * while we're in here, shifting to SUSPENDED after a brief moment at
-     * RUNNING.  At that point the native stack isn't all that interesting,
-     * though, so if we fail to dump it there's little lost.
-     */
-    if (thread->status == THREAD_NATIVE || thread->status == THREAD_VMWAIT) {
+    if (shouldShowNativeStack(thread)) {
         dvmDumpNativeStack(target, thread->systemTid);
     }
 
@@ -3490,10 +3513,7 @@
     }
 
 #ifdef HAVE_ANDROID_OS
-    char path[64];
-    snprintf(path, sizeof(path), "/proc/%d/task", getpid());
-
-    DIR* d = opendir(path);
+    DIR* d = opendir("/proc/self/task");
     if (d != NULL) {
         dirent* entry = NULL;
         bool first = true;
diff --git a/vm/alloc/Heap.cpp b/vm/alloc/Heap.cpp
index 9bbe8a5..4a8d165 100644
--- a/vm/alloc/Heap.cpp
+++ b/vm/alloc/Heap.cpp
@@ -13,6 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#define ATRACE_TAG ATRACE_TAG_DALVIK
+
 /*
  * Garbage-collecting memory allocator.
  */
@@ -31,6 +34,8 @@
 #include <limits.h>
 #include <errno.h>
 
+#include <cutils/trace.h>
+
 static const GcSpec kGcForMallocSpec = {
     true,  /* isPartial */
     false,  /* isConcurrent */
@@ -456,9 +461,23 @@
         return;
     }
 
+    // Trace the beginning of the top-level GC.
+    if (spec == GC_FOR_MALLOC) {
+        ATRACE_BEGIN("GC (alloc)");
+    } else if (spec == GC_CONCURRENT) {
+        ATRACE_BEGIN("GC (concurrent)");
+    } else if (spec == GC_EXPLICIT) {
+        ATRACE_BEGIN("GC (explicit)");
+    } else if (spec == GC_BEFORE_OOM) {
+        ATRACE_BEGIN("GC (before OOM)");
+    } else {
+        ATRACE_BEGIN("GC (unknown)");
+    }
+
     gcHeap->gcRunning = true;
 
     rootStart = dvmGetRelativeTimeMsec();
+    ATRACE_BEGIN("GC: Threads Suspended"); // Suspend A
     dvmSuspendAllThreads(SUSPEND_FOR_GC);
 
     /*
@@ -478,6 +497,8 @@
     /* Set up the marking context.
      */
     if (!dvmHeapBeginMarkStep(spec->isPartial)) {
+        ATRACE_END(); // Suspend A
+        ATRACE_END(); // Top-level GC
         LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting");
         dvmAbort();
     }
@@ -504,6 +525,7 @@
         dvmClearCardTable();
         dvmUnlockHeap();
         dvmResumeAllThreads(SUSPEND_FOR_GC);
+        ATRACE_END(); // Suspend A
         rootEnd = dvmGetRelativeTimeMsec();
     }
 
@@ -521,6 +543,7 @@
          */
         dirtyStart = dvmGetRelativeTimeMsec();
         dvmLockHeap();
+        ATRACE_BEGIN("GC: Threads Suspended"); // Suspend B
         dvmSuspendAllThreads(SUSPEND_FOR_GC);
         /*
          * As no barrier intercepts root updates, we conservatively
@@ -582,6 +605,7 @@
     if (spec->isConcurrent) {
         dvmUnlockHeap();
         dvmResumeAllThreads(SUSPEND_FOR_GC);
+        ATRACE_END(); // Suspend B
         dirtyEnd = dvmGetRelativeTimeMsec();
     }
     dvmHeapSweepUnmarkedObjects(spec->isPartial, spec->isConcurrent,
@@ -622,6 +646,7 @@
 
     if (!spec->isConcurrent) {
         dvmResumeAllThreads(SUSPEND_FOR_GC);
+        ATRACE_END(); // Suspend A
         dirtyEnd = dvmGetRelativeTimeMsec();
         /*
          * Restore the original thread scheduling priority if it was
@@ -675,6 +700,8 @@
         LOGD_HEAP("Dumping native heap to DDM");
         dvmDdmSendHeapSegments(false, true);
     }
+
+    ATRACE_END(); // Top-level GC
 }
 
 /*
@@ -699,6 +726,7 @@
  */
 bool dvmWaitForConcurrentGcToComplete()
 {
+    ATRACE_BEGIN("GC: Wait For Concurrent");
     bool waited = gDvm.gcHeap->gcRunning;
     Thread *self = dvmThreadSelf();
     assert(self != NULL);
@@ -712,5 +740,6 @@
     if (end - start > 0) {
         ALOGD("WAIT_FOR_CONCURRENT_GC blocked %ums", end - start);
     }
+    ATRACE_END();
     return waited;
 }
diff --git a/vm/alloc/HeapSource.cpp b/vm/alloc/HeapSource.cpp
index ee40af82..93cdd2f 100644
--- a/vm/alloc/HeapSource.cpp
+++ b/vm/alloc/HeapSource.cpp
@@ -457,6 +457,14 @@
             dvmWaitCond(&gHs->gcThreadCond, &gHs->gcThreadMutex);
         }
 
+        // Many JDWP requests cause allocation. We can't take the heap lock and wait to
+        // transition to runnable so we can start a GC if a debugger is connected, because
+        // we don't know that the JDWP thread isn't about to allocate and require the
+        // heap lock itself, leading to deadlock. http://b/8191824.
+        if (gDvm.debuggerConnected) {
+            continue;
+        }
+
         dvmLockHeap();
         /*
          * Another thread may have started a concurrent garbage
diff --git a/vm/compiler/Compiler.cpp b/vm/compiler/Compiler.cpp
index cdd62cc..188027f 100644
--- a/vm/compiler/Compiler.cpp
+++ b/vm/compiler/Compiler.cpp
@@ -448,7 +448,7 @@
     pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
     if (!pJitProfTable) {
         ALOGE("jit prof table allocation failed");
-        free(pJitProfTable);
+        free(pJitTable);
         dvmUnlockMutex(&gDvmJit.tableLock);
         goto fail;
     }
@@ -464,6 +464,8 @@
                              calloc(1, sizeof(*pJitTraceProfCounters));
     if (!pJitTraceProfCounters) {
         ALOGE("jit trace prof counters allocation failed");
+        free(pJitTable);
+        free(pJitProfTable);
         dvmUnlockMutex(&gDvmJit.tableLock);
         goto fail;
     }
diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.cpp b/vm/compiler/codegen/arm/Thumb2/Factory.cpp
index c3c3712..b9265e8 100644
--- a/vm/compiler/codegen/arm/Thumb2/Factory.cpp
+++ b/vm/compiler/codegen/arm/Thumb2/Factory.cpp
@@ -727,7 +727,8 @@
             loadPcRel->operands[1] = r15pc;
             setupResourceMasks(loadPcRel);
             setMemRefType(loadPcRel, true, kLiteral);
-            loadPcRel->aliasInfo = dataTarget->operands[0];
+            // TODO: rework literal load disambiguation to more cleanly handle 64-bit loads
+            loadPcRel->aliasInfo = (uintptr_t)dataTarget;
             dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
             res =  loadPcRel;
         }
diff --git a/vm/compiler/codegen/x86/CodegenInterface.cpp b/vm/compiler/codegen/x86/CodegenInterface.cpp
index e7dd8af..46f0979 100644
--- a/vm/compiler/codegen/x86/CodegenInterface.cpp
+++ b/vm/compiler/codegen/x86/CodegenInterface.cpp
@@ -70,6 +70,9 @@
     gDvmJit.codeCacheSize = 512*1024;
     gDvmJit.optLevel = kJitOptLevelO1;
 
+    //Disable Method-JIT
+    gDvmJit.disableOpt |= (1 << kMethodJit);
+
 #if defined(WITH_SELF_VERIFICATION)
     /* Force into blocking mode */
     gDvmJit.blockingMode = true;
@@ -324,7 +327,7 @@
         cellAddr->clazz = newContent->clazz;
         //cacheflush((intptr_t) cellAddr, (intptr_t) (cellAddr+1), 0);
 #endif
-#if defined(IA_JIT_TUNING)
+#if defined(WITH_JIT_TUNING)
         gDvmJit.icPatchInit++;
 #endif
         COMPILER_TRACE_CHAINING(
@@ -717,6 +720,12 @@
 #ifndef PREDICTED_CHAINING
     //assume rPC for callee->insns in %ebx
     scratchRegs[0] = PhysicalReg_EAX;
+#if defined(WITH_JIT_TUNING)
+    /* Predicted chaining is not enabled. Fall back to interpreter and
+     * indicate that predicted chaining was not done.
+     */
+    move_imm_to_reg(OpndSize_32, kInlineCacheMiss, PhysicalReg_EDX, true);
+#endif
     call_dvmJitToInterpTraceSelectNoChain();
 #else
     /* make sure section for predicited chaining cell is 4-byte aligned */
diff --git a/vm/compiler/codegen/x86/LowerAlu.cpp b/vm/compiler/codegen/x86/LowerAlu.cpp
index 2231bac..c8c4d66 100644
--- a/vm/compiler/codegen/x86/LowerAlu.cpp
+++ b/vm/compiler/codegen/x86/LowerAlu.cpp
@@ -291,56 +291,74 @@
         load_fp_stack_VR(OpndSize_32, vB); //flds
     }
 
-    load_fp_stack_global_data_API("valuePosInfLong", OpndSize_64);
+    //Check if it is the special Negative Infinity value
     load_fp_stack_global_data_API("valueNegInfLong", OpndSize_64);
-
-    //ST(0) ST(1) ST(2) --> LintMin LintMax value
-    compare_fp_stack(true, 2, false/*isDouble*/); //ST(2)
-    //ST(0) ST(1) --> LintMax value
+    //Stack status: ST(0) ST(1) --> LlongMin value
+    compare_fp_stack(true, 1, false/*isDouble*/); // Pops ST(1)
     conditional_jump(Condition_AE, ".float_to_long_negInf", true);
     rememberState(1);
-    compare_fp_stack(true, 1, false/*isDouble*/); //ST(1)
+
+    //Check if it is the special Positive Infinity value
+    load_fp_stack_global_data_API("valuePosInfLong", OpndSize_64);
+    //Stack status: ST(0) ST(1) --> LlongMax value
+    compare_fp_stack(true, 1, false/*isDouble*/); // Pops ST(1)
     rememberState(2);
-    //ST(0) --> value
     conditional_jump(Condition_C, ".float_to_long_nanInf", true);
-    //fnstcw, orw, fldcw, xorw
+
+    //Normal Case
+    //We want to truncate to 0 for conversion. That will be rounding mode 0x11
     load_effective_addr(-2, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
     store_fpu_cw(false/*checkException*/, 0, PhysicalReg_ESP, true);
+    //Change control word to rounding mode 11:
     alu_binary_imm_mem(OpndSize_16, or_opc, 0xc00, 0, PhysicalReg_ESP, true);
+    //Load the control word
     load_fpu_cw(0, PhysicalReg_ESP, true);
+    //Reset the control word
     alu_binary_imm_mem(OpndSize_16, xor_opc, 0xc00, 0, PhysicalReg_ESP, true);
+    //Perform the actual conversion
     store_int_fp_stack_VR(true/*pop*/, OpndSize_64, vA); //fistpll
-    //fldcw
+    // Restore the original control word
     load_fpu_cw(0, PhysicalReg_ESP, true);
     load_effective_addr(2, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
     rememberState(3);
+    /* NOTE: We do not need to pop out the original value we pushed
+     * since load_fpu_cw above already clears the stack for
+     * normal values.
+     */
     unconditional_jump(".float_to_long_okay", true);
+
+    //We can be here for positive infinity or NaN. Check parity bit
     insertLabel(".float_to_long_nanInf", true);
     conditional_jump(Condition_NP, ".float_to_long_posInf", true);
-    //fstpl??
     goToState(2);
-
+    //Save corresponding Long NaN value
     load_global_data_API("valueNanLong", OpndSize_64, 1, false);
-
     set_virtual_reg(vA, OpndSize_64, 1, false);
     transferToState(3);
+    //Pop out the original value we pushed
+    compare_fp_stack(true, 0, false/*isDouble*/); //ST(0)
     unconditional_jump(".float_to_long_okay", true);
-    insertLabel(".float_to_long_posInf", true);
-    //fstpl
-    goToState(2);
 
+    insertLabel(".float_to_long_posInf", true);
+    goToState(2);
+    //Save corresponding Long Positive Infinity value
     load_global_data_API("valuePosInfLong", OpndSize_64, 2, false);
     set_virtual_reg(vA, OpndSize_64, 2, false);
     transferToState(3);
+    //Pop out the original value we pushed
+    compare_fp_stack(true, 0, false/*isDouble*/); //ST(0)
     unconditional_jump(".float_to_long_okay", true);
+
     insertLabel(".float_to_long_negInf", true);
     //fstpl
-    //fstpl
     goToState(1);
-
+    //Load corresponding Long Negative Infinity value
     load_global_data_API("valueNegInfLong", OpndSize_64, 3, false);
     set_virtual_reg(vA, OpndSize_64, 3, false);
     transferToState(3);
+    //Pop out the original value we pushed
+    compare_fp_stack(true, 0, false/*isDouble*/); //ST(0)
+
     insertLabel(".float_to_long_okay", true);
     return 0;
 }
diff --git a/vm/compiler/codegen/x86/LowerGetPut.cpp b/vm/compiler/codegen/x86/LowerGetPut.cpp
index c87b174..be519b1 100644
--- a/vm/compiler/codegen/x86/LowerGetPut.cpp
+++ b/vm/compiler/codegen/x86/LowerGetPut.cpp
@@ -668,7 +668,17 @@
     void *fieldPtr = (void*)
         (currentMethod->clazz->pDvmDex->pResFields[tmp]);
 #endif
-    assert(fieldPtr != NULL);
+
+    /* Usually, fieldPtr should not be null. The interpreter should resolve
+     * it before we come here, or not allow this opcode in a trace. However,
+     * we can be in a loop trace and this opcode might have been picked up
+     * by exhaustTrace. Sending a -1 here will terminate the loop formation
+     * and fall back to normal trace, which will not have this opcode.
+     */
+    if (!fieldPtr) {
+        return -1;
+    }
+
     move_imm_to_reg(OpndSize_32, (int)fieldPtr, PhysicalReg_EAX, true);
     if(flag == SGET) {
         move_mem_to_reg(OpndSize_32, offStaticField_value, PhysicalReg_EAX, true, 7, false); //access field
diff --git a/vm/compiler/codegen/x86/LowerInvoke.cpp b/vm/compiler/codegen/x86/LowerInvoke.cpp
index 3d02190..10bc197 100644
--- a/vm/compiler/codegen/x86/LowerInvoke.cpp
+++ b/vm/compiler/codegen/x86/LowerInvoke.cpp
@@ -833,6 +833,12 @@
         if(callNoChain) {
             scratchRegs[0] = PhysicalReg_EAX;
             load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
+#if defined(WITH_JIT_TUNING)
+            /* Predicted chaining failed. Fall back to interpreter and indicate
+             * inline cache miss.
+             */
+            move_imm_to_reg(OpndSize_32, kInlineCacheMiss, PhysicalReg_EDX, true);
+#endif
             call_dvmJitToInterpTraceSelectNoChain(); //input: rPC in %ebx
         } else {
             //jump to the stub at (%esp)
@@ -906,6 +912,11 @@
         //move rPC by 6 (3 bytecode units for INVOKE)
         alu_binary_imm_reg(OpndSize_32, add_opc, 6, PhysicalReg_EBX, true);
         scratchRegs[0] = PhysicalReg_EAX;
+#if defined(WITH_JIT_TUNING)
+        /* Return address not in code cache. Indicate that continuing with interpreter
+         */
+        move_imm_to_reg(OpndSize_32, kCallsiteInterpreted, PhysicalReg_EDX, true);
+#endif
         call_dvmJitToInterpTraceSelectNoChain(); //rPC in %ebx
     }
     return;
diff --git a/vm/compiler/codegen/x86/LowerJump.cpp b/vm/compiler/codegen/x86/LowerJump.cpp
index 2b10d6b..d4b0df3 100644
--- a/vm/compiler/codegen/x86/LowerJump.cpp
+++ b/vm/compiler/codegen/x86/LowerJump.cpp
@@ -1163,6 +1163,13 @@
     //get rPC, %eax has the relative PC offset
     alu_binary_imm_reg(OpndSize_32, add_opc, (int)rPC, PhysicalReg_EAX, true);
     scratchRegs[0] = PhysicalReg_SCRATCH_2;
+#if defined(WITH_JIT_TUNING)
+    /* Fall back to interpreter after resolving address of switch target.
+     * Indicate a kSwitchOverflow. Note: This is not an "overflow". But it helps
+     * count the times we return from a Switch
+     */
+    move_imm_to_mem(OpndSize_32, kSwitchOverflow, 0, PhysicalReg_ESP, true);
+#endif
     jumpToInterpNoChain();
     rPC += 3;
     return 0;
@@ -1220,6 +1227,13 @@
     //get rPC, %eax has the relative PC offset
     alu_binary_imm_reg(OpndSize_32, add_opc, (int)rPC, PhysicalReg_EAX, true);
     scratchRegs[0] = PhysicalReg_SCRATCH_2;
+#if defined(WITH_JIT_TUNING)
+    /* Fall back to interpreter after resolving address of switch target.
+     * Indicate a kSwitchOverflow. Note: This is not an "overflow". But it helps
+     * count the times we return from a Switch
+     */
+    move_imm_to_mem(OpndSize_32, kSwitchOverflow, 0, PhysicalReg_ESP, true);
+#endif
     jumpToInterpNoChain();
     rPC += 3;
     return 0;
diff --git a/vm/compiler/codegen/x86/LowerReturn.cpp b/vm/compiler/codegen/x86/LowerReturn.cpp
index 928c05c..294d6b5 100644
--- a/vm/compiler/codegen/x86/LowerReturn.cpp
+++ b/vm/compiler/codegen/x86/LowerReturn.cpp
@@ -95,7 +95,11 @@
     typedef void (*vmHelper)(int);
     vmHelper funcPtr = dvmJitToInterpNoChainNoProfile; //%eax is the input
     move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical);
-
+#if defined(WITH_JIT_TUNING)
+    /* Return address not in code cache. Indicate that continuing with interpreter.
+     */
+    move_imm_to_mem(OpndSize_32, kCallsiteInterpreted, 0, PhysicalReg_ESP, true);
+#endif
     unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical);
     touchEax();
     return 0;
diff --git a/vm/interp/Interp.cpp b/vm/interp/Interp.cpp
index a37e134..fa77523 100644
--- a/vm/interp/Interp.cpp
+++ b/vm/interp/Interp.cpp
@@ -1669,6 +1669,9 @@
     if (gDvm.debuggerActive) {
         dvmEnableSubMode(thread, kSubModeDebuggerActive);
     }
+#if defined(WITH_JIT)
+    dvmJitUpdateThreadStateSingle(thread);
+#endif
 #if 0
     // Debugging stress mode - force checkBefore
     dvmEnableSubMode(thread, kSubModeCheckAlways);
diff --git a/vm/jdwp/JdwpAdb.cpp b/vm/jdwp/JdwpAdb.cpp
index 87db1d2..8fb5391 100644
--- a/vm/jdwp/JdwpAdb.cpp
+++ b/vm/jdwp/JdwpAdb.cpp
@@ -345,7 +345,7 @@
 
     if (netState->wakeFds[1] >= 0) {
         ALOGV("+++ writing to wakePipe");
-        write(netState->wakeFds[1], "", 1);
+        TEMP_FAILURE_RETRY(write(netState->wakeFds[1], "", 1));
     }
 }
 
@@ -629,8 +629,8 @@
         }
 
         errno = 0;
-        cc = write(netState->clientSock, netState->inputBuffer,
-                kMagicHandshakeLen);
+        cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer,
+                                      kMagicHandshakeLen));
         if (cc != kMagicHandshakeLen) {
             ALOGE("Failed writing handshake bytes: %s (%d of %d)",
                 strerror(errno), cc, (int) kMagicHandshakeLen);
diff --git a/vm/jdwp/JdwpHandler.cpp b/vm/jdwp/JdwpHandler.cpp
index 5ce432c..9126584 100644
--- a/vm/jdwp/JdwpHandler.cpp
+++ b/vm/jdwp/JdwpHandler.cpp
@@ -376,6 +376,7 @@
     ALOGV("  Req to create string '%s'", str);
 
     ObjectId stringId = dvmDbgCreateString(str);
+    free(str);
     if (stringId == 0)
         return ERR_OUT_OF_MEMORY;
 
diff --git a/vm/jdwp/JdwpMain.cpp b/vm/jdwp/JdwpMain.cpp
index 90e4c45..55e278d 100644
--- a/vm/jdwp/JdwpMain.cpp
+++ b/vm/jdwp/JdwpMain.cpp
@@ -45,8 +45,8 @@
 ssize_t JdwpNetStateBase::writePacket(ExpandBuf* pReply)
 {
     dvmDbgLockMutex(&socketLock);
-    ssize_t cc = write(clientSock, expandBufGetBuffer(pReply),
-            expandBufGetLength(pReply));
+    ssize_t cc = TEMP_FAILURE_RETRY(write(clientSock, expandBufGetBuffer(pReply),
+                                          expandBufGetLength(pReply)));
     dvmDbgUnlockMutex(&socketLock);
 
     return cc;
@@ -59,7 +59,7 @@
     int iovcnt)
 {
     dvmDbgLockMutex(&socketLock);
-    ssize_t actual = writev(clientSock, iov, iovcnt);
+    ssize_t actual = TEMP_FAILURE_RETRY(writev(clientSock, iov, iovcnt));
     dvmDbgUnlockMutex(&socketLock);
 
     return actual;
diff --git a/vm/jdwp/JdwpSocket.cpp b/vm/jdwp/JdwpSocket.cpp
index ad0a287..eaea607 100644
--- a/vm/jdwp/JdwpSocket.cpp
+++ b/vm/jdwp/JdwpSocket.cpp
@@ -226,7 +226,7 @@
     /* if we might be sitting in select, kick us loose */
     if (netState->wakePipe[1] >= 0) {
         ALOGV("+++ writing to wakePipe");
-        (void) write(netState->wakePipe[1], "", 1);
+        TEMP_FAILURE_RETRY(write(netState->wakePipe[1], "", 1));
     }
 }
 static void netShutdownExtern(JdwpState* state)
@@ -789,8 +789,8 @@
         }
 
         errno = 0;
-        cc = write(netState->clientSock, netState->inputBuffer,
-                kMagicHandshakeLen);
+        cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer,
+                                      kMagicHandshakeLen));
         if (cc != kMagicHandshakeLen) {
             ALOGE("Failed writing handshake bytes: %s (%d of %d)",
                 strerror(errno), cc, (int) kMagicHandshakeLen);
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index 760e674..c87f306 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -15754,7 +15754,9 @@
  */
 dvmJitToInterpNoChainNoProfile:
 #if defined(WITH_JIT_TUNING)
+    SPILL_TMP1(%eax)
     call   dvmBumpNoChain
+    UNSPILL_TMP1(%eax)
 #endif
     movl   %eax, rPC
     movl   rSELF, %eax
@@ -15782,6 +15784,7 @@
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
 #if defined(WITH_JIT_TUNING)
+    movl   %edx, OUT_ARG0(%esp)
     call   dvmBumpNoChain
 #endif
     movl   %ebx, rPC
@@ -15895,6 +15898,11 @@
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
 dvmJitToInterpNoChain: #rPC in eax
+#if defined(WITH_JIT_TUNING)
+    SPILL_TMP1(%eax)
+    call   dvmBumpNoChain
+    UNSPILL_TMP1(%eax)
+#endif
     ## TODO, need to clean up stack manipulation ... this isn't signal safe and
     ## doesn't use the calling conventions of header.S
     movl        %eax, rPC
diff --git a/vm/mterp/x86/footer.S b/vm/mterp/x86/footer.S
index 3b5c79e..054dc11 100644
--- a/vm/mterp/x86/footer.S
+++ b/vm/mterp/x86/footer.S
@@ -77,7 +77,9 @@
  */
 dvmJitToInterpNoChainNoProfile:
 #if defined(WITH_JIT_TUNING)
+    SPILL_TMP1(%eax)
     call   dvmBumpNoChain
+    UNSPILL_TMP1(%eax)
 #endif
     movl   %eax, rPC
     movl   rSELF, %eax
@@ -105,6 +107,7 @@
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
 #if defined(WITH_JIT_TUNING)
+    movl   %edx, OUT_ARG0(%esp)
     call   dvmBumpNoChain
 #endif
     movl   %ebx, rPC
@@ -218,6 +221,11 @@
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
 dvmJitToInterpNoChain: #rPC in eax
+#if defined(WITH_JIT_TUNING)
+    SPILL_TMP1(%eax)
+    call   dvmBumpNoChain
+    UNSPILL_TMP1(%eax)
+#endif
     ## TODO, need to clean up stack manipulation ... this isn't signal safe and
     ## doesn't use the calling conventions of header.S
     movl        %eax, rPC
diff --git a/vm/native/dalvik_system_DexFile.cpp b/vm/native/dalvik_system_DexFile.cpp
index f328a19..69cb71d 100644
--- a/vm/native/dalvik_system_DexFile.cpp
+++ b/vm/native/dalvik_system_DexFile.cpp
@@ -232,6 +232,7 @@
         free(sourceName);
     }
 
+    free(outputName);
     RETURN_PTR(pDexOrJar);
 }