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 * Call the appropriate copy function given the circumstances. 25 */ 26static void copy(void *dest, const void *src, size_t n, bool sameArray, 27 size_t elemSize) 28{ 29 if (sameArray) { 30 /* Might overlap. */ 31 if (elemSize == sizeof(Object*)) { 32 /* 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 38 * language support. 39 * 40 * Note: bcopy()'s argument order is different than memcpy(). 41 */ 42 bcopy(src, dest, n); 43 } else { 44 memmove(dest, src, n); 45 } 46 } else { 47 memcpy(dest, src, n); /* Can't overlap; use faster function. */ 48 } 49} 50 51/* 52 * public static void arraycopy(Object src, int srcPos, Object dest, 53 * int destPos, int length) 54 * 55 * The description of this function is long, and describes a multitude 56 * of checks and exceptions. 57 */ 58static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) 59{ 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; 67 bool sameArray; 68 69 srcArray = (ArrayObject*) args[0]; 70 srcPos = args[1]; 71 dstArray = (ArrayObject*) args[2]; 72 dstPos = args[3]; 73 length = args[4]; 74 75 sameArray = (srcArray == dstArray); 76 77 /* check for null or bad pointer */ 78 if (!dvmValidateObject((Object*)srcArray) || 79 !dvmValidateObject((Object*)dstArray)) 80 { 81 assert(dvmCheckException(dvmThreadSelf())); 82 RETURN_VOID(); 83 } 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); 90 RETURN_VOID(); 91 } 92 93 // avoid int overflow 94 if (srcPos < 0 || dstPos < 0 || length < 0 || 95 srcPos > (int) srcArray->length - length || 96 dstPos > (int) dstArray->length - length) 97 { 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); 101 RETURN_VOID(); 102 } 103 104 srcClass = srcArray->obj.clazz; 105 dstClass = dstArray->obj.clazz; 106 srcType = srcClass->descriptor[1]; 107 dstType = dstClass->descriptor[1]; 108 109 /* 110 * If one of the arrays holds a primitive type, the other array must 111 * hold the same type. 112 */ 113 srcPrim = (srcType != '[' && srcType != 'L'); 114 dstPrim = (dstType != '[' && dstType != 'L'); 115 if (srcPrim || dstPrim) { 116 int width; 117 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); 122 RETURN_VOID(); 123 } 124 125 switch (srcClass->descriptor[1]) { 126 case 'B': 127 case 'Z': 128 width = 1; 129 break; 130 case 'C': 131 case 'S': 132 width = 2; 133 break; 134 case 'F': 135 case 'I': 136 width = 4; 137 break; 138 case 'D': 139 case 'J': 140 width = 8; 141 break; 142 default: /* 'V' or something weird */ 143 LOGE("Weird array type '%s'\n", srcClass->descriptor); 144 assert(false); 145 width = 0; 146 break; 147 } 148 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, 152 length * width); 153 copy((u1*)dstArray->contents + dstPos * width, 154 (const u1*)srcArray->contents + srcPos * width, 155 length * width, 156 sameArray, width); 157 } else { 158 /* 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 161 * Object). 162 */ 163 int width = sizeof(Object*); 164 165 if (srcClass->arrayDim == dstClass->arrayDim && 166 dvmInstanceof(srcClass, dstClass)) 167 { 168 /* 169 * "dst" can hold "src"; copy the whole thing. 170 */ 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, 174 length * width); 175 copy((u1*)dstArray->contents + dstPos * width, 176 (const u1*)srcArray->contents + srcPos * width, 177 length * width, 178 sameArray, width); 179 dvmWriteBarrierArray(dstArray, dstPos, dstPos+length); 180 } else { 181 /* 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. 187 * 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. 192 */ 193 Object** srcObj; 194 Object** dstObj; 195 int copyCount; 196 ClassObject* clazz = NULL; 197 198 srcObj = ((Object**) srcArray->contents) + srcPos; 199 dstObj = ((Object**) dstArray->contents) + dstPos; 200 201 if (length > 0 && srcObj[0] != NULL) 202 { 203 clazz = srcObj[0]->clazz; 204 if (!dvmCanPutArrayElement(clazz, dstClass)) 205 clazz = NULL; 206 } 207 208 for (copyCount = 0; copyCount < length; copyCount++) 209 { 210 if (srcObj[copyCount] != NULL && 211 srcObj[copyCount]->clazz != clazz && 212 !dvmCanPutArrayElement(srcObj[copyCount]->clazz, dstClass)) 213 { 214 /* can't put this element into the array */ 215 break; 216 } 217 } 218 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, 222 copyCount, length); 223 copy((u1*)dstArray->contents + dstPos * width, 224 (const u1*)srcArray->contents + srcPos * width, 225 copyCount * width, 226 sameArray, 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); 233 RETURN_VOID(); 234 } 235 } 236 } 237 238 RETURN_VOID(); 239} 240 241/* 242 * static long currentTimeMillis() 243 * 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. 246 */ 247static void Dalvik_java_lang_System_currentTimeMillis(const u4* args, 248 JValue* pResult) 249{ 250 struct timeval tv; 251 252 UNUSED_PARAMETER(args); 253 254 gettimeofday(&tv, (struct timezone *) NULL); 255 long long when = tv.tv_sec * 1000LL + tv.tv_usec / 1000; 256 257 RETURN_LONG(when); 258} 259 260/* 261 * static long nanoTime() 262 * 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. 266 */ 267static void Dalvik_java_lang_System_nanoTime(const u4* args, JValue* pResult) 268{ 269 UNUSED_PARAMETER(args); 270 271 u8 when = dvmGetRelativeTimeNsec(); 272 RETURN_LONG(when); 273} 274 275/* 276 * static int identityHashCode(Object x) 277 * 278 * Returns that hash code that the default hashCode() 279 * method would return for "x", even if "x"s class 280 * overrides hashCode(). 281 */ 282static void Dalvik_java_lang_System_identityHashCode(const u4* args, 283 JValue* pResult) 284{ 285 Object* thisPtr = (Object*) args[0]; 286 RETURN_INT(dvmIdentityHashCode(thisPtr)); 287} 288 289/* 290 * public static String mapLibraryName(String libname) 291 */ 292static void Dalvik_java_lang_System_mapLibraryName(const u4* args, 293 JValue* pResult) 294{ 295 StringObject* nameObj = (StringObject*) args[0]; 296 StringObject* result = NULL; 297 char* name; 298 char* mappedName; 299 300 if (nameObj == NULL) { 301 dvmThrowException("Ljava/lang/NullPointerException;", NULL); 302 RETURN_VOID(); 303 } 304 305 name = dvmCreateCstrFromString(nameObj); 306 mappedName = dvmCreateSystemLibraryName(name); 307 if (mappedName != NULL) { 308 result = dvmCreateStringFromCstr(mappedName); 309 dvmReleaseTrackedAlloc((Object*) result, NULL); 310 } 311 312 free(name); 313 free(mappedName); 314 RETURN_PTR(result); 315} 316 317const 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 }, 322 { "nanoTime", "()J", 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 }, 329}; 330