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