From 81058aaf92c188cc20273edd0275329fc304aca2 Mon Sep 17 00:00:00 2001 From: Dan Bornstein Date: Thu, 27 Jan 2011 11:38:37 -0800 Subject: Use bcopy() to move object refs around within an array. DO NOT MERGE. bcopy() guarantees that pointer-size words are stored atomically, and so this prevents the gc from seeing a pointer in mid-change. Bug: 3399673 Change-Id: Ic7d795e5d397548e9d6d8c11a585d86838cf8a44 --- vm/native/java_lang_System.c | 49 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/vm/native/java_lang_System.c b/vm/native/java_lang_System.c index 96cc144a6..4af0dfa42 100644 --- a/vm/native/java_lang_System.c +++ b/vm/native/java_lang_System.c @@ -20,6 +20,33 @@ #include "Dalvik.h" #include "native/InternalNativePriv.h" +/* + * Call the appropriate copy function given the circumstances. + */ +static void copy(void *dest, const void *src, size_t n, bool sameArray, + size_t elemSize) +{ + if (sameArray) { + /* Might overlap. */ + if (elemSize == sizeof(Object*)) { + /* + * In addition to handling overlap properly, bcopy() + * guarantees atomic treatment of words. This is needed so + * that concurrent threads never see half-formed pointers + * or ints. The former is required for proper gc behavior, + * and the latter is also required for proper high-level + * language support. + * + * Note: bcopy()'s argument order is different than memcpy(). + */ + bcopy(src, dest, n); + } else { + memmove(dest, src, n); + } + } else { + memcpy(dest, src, n); /* Can't overlap; use faster function. */ + } +} /* * public static void arraycopy(Object src, int srcPos, Object dest, @@ -30,7 +57,6 @@ */ static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) { - void* (*copyFunc)(void *dest, const void *src, size_t n); ArrayObject* srcArray; ArrayObject* dstArray; ClassObject* srcClass; @@ -38,6 +64,7 @@ static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) int srcPos, dstPos, length; char srcType, dstType; bool srcPrim, dstPrim; + bool sameArray; srcArray = (ArrayObject*) args[0]; srcPos = args[1]; @@ -45,10 +72,7 @@ static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) dstPos = args[3]; length = args[4]; - if (srcArray == dstArray) - copyFunc = memmove; /* might overlap */ - else - copyFunc = memcpy; /* can't overlap, use faster func */ + sameArray = (srcArray == dstArray); /* check for null or bad pointer */ if (!dvmValidateObject((Object*)srcArray) || @@ -126,9 +150,10 @@ static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) dstArray->contents, dstPos * width, srcArray->contents, srcPos * width, length * width); - (*copyFunc)((u1*)dstArray->contents + dstPos * width, + copy((u1*)dstArray->contents + dstPos * width, (const u1*)srcArray->contents + srcPos * width, - length * width); + length * width, + sameArray, width); } else { /* * Neither class is primitive. See if elements in "src" are instances @@ -147,9 +172,10 @@ static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) dstArray->contents, dstPos * width, srcArray->contents, srcPos * width, length * width); - (*copyFunc)((u1*)dstArray->contents + dstPos * width, + copy((u1*)dstArray->contents + dstPos * width, (const u1*)srcArray->contents + srcPos * width, - length * width); + length * width, + sameArray, width); dvmWriteBarrierArray(dstArray, dstPos, dstPos+length); } else { /* @@ -194,9 +220,10 @@ static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) dstArray->contents, dstPos * width, srcArray->contents, srcPos * width, copyCount, length); - (*copyFunc)((u1*)dstArray->contents + dstPos * width, + copy((u1*)dstArray->contents + dstPos * width, (const u1*)srcArray->contents + srcPos * width, - copyCount * width); + copyCount * width, + sameArray, width); dvmWriteBarrierArray(dstArray, 0, copyCount); if (copyCount != length) { dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;", -- cgit v1.2.3