2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include "native/InternalNativePriv.h"
24 * Call the appropriate copy function given the circumstances.
26 static void copy(void *dest, const void *src, size_t n, bool sameArray,
31 if (elemSize == sizeof(Object*)) {
33 * In addition to handling overlap properly, bcopy()
34 * guarantees atomic treatment of words. This is needed so
35 * that concurrent threads never see half-formed pointers
36 * or ints. The former is required for proper gc behavior,
37 * and the latter is also required for proper high-level
40 * Note: bcopy()'s argument order is different than memcpy().
44 memmove(dest, src, n);
47 memcpy(dest, src, n); /* Can't overlap; use faster function. */
52 * public static void arraycopy(Object src, int srcPos, Object dest,
53 * int destPos, int length)
55 * The description of this function is long, and describes a multitude
56 * of checks and exceptions.
58 static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult)
60 ArrayObject* srcArray;
61 ArrayObject* dstArray;
62 ClassObject* srcClass;
63 ClassObject* dstClass;
64 int srcPos, dstPos, length;
65 char srcType, dstType;
66 bool srcPrim, dstPrim;
69 srcArray = (ArrayObject*) args[0];
71 dstArray = (ArrayObject*) args[2];
75 sameArray = (srcArray == dstArray);
77 /* check for null or bad pointer */
78 if (!dvmValidateObject((Object*)srcArray) ||
79 !dvmValidateObject((Object*)dstArray))
81 assert(dvmCheckException(dvmThreadSelf()));
84 /* make sure it's an array */
85 if (!dvmIsArray(srcArray) || !dvmIsArray(dstArray)) {
86 dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;",
87 "source and destination must be arrays, but were %s and %s",
88 ((Object*)srcArray)->clazz->descriptor,
89 ((Object*)dstArray)->clazz->descriptor);
94 if (srcPos < 0 || dstPos < 0 || length < 0 ||
95 srcPos > (int) srcArray->length - length ||
96 dstPos > (int) dstArray->length - length)
98 dvmThrowExceptionFmt("Ljava/lang/ArrayIndexOutOfBoundsException;",
99 "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
100 srcArray->length, srcPos, dstArray->length, dstPos, length);
104 srcClass = srcArray->obj.clazz;
105 dstClass = dstArray->obj.clazz;
106 srcType = srcClass->descriptor[1];
107 dstType = dstClass->descriptor[1];
110 * If one of the arrays holds a primitive type, the other array must
111 * hold the same type.
113 srcPrim = (srcType != '[' && srcType != 'L');
114 dstPrim = (dstType != '[' && dstType != 'L');
115 if (srcPrim || dstPrim) {
118 if (srcPrim != dstPrim || srcType != dstType) {
119 dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;",
120 "source and destination arrays are incompatible: %s and %s",
121 srcClass->descriptor, dstClass->descriptor);
125 switch (srcClass->descriptor[1]) {
142 default: /* 'V' or something weird */
143 LOGE("Weird array type '%s'\n", srcClass->descriptor);
149 if (false) LOGVV("arraycopy prim dst=%p %d src=%p %d len=%d\n",
150 dstArray->contents, dstPos * width,
151 srcArray->contents, srcPos * width,
153 copy((u1*)dstArray->contents + dstPos * width,
154 (const u1*)srcArray->contents + srcPos * width,
159 * Neither class is primitive. See if elements in "src" are instances
160 * of elements in "dst" (e.g. copy String to String or String to
163 int width = sizeof(Object*);
165 if (srcClass->arrayDim == dstClass->arrayDim &&
166 dvmInstanceof(srcClass, dstClass))
169 * "dst" can hold "src"; copy the whole thing.
171 if (false) LOGVV("arraycopy ref dst=%p %d src=%p %d len=%d\n",
172 dstArray->contents, dstPos * width,
173 srcArray->contents, srcPos * width,
175 copy((u1*)dstArray->contents + dstPos * width,
176 (const u1*)srcArray->contents + srcPos * width,
179 dvmWriteBarrierArray(dstArray, dstPos, dstPos+length);
182 * The arrays are not fundamentally compatible. However, we may
183 * still be able to do this if the destination object is compatible
184 * (e.g. copy Object to String, but the Object being copied is
185 * actually a String). We need to copy elements one by one until
186 * something goes wrong.
188 * Because of overlapping moves, what we really want to do is
189 * compare the types and count up how many we can move, then call
190 * memmove() to shift the actual data. If we just start from the
191 * front we could do a smear rather than a move.
196 ClassObject* clazz = NULL;
198 srcObj = ((Object**) srcArray->contents) + srcPos;
199 dstObj = ((Object**) dstArray->contents) + dstPos;
201 if (length > 0 && srcObj[0] != NULL)
203 clazz = srcObj[0]->clazz;
204 if (!dvmCanPutArrayElement(clazz, dstClass))
208 for (copyCount = 0; copyCount < length; copyCount++)
210 if (srcObj[copyCount] != NULL &&
211 srcObj[copyCount]->clazz != clazz &&
212 !dvmCanPutArrayElement(srcObj[copyCount]->clazz, dstClass))
214 /* can't put this element into the array */
219 if (false) LOGVV("arraycopy iref dst=%p %d src=%p %d count=%d of %d\n",
220 dstArray->contents, dstPos * width,
221 srcArray->contents, srcPos * width,
223 copy((u1*)dstArray->contents + dstPos * width,
224 (const u1*)srcArray->contents + srcPos * width,
227 dvmWriteBarrierArray(dstArray, 0, copyCount);
228 if (copyCount != length) {
229 dvmThrowExceptionFmt("Ljava/lang/ArrayStoreException;",
230 "source[%d] of type %s cannot be stored in destination array of type %s",
231 copyCount, srcObj[copyCount]->clazz->descriptor,
232 dstClass->descriptor);
242 * static long currentTimeMillis()
244 * Current time, in miliseconds. This doesn't need to be internal to the
245 * VM, but we're already handling java.lang.System here.
247 static void Dalvik_java_lang_System_currentTimeMillis(const u4* args,
252 UNUSED_PARAMETER(args);
254 gettimeofday(&tv, (struct timezone *) NULL);
255 long long when = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
261 * static long nanoTime()
263 * Current monotonically-increasing time, in nanoseconds. This doesn't
264 * need to be internal to the VM, but we're already handling
265 * java.lang.System here.
267 static void Dalvik_java_lang_System_nanoTime(const u4* args, JValue* pResult)
269 UNUSED_PARAMETER(args);
271 u8 when = dvmGetRelativeTimeNsec();
276 * static int identityHashCode(Object x)
278 * Returns that hash code that the default hashCode()
279 * method would return for "x", even if "x"s class
280 * overrides hashCode().
282 static void Dalvik_java_lang_System_identityHashCode(const u4* args,
285 Object* thisPtr = (Object*) args[0];
286 RETURN_INT(dvmIdentityHashCode(thisPtr));
290 * public static String mapLibraryName(String libname)
292 static void Dalvik_java_lang_System_mapLibraryName(const u4* args,
295 StringObject* nameObj = (StringObject*) args[0];
296 StringObject* result = NULL;
300 if (nameObj == NULL) {
301 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
305 name = dvmCreateCstrFromString(nameObj);
306 mappedName = dvmCreateSystemLibraryName(name);
307 if (mappedName != NULL) {
308 result = dvmCreateStringFromCstr(mappedName);
309 dvmReleaseTrackedAlloc((Object*) result, NULL);
317 const DalvikNativeMethod dvm_java_lang_System[] = {
318 { "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
319 Dalvik_java_lang_System_arraycopy },
320 { "currentTimeMillis", "()J",
321 Dalvik_java_lang_System_currentTimeMillis },
323 Dalvik_java_lang_System_nanoTime },
324 { "identityHashCode", "(Ljava/lang/Object;)I",
325 Dalvik_java_lang_System_identityHashCode },
326 { "mapLibraryName", "(Ljava/lang/String;)Ljava/lang/String;",
327 Dalvik_java_lang_System_mapLibraryName },
328 { NULL, NULL, NULL },