PageRenderTime 60ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/native/java_lang_System.cpp

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