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);
}