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