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