• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 /*
18  * java.lang.Class
19  */
20 #include "Dalvik.h"
21 #include "native/InternalNativePriv.h"
22 
23 
24 /*
25  * public static void arraycopy(Object src, int srcPos, Object dest,
26  *      int destPos, int length)
27  *
28  * The description of this function is long, and describes a multitude
29  * of checks and exceptions.
30  */
Dalvik_java_lang_System_arraycopy(const u4 * args,JValue * pResult)31 static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult)
32 {
33     void* (*copyFunc)(void *dest, const void *src, size_t n);
34     ArrayObject* srcArray;
35     ArrayObject* dstArray;
36     ClassObject* srcClass;
37     ClassObject* dstClass;
38     int srcPos, dstPos, length;
39     char srcType, dstType;
40     bool srcPrim, dstPrim;
41 
42     srcArray = (ArrayObject*) args[0];
43     srcPos = args[1];
44     dstArray = (ArrayObject*) args[2];
45     dstPos = args[3];
46     length = args[4];
47 
48     if (srcArray == dstArray)
49         copyFunc = memmove;         /* might overlap */
50     else
51         copyFunc = memcpy;          /* can't overlap, use faster func */
52 
53     /* check for null or bad pointer */
54     if (!dvmValidateObject((Object*)srcArray) ||
55         !dvmValidateObject((Object*)dstArray))
56     {
57         assert(dvmCheckException(dvmThreadSelf()));
58         RETURN_VOID();
59     }
60     /* make sure it's an array */
61     if (!dvmIsArray(srcArray) || !dvmIsArray(dstArray)) {
62         dvmThrowException("Ljava/lang/ArrayStoreException;", NULL);
63         RETURN_VOID();
64     }
65 
66     // avoid int overflow
67     if (srcPos < 0 || dstPos < 0 || length < 0 ||
68         srcPos > (int) srcArray->length - length ||
69         dstPos > (int) dstArray->length - length)
70     {
71         dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL);
72         RETURN_VOID();
73     }
74 
75     srcClass = srcArray->obj.clazz;
76     dstClass = dstArray->obj.clazz;
77     srcType = srcClass->descriptor[1];
78     dstType = dstClass->descriptor[1];
79 
80     /*
81      * If one of the arrays holds a primitive type, the other array must
82      * hold the same type.
83      */
84     srcPrim = (srcType != '[' && srcType != 'L');
85     dstPrim = (dstType != '[' && dstType != 'L');
86     if (srcPrim || dstPrim) {
87         int width;
88 
89         if (srcPrim != dstPrim || srcType != dstType) {
90             dvmThrowException("Ljava/lang/ArrayStoreException;", NULL);
91             RETURN_VOID();
92         }
93 
94         switch (srcClass->descriptor[1]) {
95         case 'B':
96         case 'Z':
97             width = 1;
98             break;
99         case 'C':
100         case 'S':
101             width = 2;
102             break;
103         case 'F':
104         case 'I':
105             width = 4;
106             break;
107         case 'D':
108         case 'J':
109             width = 8;
110             break;
111         default:        /* 'V' or something weird */
112             LOGE("Weird array type '%s'\n", srcClass->descriptor);
113             assert(false);
114             width = 0;
115             break;
116         }
117 
118         if (false) LOGVV("arraycopy prim dst=%p %d src=%p %d len=%d\n",
119                 dstArray->contents, dstPos * width,
120                 srcArray->contents, srcPos * width,
121                 length * width);
122         (*copyFunc)((u1*)dstArray->contents + dstPos * width,
123                 (const u1*)srcArray->contents + srcPos * width,
124                 length * width);
125     } else {
126         /*
127          * Neither class is primitive.  See if elements in "src" are instances
128          * of elements in "dst" (e.g. copy String to String or String to
129          * Object).
130          */
131         int width = sizeof(Object*);
132 
133         if (srcClass->arrayDim == dstClass->arrayDim &&
134             dvmInstanceof(srcClass, dstClass))
135         {
136             /*
137              * "dst" can hold "src"; copy the whole thing.
138              */
139             if (false) LOGVV("arraycopy ref dst=%p %d src=%p %d len=%d\n",
140                 dstArray->contents, dstPos * width,
141                 srcArray->contents, srcPos * width,
142                 length * width);
143             (*copyFunc)((u1*)dstArray->contents + dstPos * width,
144                     (const u1*)srcArray->contents + srcPos * width,
145                     length * width);
146         } else {
147             /*
148              * The arrays are not fundamentally compatible.  However, we may
149              * still be able to do this if the destination object is compatible
150              * (e.g. copy Object to String, but the Object being copied is
151              * actually a String).  We need to copy elements one by one until
152              * something goes wrong.
153              *
154              * Because of overlapping moves, what we really want to do is
155              * compare the types and count up how many we can move, then call
156              * memmove() to shift the actual data.  If we just start from the
157              * front we could do a smear rather than a move.
158              */
159             Object** srcObj;
160             Object** dstObj;
161             int copyCount;
162             ClassObject*   clazz = NULL;
163 
164             srcObj = ((Object**) srcArray->contents) + srcPos;
165             dstObj = ((Object**) dstArray->contents) + dstPos;
166 
167             if (length > 0 && srcObj[0] != NULL)
168             {
169                 clazz = srcObj[0]->clazz;
170                 if (!dvmCanPutArrayElement(clazz, dstClass))
171                     clazz = NULL;
172             }
173 
174             for (copyCount = 0; copyCount < length; copyCount++)
175             {
176                 if (srcObj[copyCount] != NULL &&
177                     srcObj[copyCount]->clazz != clazz &&
178                     !dvmCanPutArrayElement(srcObj[copyCount]->clazz, dstClass))
179                 {
180                     /* can't put this element into the array */
181                     break;
182                 }
183             }
184 
185             if (false) LOGVV("arraycopy iref dst=%p %d src=%p %d count=%d of %d\n",
186                 dstArray->contents, dstPos * width,
187                 srcArray->contents, srcPos * width,
188                 copyCount, length);
189             (*copyFunc)((u1*)dstArray->contents + dstPos * width,
190                     (const u1*)srcArray->contents + srcPos * width,
191                     copyCount * width);
192 
193             if (copyCount != length) {
194                 dvmThrowException("Ljava/lang/ArrayStoreException;", NULL);
195                 RETURN_VOID();
196             }
197         }
198     }
199 
200     RETURN_VOID();
201 }
202 
203 /*
204  * static long currentTimeMillis()
205  *
206  * Current time, in miliseconds.  This doesn't need to be internal to the
207  * VM, but we're already handling java.lang.System here.
208  */
Dalvik_java_lang_System_currentTimeMillis(const u4 * args,JValue * pResult)209 static void Dalvik_java_lang_System_currentTimeMillis(const u4* args,
210     JValue* pResult)
211 {
212     struct timeval tv;
213 
214     UNUSED_PARAMETER(args);
215 
216     gettimeofday(&tv, (struct timezone *) NULL);
217     long long when = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
218 
219     RETURN_LONG(when);
220 }
221 
222 /*
223  * static long nanoTime()
224  *
225  * Current monotonically-increasing time, in nanoseconds.  This doesn't
226  * need to be internal to the VM, but we're already handling
227  * java.lang.System here.
228  */
Dalvik_java_lang_System_nanoTime(const u4 * args,JValue * pResult)229 static void Dalvik_java_lang_System_nanoTime(const u4* args, JValue* pResult)
230 {
231     UNUSED_PARAMETER(args);
232 
233     u8 when = dvmGetRelativeTimeNsec();
234     RETURN_LONG(when);
235 }
236 
237 /*
238  * static int identityHashCode(Object x)
239  *
240  * Returns that hash code that the default hashCode()
241  * method would return for "x", even if "x"s class
242  * overrides hashCode().
243  */
Dalvik_java_lang_System_identityHashCode(const u4 * args,JValue * pResult)244 static void Dalvik_java_lang_System_identityHashCode(const u4* args,
245     JValue* pResult)
246 {
247     Object* thisPtr = (Object*) args[0];
248     RETURN_INT(dvmGetObjectHashCode(thisPtr));
249 }
250 
251 /*
252  * public static String mapLibraryName(String libname)
253  */
Dalvik_java_lang_System_mapLibraryName(const u4 * args,JValue * pResult)254 static void Dalvik_java_lang_System_mapLibraryName(const u4* args,
255     JValue* pResult)
256 {
257     StringObject* nameObj = (StringObject*) args[0];
258     StringObject* result = NULL;
259     char* name;
260     char* mappedName;
261 
262     if (nameObj == NULL) {
263         dvmThrowException("Ljava/lang/NullPointerException;", NULL);
264         RETURN_VOID();
265     }
266 
267     name = dvmCreateCstrFromString(nameObj);
268     mappedName = dvmCreateSystemLibraryName(name);
269     if (mappedName != NULL) {
270         result = dvmCreateStringFromCstr(mappedName, ALLOC_DEFAULT);
271         dvmReleaseTrackedAlloc((Object*) result, NULL);
272     }
273 
274     free(name);
275     free(mappedName);
276     RETURN_PTR(result);
277 }
278 
279 const DalvikNativeMethod dvm_java_lang_System[] = {
280     { "arraycopy",          "(Ljava/lang/Object;ILjava/lang/Object;II)V",
281         Dalvik_java_lang_System_arraycopy },
282     { "currentTimeMillis",  "()J",
283         Dalvik_java_lang_System_currentTimeMillis },
284     { "nanoTime",  "()J",
285         Dalvik_java_lang_System_nanoTime },
286     { "identityHashCode",  "(Ljava/lang/Object;)I",
287         Dalvik_java_lang_System_identityHashCode },
288     { "mapLibraryName",     "(Ljava/lang/String;)Ljava/lang/String;",
289         Dalvik_java_lang_System_mapLibraryName },
290     { NULL, NULL, NULL },
291 };
292 
293