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 native methods 19 */ 20 #include "Dalvik.h" 21 #include "native/InternalNativePriv.h" 22 23 /* 24 * The VM makes guarantees about the atomicity of accesses to primitive 25 * variables. These guarantees also apply to elements of arrays. 26 * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and 27 * must not cause "word tearing". Accesses to 64-bit array elements must 28 * either be atomic or treated as two 32-bit operations. References are 29 * always read and written atomically, regardless of the number of bits 30 * used to represent them. 31 * 32 * We can't rely on standard libc functions like memcpy() and memmove() 33 * in our implementation of System.arraycopy(), because they may copy 34 * byte-by-byte (either for the full run or for "unaligned" parts at the 35 * start or end). We need to use functions that guarantee 16-bit or 32-bit 36 * atomicity as appropriate. 37 * 38 * System.arraycopy() is heavily used, so having an efficient implementation 39 * is important. The bionic libc provides a platform-optimized memory move 40 * function that should be used when possible. If it's not available, 41 * the trivial "reference implementation" versions below can be used until 42 * a proper version can be written. 43 * 44 * For these functions, The caller must guarantee that dest/src are aligned 45 * appropriately for the element type, and that n is a multiple of the 46 * element size. 47 */ 48 #ifdef __BIONIC__ 49 /* always present in bionic libc */ 50 #define HAVE_MEMMOVE_WORDS 51 #endif 52 53 #ifdef HAVE_MEMMOVE_WORDS 54 extern "C" void _memmove_words(void* dest, const void* src, size_t n); 55 #define move16 _memmove_words 56 #define move32 _memmove_words 57 #else move16(void * dest,const void * src,size_t n)58 static void move16(void* dest, const void* src, size_t n) 59 { 60 assert((((uintptr_t) dest | (uintptr_t) src | n) & 0x01) == 0); 61 62 uint16_t* d = (uint16_t*) dest; 63 const uint16_t* s = (uint16_t*) src; 64 65 n /= sizeof(uint16_t); 66 67 if (d < s) { 68 /* copy forward */ 69 while (n--) { 70 *d++ = *s++; 71 } 72 } else { 73 /* copy backward */ 74 d += n; 75 s += n; 76 while (n--) { 77 *--d = *--s; 78 } 79 } 80 } 81 move32(void * dest,const void * src,size_t n)82 static void move32(void* dest, const void* src, size_t n) 83 { 84 assert((((uintptr_t) dest | (uintptr_t) src | n) & 0x03) == 0); 85 86 uint32_t* d = (uint32_t*) dest; 87 const uint32_t* s = (uint32_t*) src; 88 89 n /= sizeof(uint32_t); 90 91 if (d < s) { 92 /* copy forward */ 93 while (n--) { 94 *d++ = *s++; 95 } 96 } else { 97 /* copy backward */ 98 d += n; 99 s += n; 100 while (n--) { 101 *--d = *--s; 102 } 103 } 104 } 105 #endif /*HAVE_MEMMOVE_WORDS*/ 106 107 /* 108 * public static void arraycopy(Object src, int srcPos, Object dest, 109 * int destPos, int length) 110 * 111 * The description of this function is long, and describes a multitude 112 * of checks and exceptions. 113 */ Dalvik_java_lang_System_arraycopy(const u4 * args,JValue * pResult)114 static void Dalvik_java_lang_System_arraycopy(const u4* args, JValue* pResult) 115 { 116 ArrayObject* srcArray = (ArrayObject*) args[0]; 117 int srcPos = args[1]; 118 ArrayObject* dstArray = (ArrayObject*) args[2]; 119 int dstPos = args[3]; 120 int length = args[4]; 121 122 /* Check for null pointers. */ 123 if (srcArray == NULL) { 124 dvmThrowNullPointerException("src == null"); 125 RETURN_VOID(); 126 } 127 if (dstArray == NULL) { 128 dvmThrowNullPointerException("dst == null"); 129 RETURN_VOID(); 130 } 131 132 /* Make sure source and destination are arrays. */ 133 if (!dvmIsArray(srcArray)) { 134 dvmThrowArrayStoreExceptionNotArray(((Object*)srcArray)->clazz, "source"); 135 RETURN_VOID(); 136 } 137 if (!dvmIsArray(dstArray)) { 138 dvmThrowArrayStoreExceptionNotArray(((Object*)dstArray)->clazz, "destination"); 139 RETURN_VOID(); 140 } 141 142 /* avoid int overflow */ 143 if (srcPos < 0 || dstPos < 0 || length < 0 || 144 srcPos > (int) srcArray->length - length || 145 dstPos > (int) dstArray->length - length) 146 { 147 dvmThrowExceptionFmt(gDvm.exArrayIndexOutOfBoundsException, 148 "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d", 149 srcArray->length, srcPos, dstArray->length, dstPos, length); 150 RETURN_VOID(); 151 } 152 153 ClassObject* srcClass = srcArray->clazz; 154 ClassObject* dstClass = dstArray->clazz; 155 char srcType = srcClass->descriptor[1]; 156 char dstType = dstClass->descriptor[1]; 157 158 /* 159 * If one of the arrays holds a primitive type, the other array must 160 * hold the same type. 161 */ 162 bool srcPrim = (srcType != '[' && srcType != 'L'); 163 bool dstPrim = (dstType != '[' && dstType != 'L'); 164 if (srcPrim || dstPrim) { 165 if (srcPrim != dstPrim || srcType != dstType) { 166 dvmThrowArrayStoreExceptionIncompatibleArrays(srcClass, dstClass); 167 RETURN_VOID(); 168 } 169 170 if (false) ALOGD("arraycopy prim[%c] dst=%p %d src=%p %d len=%d", 171 srcType, dstArray->contents, dstPos, 172 srcArray->contents, srcPos, length); 173 174 switch (srcType) { 175 case 'B': 176 case 'Z': 177 /* 1 byte per element */ 178 memmove((u1*) dstArray->contents + dstPos, 179 (const u1*) srcArray->contents + srcPos, 180 length); 181 break; 182 case 'C': 183 case 'S': 184 /* 2 bytes per element */ 185 move16((u1*) dstArray->contents + dstPos * 2, 186 (const u1*) srcArray->contents + srcPos * 2, 187 length * 2); 188 break; 189 case 'F': 190 case 'I': 191 /* 4 bytes per element */ 192 move32((u1*) dstArray->contents + dstPos * 4, 193 (const u1*) srcArray->contents + srcPos * 4, 194 length * 4); 195 break; 196 case 'D': 197 case 'J': 198 /* 199 * 8 bytes per element. We don't need to guarantee atomicity 200 * of the entire 64-bit word, so we can use the 32-bit copier. 201 */ 202 move32((u1*) dstArray->contents + dstPos * 8, 203 (const u1*) srcArray->contents + srcPos * 8, 204 length * 8); 205 break; 206 default: /* illegal array type */ 207 ALOGE("Weird array type '%s'", srcClass->descriptor); 208 dvmAbort(); 209 } 210 } else { 211 /* 212 * Neither class is primitive. See if elements in "src" are instances 213 * of elements in "dst" (e.g. copy String to String or String to 214 * Object). 215 */ 216 const int width = sizeof(Object*); 217 218 if (srcClass->arrayDim == dstClass->arrayDim && 219 dvmInstanceof(srcClass, dstClass)) 220 { 221 /* 222 * "dst" can hold "src"; copy the whole thing. 223 */ 224 if (false) ALOGD("arraycopy ref dst=%p %d src=%p %d len=%d", 225 dstArray->contents, dstPos * width, 226 srcArray->contents, srcPos * width, 227 length * width); 228 move32((u1*)dstArray->contents + dstPos * width, 229 (const u1*)srcArray->contents + srcPos * width, 230 length * width); 231 dvmWriteBarrierArray(dstArray, dstPos, dstPos+length); 232 } else { 233 /* 234 * The arrays are not fundamentally compatible. However, we 235 * may still be able to do this if the destination object is 236 * compatible (e.g. copy Object[] to String[], but the Object 237 * being copied is actually a String). We need to copy elements 238 * one by one until something goes wrong. 239 * 240 * Because of overlapping moves, what we really want to do 241 * is compare the types and count up how many we can move, 242 * then call move32() to shift the actual data. If we just 243 * start from the front we could do a smear rather than a move. 244 */ 245 Object** srcObj; 246 int copyCount; 247 ClassObject* clazz = NULL; 248 249 srcObj = ((Object**)(void*)srcArray->contents) + srcPos; 250 251 if (length > 0 && srcObj[0] != NULL) 252 { 253 clazz = srcObj[0]->clazz; 254 if (!dvmCanPutArrayElement(clazz, dstClass)) 255 clazz = NULL; 256 } 257 258 for (copyCount = 0; copyCount < length; copyCount++) 259 { 260 if (srcObj[copyCount] != NULL && 261 srcObj[copyCount]->clazz != clazz && 262 !dvmCanPutArrayElement(srcObj[copyCount]->clazz, dstClass)) 263 { 264 /* can't put this element into the array */ 265 break; 266 } 267 } 268 269 if (false) ALOGD("arraycopy iref dst=%p %d src=%p %d count=%d of %d", 270 dstArray->contents, dstPos * width, 271 srcArray->contents, srcPos * width, 272 copyCount, length); 273 move32((u1*)dstArray->contents + dstPos * width, 274 (const u1*)srcArray->contents + srcPos * width, 275 copyCount * width); 276 dvmWriteBarrierArray(dstArray, 0, copyCount); 277 if (copyCount != length) { 278 dvmThrowArrayStoreExceptionIncompatibleArrayElement(srcPos + copyCount, 279 srcObj[copyCount]->clazz, dstClass); 280 RETURN_VOID(); 281 } 282 } 283 } 284 285 RETURN_VOID(); 286 } 287 288 /* 289 * static long currentTimeMillis() 290 * 291 * Current time, in miliseconds. This doesn't need to be internal to the 292 * VM, but we're already handling java.lang.System here. 293 */ Dalvik_java_lang_System_currentTimeMillis(const u4 * args,JValue * pResult)294 static void Dalvik_java_lang_System_currentTimeMillis(const u4* args, 295 JValue* pResult) 296 { 297 struct timeval tv; 298 299 UNUSED_PARAMETER(args); 300 301 gettimeofday(&tv, (struct timezone *) NULL); 302 long long when = tv.tv_sec * 1000LL + tv.tv_usec / 1000; 303 304 RETURN_LONG(when); 305 } 306 307 /* 308 * static long nanoTime() 309 * 310 * Current monotonically-increasing time, in nanoseconds. This doesn't 311 * need to be internal to the VM, but we're already handling 312 * java.lang.System here. 313 */ Dalvik_java_lang_System_nanoTime(const u4 * args,JValue * pResult)314 static void Dalvik_java_lang_System_nanoTime(const u4* args, JValue* pResult) 315 { 316 UNUSED_PARAMETER(args); 317 318 u8 when = dvmGetRelativeTimeNsec(); 319 RETURN_LONG(when); 320 } 321 322 /* 323 * static int identityHashCode(Object x) 324 * 325 * Returns that hash code that the default hashCode() 326 * method would return for "x", even if "x"s class 327 * overrides hashCode(). 328 */ Dalvik_java_lang_System_identityHashCode(const u4 * args,JValue * pResult)329 static void Dalvik_java_lang_System_identityHashCode(const u4* args, 330 JValue* pResult) 331 { 332 Object* thisPtr = (Object*) args[0]; 333 RETURN_INT(dvmIdentityHashCode(thisPtr)); 334 } 335 Dalvik_java_lang_System_mapLibraryName(const u4 * args,JValue * pResult)336 static void Dalvik_java_lang_System_mapLibraryName(const u4* args, 337 JValue* pResult) 338 { 339 StringObject* nameObj = (StringObject*) args[0]; 340 StringObject* result = NULL; 341 char* name; 342 char* mappedName; 343 344 if (nameObj == NULL) { 345 dvmThrowNullPointerException("userLibName == null"); 346 RETURN_VOID(); 347 } 348 349 name = dvmCreateCstrFromString(nameObj); 350 mappedName = dvmCreateSystemLibraryName(name); 351 if (mappedName != NULL) { 352 result = dvmCreateStringFromCstr(mappedName); 353 dvmReleaseTrackedAlloc((Object*) result, NULL); 354 } 355 356 free(name); 357 free(mappedName); 358 RETURN_PTR(result); 359 } 360 361 const DalvikNativeMethod dvm_java_lang_System[] = { 362 { "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", 363 Dalvik_java_lang_System_arraycopy }, 364 { "currentTimeMillis", "()J", 365 Dalvik_java_lang_System_currentTimeMillis }, 366 { "identityHashCode", "(Ljava/lang/Object;)I", 367 Dalvik_java_lang_System_identityHashCode }, 368 { "mapLibraryName", "(Ljava/lang/String;)Ljava/lang/String;", 369 Dalvik_java_lang_System_mapLibraryName }, 370 { "nanoTime", "()J", 371 Dalvik_java_lang_System_nanoTime }, 372 { NULL, NULL, NULL }, 373 }; 374