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 * Inlined native functions. These definitions replace interpreted or 19 * native implementations at runtime; "intrinsic" might be a better word. 20 */ 21 #include "Dalvik.h" 22 23 #include <math.h> 24 25 #ifdef HAVE__MEMCMP16 26 /* hand-coded assembly implementation, available on some platforms */ 27 //#warning "trying memcmp16" 28 //#define CHECK_MEMCMP16 29 /* "count" is in 16-bit units */ 30 extern "C" u4 __memcmp16(const u2* s0, const u2* s1, size_t count); 31 #endif 32 33 /* 34 * Some notes on "inline" functions. 35 * 36 * These are NOT simply native implementations. A full method definition 37 * must still be provided. Depending on the flags passed into the VM 38 * at runtime, the original or inline version may be selected by the 39 * DEX optimizer. 40 * 41 * PLEASE DO NOT use this as the default location for native methods. 42 * The difference between this and an "internal native" static method 43 * call on a 200MHz ARM 9 is roughly 370ns vs. 700ns. The code here 44 * "secretly replaces" the other method, so you can't avoid having two 45 * implementations. Since the DEX optimizer mode can't be known ahead 46 * of time, both implementations must be correct and complete. 47 * 48 * The only stuff that really needs to be here are methods that 49 * are high-volume or must be low-overhead, e.g. certain String/Math 50 * methods and some java.util.concurrent.atomic operations. 51 * 52 * Normally, a class is loaded and initialized the first time a static 53 * method is invoked. This property is NOT preserved here. If you need 54 * to access a static field in a class, you must ensure initialization 55 * yourself (cheap/easy way is to check the resolved-methods table, and 56 * resolve the method if it hasn't been). 57 * 58 * DO NOT replace "synchronized" methods. We do not support method 59 * synchronization here. 60 * 61 * DO NOT perform any allocations or do anything that could cause a 62 * garbage collection. The method arguments are not visible to the GC 63 * and will not be pinned or updated when memory blocks move. You are 64 * allowed to allocate and throw an exception so long as you only do so 65 * immediately before returning. 66 * 67 * Remember that these functions are executing while the thread is in 68 * the "RUNNING" state, not the "NATIVE" state. If you perform a blocking 69 * operation you can stall the entire VM if the GC or debugger wants to 70 * suspend the thread. Since these are arguably native implementations 71 * rather than VM internals, prefer NATIVE to VMWAIT if you want to change 72 * the thread state. 73 * 74 * Always write results to 32-bit or 64-bit fields in "pResult", e.g. do 75 * not write boolean results to pResult->z. The interpreter expects 76 * 32 or 64 bits to be set. 77 * 78 * Inline op methods return "false" if an exception was thrown, "true" if 79 * everything went well. 80 * 81 * DO NOT provide implementations of methods that can be overridden by a 82 * subclass, as polymorphism does not work correctly. For safety you should 83 * only provide inline functions for classes/methods declared "final". 84 * 85 * It's best to avoid inlining the overridden version of a method. For 86 * example, String.hashCode() is inherited from Object.hashCode(). Code 87 * calling String.hashCode() through an Object reference will run the 88 * "slow" version, while calling it through a String reference gets 89 * the inlined version. It's best to have just one version unless there 90 * are clear performance gains. 91 * 92 * Because the actual method is not called, debugger breakpoints on these 93 * methods will not happen. (TODO: have the code here find the original 94 * method and call it when the debugger is active.) Additional steps have 95 * been taken to allow method profiling to produce correct results. 96 */ 97 98 99 /* 100 * =========================================================================== 101 * org.apache.harmony.dalvik.NativeTestTarget 102 * =========================================================================== 103 */ 104 105 /* 106 * public static void emptyInlineMethod 107 * 108 * This exists only for benchmarks. 109 */ 110 static bool org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod( 111 u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 112 { 113 // do nothing 114 return true; 115 } 116 117 118 /* 119 * =========================================================================== 120 * java.lang.String 121 * =========================================================================== 122 */ 123 124 /* 125 * public char charAt(int index) 126 */ 127 bool javaLangString_charAt(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 128 JValue* pResult) 129 { 130 int count, offset; 131 ArrayObject* chars; 132 133 /* null reference check on "this" */ 134 if ((Object*) arg0 == NULL) { 135 dvmThrowNullPointerException(NULL); 136 return false; 137 } 138 139 //ALOGI("String.charAt this=0x%08x index=%d", arg0, arg1); 140 count = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT); 141 if ((s4) arg1 < 0 || (s4) arg1 >= count) { 142 dvmThrowStringIndexOutOfBoundsExceptionWithIndex(count, arg1); 143 return false; 144 } else { 145 offset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET); 146 chars = (ArrayObject*) 147 dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE); 148 149 pResult->i = ((const u2*)(void*)chars->contents)[arg1 + offset]; 150 return true; 151 } 152 } 153 154 #ifdef CHECK_MEMCMP16 155 /* 156 * Utility function when we're evaluating alternative implementations. 157 */ 158 static void badMatch(StringObject* thisStrObj, StringObject* compStrObj, 159 int expectResult, int newResult, const char* compareType) 160 { 161 ArrayObject* thisArray; 162 ArrayObject* compArray; 163 const char* thisStr; 164 const char* compStr; 165 int thisOffset, compOffset, thisCount, compCount; 166 167 thisCount = 168 dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_COUNT); 169 compCount = 170 dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_COUNT); 171 thisOffset = 172 dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_OFFSET); 173 compOffset = 174 dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_OFFSET); 175 thisArray = (ArrayObject*) 176 dvmGetFieldObject((Object*) thisStrObj, STRING_FIELDOFF_VALUE); 177 compArray = (ArrayObject*) 178 dvmGetFieldObject((Object*) compStrObj, STRING_FIELDOFF_VALUE); 179 180 thisStr = dvmCreateCstrFromString(thisStrObj); 181 compStr = dvmCreateCstrFromString(compStrObj); 182 183 ALOGE("%s expected %d got %d", compareType, expectResult, newResult); 184 ALOGE(" this (o=%d l=%d) '%s'", thisOffset, thisCount, thisStr); 185 ALOGE(" comp (o=%d l=%d) '%s'", compOffset, compCount, compStr); 186 dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG, 187 ((const u2*) thisArray->contents) + thisOffset, thisCount*2, 188 kHexDumpLocal); 189 dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG, 190 ((const u2*) compArray->contents) + compOffset, compCount*2, 191 kHexDumpLocal); 192 dvmAbort(); 193 } 194 #endif 195 196 /* 197 * public int compareTo(String s) 198 */ 199 bool javaLangString_compareTo(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 200 JValue* pResult) 201 { 202 /* 203 * Null reference check on "this". Normally this is performed during 204 * the setup of the virtual method call. We need to do it before 205 * anything else. While we're at it, check out the other string, 206 * which must also be non-null. 207 */ 208 if ((Object*) arg0 == NULL || (Object*) arg1 == NULL) { 209 dvmThrowNullPointerException(NULL); 210 return false; 211 } 212 213 /* quick test for comparison with itself */ 214 if (arg0 == arg1) { 215 pResult->i = 0; 216 return true; 217 } 218 219 /* 220 * This would be simpler and faster if we promoted StringObject to 221 * a full representation, lining up the C structure fields with the 222 * actual object fields. 223 */ 224 int thisCount, thisOffset, compCount, compOffset; 225 ArrayObject* thisArray; 226 ArrayObject* compArray; 227 const u2* thisChars; 228 const u2* compChars; 229 int minCount, countDiff; 230 231 thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT); 232 compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT); 233 countDiff = thisCount - compCount; 234 minCount = (countDiff < 0) ? thisCount : compCount; 235 thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET); 236 compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET); 237 thisArray = (ArrayObject*) 238 dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE); 239 compArray = (ArrayObject*) 240 dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE); 241 thisChars = ((const u2*)(void*)thisArray->contents) + thisOffset; 242 compChars = ((const u2*)(void*)compArray->contents) + compOffset; 243 244 #ifdef HAVE__MEMCMP16 245 /* 246 * Use assembly version, which returns the difference between the 247 * characters. The annoying part here is that 0x00e9 - 0xffff != 0x00ea, 248 * because the interpreter converts the characters to 32-bit integers 249 * *without* sign extension before it subtracts them (which makes some 250 * sense since "char" is unsigned). So what we get is the result of 251 * 0x000000e9 - 0x0000ffff, which is 0xffff00ea. 252 */ 253 int otherRes = __memcmp16(thisChars, compChars, minCount); 254 # ifdef CHECK_MEMCMP16 255 int i; 256 for (i = 0; i < minCount; i++) { 257 if (thisChars[i] != compChars[i]) { 258 pResult->i = (s4) thisChars[i] - (s4) compChars[i]; 259 if (pResult->i != otherRes) { 260 badMatch((StringObject*) arg0, (StringObject*) arg1, 261 pResult->i, otherRes, "compareTo"); 262 } 263 return true; 264 } 265 } 266 # endif 267 if (otherRes != 0) { 268 pResult->i = otherRes; 269 return true; 270 } 271 272 #else 273 /* 274 * Straightforward implementation, examining 16 bits at a time. Compare 275 * the characters that overlap, and if they're all the same then return 276 * the difference in lengths. 277 */ 278 int i; 279 for (i = 0; i < minCount; i++) { 280 if (thisChars[i] != compChars[i]) { 281 pResult->i = (s4) thisChars[i] - (s4) compChars[i]; 282 return true; 283 } 284 } 285 #endif 286 287 pResult->i = countDiff; 288 return true; 289 } 290 291 /* 292 * public boolean equals(Object anObject) 293 */ 294 bool javaLangString_equals(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 295 JValue* pResult) 296 { 297 /* 298 * Null reference check on "this". 299 */ 300 if ((Object*) arg0 == NULL) { 301 dvmThrowNullPointerException(NULL); 302 return false; 303 } 304 305 /* quick test for comparison with itself */ 306 if (arg0 == arg1) { 307 pResult->i = true; 308 return true; 309 } 310 311 /* 312 * See if the other object is also a String. 313 * 314 * str.equals(null) is expected to return false, presumably based on 315 * the results of the instanceof test. 316 */ 317 if (arg1 == 0 || ((Object*) arg0)->clazz != ((Object*) arg1)->clazz) { 318 pResult->i = false; 319 return true; 320 } 321 322 /* 323 * This would be simpler and faster if we promoted StringObject to 324 * a full representation, lining up the C structure fields with the 325 * actual object fields. 326 */ 327 int thisCount, thisOffset, compCount, compOffset; 328 ArrayObject* thisArray; 329 ArrayObject* compArray; 330 const u2* thisChars; 331 const u2* compChars; 332 333 /* quick length check */ 334 thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT); 335 compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT); 336 if (thisCount != compCount) { 337 pResult->i = false; 338 return true; 339 } 340 341 /* 342 * You may, at this point, be tempted to pull out the hashCode fields 343 * and compare them. If both fields have been initialized, and they 344 * are not equal, we can return false immediately. 345 * 346 * However, the hashCode field is often not set. If it is set, 347 * there's an excellent chance that the String is being used as a key 348 * in a hashed data structure (e.g. HashMap). That data structure has 349 * already made the comparison and determined that the hashes are equal, 350 * making a check here redundant. 351 * 352 * It's not clear that checking the hashes will be a win in "typical" 353 * use cases. We err on the side of simplicity and ignore them. 354 */ 355 356 thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET); 357 compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET); 358 thisArray = (ArrayObject*) 359 dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE); 360 compArray = (ArrayObject*) 361 dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE); 362 thisChars = ((const u2*)(void*)thisArray->contents) + thisOffset; 363 compChars = ((const u2*)(void*)compArray->contents) + compOffset; 364 365 #ifdef HAVE__MEMCMP16 366 pResult->i = (__memcmp16(thisChars, compChars, thisCount) == 0); 367 # ifdef CHECK_MEMCMP16 368 int otherRes = (memcmp(thisChars, compChars, thisCount * 2) == 0); 369 if (pResult->i != otherRes) { 370 badMatch((StringObject*) arg0, (StringObject*) arg1, 371 otherRes, pResult->i, "equals-1"); 372 } 373 # endif 374 #else 375 /* 376 * Straightforward implementation, examining 16 bits at a time. The 377 * direction of the loop doesn't matter, and starting at the end may 378 * give us an advantage when comparing certain types of strings (e.g. 379 * class names). 380 * 381 * We want to go forward for benchmarks against __memcmp16 so we get a 382 * meaningful comparison when the strings don't match (could also test 383 * with palindromes). 384 */ 385 int i; 386 //for (i = 0; i < thisCount; i++) 387 for (i = thisCount-1; i >= 0; --i) 388 { 389 if (thisChars[i] != compChars[i]) { 390 pResult->i = false; 391 return true; 392 } 393 } 394 pResult->i = true; 395 #endif 396 397 return true; 398 } 399 400 /* 401 * public int length() 402 */ 403 bool javaLangString_length(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 404 JValue* pResult) 405 { 406 //ALOGI("String.length this=0x%08x pResult=%p", arg0, pResult); 407 408 /* null reference check on "this" */ 409 if ((Object*) arg0 == NULL) { 410 dvmThrowNullPointerException(NULL); 411 return false; 412 } 413 414 pResult->i = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT); 415 return true; 416 } 417 418 /* 419 * public boolean isEmpty() 420 */ 421 bool javaLangString_isEmpty(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 422 JValue* pResult) 423 { 424 //ALOGI("String.isEmpty this=0x%08x pResult=%p", arg0, pResult); 425 426 /* null reference check on "this" */ 427 if ((Object*) arg0 == NULL) { 428 dvmThrowNullPointerException(NULL); 429 return false; 430 } 431 432 pResult->i = (dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT) == 0); 433 return true; 434 } 435 436 /* 437 * Determine the index of the first character matching "ch". The string 438 * to search is described by "chars", "offset", and "count". 439 * 440 * The character must be <= 0xffff. Supplementary characters are handled in 441 * Java. 442 * 443 * The "start" parameter must be clamped to [0..count]. 444 * 445 * Returns -1 if no match is found. 446 */ 447 static inline int indexOfCommon(Object* strObj, int ch, int start) 448 { 449 //if ((ch & 0xffff) != ch) /* 32-bit code point */ 450 // return -1; 451 452 /* pull out the basic elements */ 453 ArrayObject* charArray = 454 (ArrayObject*) dvmGetFieldObject(strObj, STRING_FIELDOFF_VALUE); 455 const u2* chars = (const u2*)(void*)charArray->contents; 456 int offset = dvmGetFieldInt(strObj, STRING_FIELDOFF_OFFSET); 457 int count = dvmGetFieldInt(strObj, STRING_FIELDOFF_COUNT); 458 //ALOGI("String.indexOf(0x%08x, 0x%04x, %d) off=%d count=%d", 459 // (u4) strObj, ch, start, offset, count); 460 461 /* factor out the offset */ 462 chars += offset; 463 464 if (start < 0) 465 start = 0; 466 else if (start > count) 467 start = count; 468 469 #if 0 470 /* 16-bit loop, simple */ 471 while (start < count) { 472 if (chars[start] == ch) 473 return start; 474 start++; 475 } 476 #else 477 /* 16-bit loop, slightly better on ARM */ 478 const u2* ptr = chars + start; 479 const u2* endPtr = chars + count; 480 while (ptr < endPtr) { 481 if (*ptr++ == ch) 482 return (ptr-1) - chars; 483 } 484 #endif 485 486 return -1; 487 } 488 489 /* 490 * public int indexOf(int c, int start) 491 * 492 * Scan forward through the string for a matching character. 493 * The character must be <= 0xffff; this method does not handle supplementary 494 * characters. 495 */ 496 bool javaLangString_fastIndexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 497 JValue* pResult) 498 { 499 /* null reference check on "this" */ 500 if ((Object*) arg0 == NULL) { 501 dvmThrowNullPointerException(NULL); 502 return false; 503 } 504 505 pResult->i = indexOfCommon((Object*) arg0, arg1, arg2); 506 return true; 507 } 508 509 510 /* 511 * =========================================================================== 512 * java.lang.Math 513 * =========================================================================== 514 */ 515 516 union Convert32 { 517 u4 arg; 518 float ff; 519 }; 520 521 union Convert64 { 522 u4 arg[2]; 523 s8 ll; 524 double dd; 525 }; 526 527 /* 528 * public static int abs(int) 529 */ 530 bool javaLangMath_abs_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 531 JValue* pResult) 532 { 533 s4 val = (s4) arg0; 534 pResult->i = (val >= 0) ? val : -val; 535 return true; 536 } 537 538 /* 539 * public static long abs(long) 540 */ 541 bool javaLangMath_abs_long(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 542 JValue* pResult) 543 { 544 Convert64 convert; 545 convert.arg[0] = arg0; 546 convert.arg[1] = arg1; 547 s8 val = convert.ll; 548 pResult->j = (val >= 0) ? val : -val; 549 return true; 550 } 551 552 /* 553 * public static float abs(float) 554 */ 555 bool javaLangMath_abs_float(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 556 JValue* pResult) 557 { 558 Convert32 convert; 559 /* clear the sign bit; assumes a fairly common fp representation */ 560 convert.arg = arg0 & 0x7fffffff; 561 pResult->f = convert.ff; 562 return true; 563 } 564 565 /* 566 * public static double abs(double) 567 */ 568 bool javaLangMath_abs_double(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 569 JValue* pResult) 570 { 571 Convert64 convert; 572 convert.arg[0] = arg0; 573 convert.arg[1] = arg1; 574 /* clear the sign bit in the (endian-dependent) high word */ 575 convert.ll &= 0x7fffffffffffffffULL; 576 pResult->d = convert.dd; 577 return true; 578 } 579 580 /* 581 * public static int min(int) 582 */ 583 bool javaLangMath_min_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 584 JValue* pResult) 585 { 586 pResult->i = ((s4) arg0 < (s4) arg1) ? arg0 : arg1; 587 return true; 588 } 589 590 /* 591 * public static int max(int) 592 */ 593 bool javaLangMath_max_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 594 JValue* pResult) 595 { 596 pResult->i = ((s4) arg0 > (s4) arg1) ? arg0 : arg1; 597 return true; 598 } 599 600 /* 601 * public static double sqrt(double) 602 * 603 * With ARM VFP enabled, gcc turns this into an fsqrtd instruction, followed 604 * by an fcmpd of the result against itself. If it doesn't match (i.e. 605 * it's NaN), the libm sqrt() is invoked. 606 */ 607 bool javaLangMath_sqrt(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 608 JValue* pResult) 609 { 610 Convert64 convert; 611 convert.arg[0] = arg0; 612 convert.arg[1] = arg1; 613 pResult->d = sqrt(convert.dd); 614 return true; 615 } 616 617 /* 618 * public static double cos(double) 619 */ 620 bool javaLangMath_cos(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 621 JValue* pResult) 622 { 623 Convert64 convert; 624 convert.arg[0] = arg0; 625 convert.arg[1] = arg1; 626 pResult->d = cos(convert.dd); 627 return true; 628 } 629 630 /* 631 * public static double sin(double) 632 */ 633 bool javaLangMath_sin(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 634 JValue* pResult) 635 { 636 Convert64 convert; 637 convert.arg[0] = arg0; 638 convert.arg[1] = arg1; 639 pResult->d = sin(convert.dd); 640 return true; 641 } 642 643 /* 644 * =========================================================================== 645 * java.lang.Float 646 * =========================================================================== 647 */ 648 649 bool javaLangFloat_floatToIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg, 650 JValue* pResult) 651 { 652 Convert32 convert; 653 convert.arg = arg0; 654 pResult->i = isnanf(convert.ff) ? 0x7fc00000 : arg0; 655 return true; 656 } 657 658 bool javaLangFloat_floatToRawIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg, 659 JValue* pResult) 660 { 661 pResult->i = arg0; 662 return true; 663 } 664 665 bool javaLangFloat_intBitsToFloat(u4 arg0, u4 arg1, u4 arg2, u4 arg, 666 JValue* pResult) 667 { 668 Convert32 convert; 669 convert.arg = arg0; 670 pResult->f = convert.ff; 671 return true; 672 } 673 674 /* 675 * =========================================================================== 676 * java.lang.Double 677 * =========================================================================== 678 */ 679 680 bool javaLangDouble_doubleToLongBits(u4 arg0, u4 arg1, u4 arg2, u4 arg, 681 JValue* pResult) 682 { 683 Convert64 convert; 684 convert.arg[0] = arg0; 685 convert.arg[1] = arg1; 686 pResult->j = isnan(convert.dd) ? 0x7ff8000000000000LL : convert.ll; 687 return true; 688 } 689 690 bool javaLangDouble_doubleToRawLongBits(u4 arg0, u4 arg1, u4 arg2, 691 u4 arg, JValue* pResult) 692 { 693 Convert64 convert; 694 convert.arg[0] = arg0; 695 convert.arg[1] = arg1; 696 pResult->j = convert.ll; 697 return true; 698 } 699 700 bool javaLangDouble_longBitsToDouble(u4 arg0, u4 arg1, u4 arg2, u4 arg, 701 JValue* pResult) 702 { 703 Convert64 convert; 704 convert.arg[0] = arg0; 705 convert.arg[1] = arg1; 706 pResult->d = convert.dd; 707 return true; 708 } 709 710 /* 711 * =========================================================================== 712 * Infrastructure 713 * =========================================================================== 714 */ 715 716 /* 717 * Table of methods. 718 * 719 * The DEX optimizer uses the class/method/signature string fields to decide 720 * which calls it can trample. The interpreter just uses the function 721 * pointer field. 722 * 723 * IMPORTANT: you must update DALVIK_VM_BUILD in DalvikVersion.h if you make 724 * changes to this table. 725 * 726 * NOTE: If present, the JIT will also need to know about changes 727 * to this table. Update the NativeInlineOps enum in InlineNative.h and 728 * the dispatch code in compiler/codegen/<target>/Codegen.c. 729 */ 730 const InlineOperation gDvmInlineOpsTable[] = { 731 { org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod, 732 "Lorg/apache/harmony/dalvik/NativeTestTarget;", 733 "emptyInlineMethod", "()V" }, 734 735 { javaLangString_charAt, "Ljava/lang/String;", "charAt", "(I)C" }, 736 { javaLangString_compareTo, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I" }, 737 { javaLangString_equals, "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" }, 738 { javaLangString_fastIndexOf_II, "Ljava/lang/String;", "fastIndexOf", "(II)I" }, 739 { javaLangString_isEmpty, "Ljava/lang/String;", "isEmpty", "()Z" }, 740 { javaLangString_length, "Ljava/lang/String;", "length", "()I" }, 741 742 { javaLangMath_abs_int, "Ljava/lang/Math;", "abs", "(I)I" }, 743 { javaLangMath_abs_long, "Ljava/lang/Math;", "abs", "(J)J" }, 744 { javaLangMath_abs_float, "Ljava/lang/Math;", "abs", "(F)F" }, 745 { javaLangMath_abs_double, "Ljava/lang/Math;", "abs", "(D)D" }, 746 { javaLangMath_min_int, "Ljava/lang/Math;", "min", "(II)I" }, 747 { javaLangMath_max_int, "Ljava/lang/Math;", "max", "(II)I" }, 748 { javaLangMath_sqrt, "Ljava/lang/Math;", "sqrt", "(D)D" }, 749 { javaLangMath_cos, "Ljava/lang/Math;", "cos", "(D)D" }, 750 { javaLangMath_sin, "Ljava/lang/Math;", "sin", "(D)D" }, 751 752 { javaLangFloat_floatToIntBits, "Ljava/lang/Float;", "floatToIntBits", "(F)I" }, 753 { javaLangFloat_floatToRawIntBits, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I" }, 754 { javaLangFloat_intBitsToFloat, "Ljava/lang/Float;", "intBitsToFloat", "(I)F" }, 755 756 { javaLangDouble_doubleToLongBits, "Ljava/lang/Double;", "doubleToLongBits", "(D)J" }, 757 { javaLangDouble_doubleToRawLongBits, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J" }, 758 { javaLangDouble_longBitsToDouble, "Ljava/lang/Double;", "longBitsToDouble", "(J)D" }, 759 760 // These are implemented exactly the same in Math and StrictMath, 761 // so we can make the StrictMath calls fast too. Note that this 762 // isn't true in general! 763 { javaLangMath_abs_int, "Ljava/lang/StrictMath;", "abs", "(I)I" }, 764 { javaLangMath_abs_long, "Ljava/lang/StrictMath;", "abs", "(J)J" }, 765 { javaLangMath_abs_float, "Ljava/lang/StrictMath;", "abs", "(F)F" }, 766 { javaLangMath_abs_double, "Ljava/lang/StrictMath;", "abs", "(D)D" }, 767 { javaLangMath_min_int, "Ljava/lang/StrictMath;", "min", "(II)I" }, 768 { javaLangMath_max_int, "Ljava/lang/StrictMath;", "max", "(II)I" }, 769 { javaLangMath_sqrt, "Ljava/lang/StrictMath;", "sqrt", "(D)D" }, 770 }; 771 772 /* 773 * Allocate some tables. 774 */ 775 bool dvmInlineNativeStartup() 776 { 777 gDvm.inlinedMethods = 778 (Method**) calloc(NELEM(gDvmInlineOpsTable), sizeof(Method*)); 779 if (gDvm.inlinedMethods == NULL) 780 return false; 781 782 return true; 783 } 784 785 /* 786 * Free generated tables. 787 */ 788 void dvmInlineNativeShutdown() 789 { 790 free(gDvm.inlinedMethods); 791 } 792 793 794 /* 795 * Get a pointer to the inlineops table. 796 */ 797 const InlineOperation* dvmGetInlineOpsTable() 798 { 799 return gDvmInlineOpsTable; 800 } 801 802 /* 803 * Get the number of entries in the inlineops table. 804 */ 805 int dvmGetInlineOpsTableLength() 806 { 807 return NELEM(gDvmInlineOpsTable); 808 } 809 810 Method* dvmFindInlinableMethod(const char* classDescriptor, 811 const char* methodName, const char* methodSignature) 812 { 813 /* 814 * Find the class. 815 */ 816 ClassObject* clazz = dvmFindClassNoInit(classDescriptor, NULL); 817 if (clazz == NULL) { 818 ALOGE("dvmFindInlinableMethod: can't find class '%s'", 819 classDescriptor); 820 dvmClearException(dvmThreadSelf()); 821 return NULL; 822 } 823 824 /* 825 * Method could be virtual or direct. Try both. Don't use 826 * the "hier" versions. 827 */ 828 Method* method = dvmFindDirectMethodByDescriptor(clazz, methodName, 829 methodSignature); 830 if (method == NULL) { 831 method = dvmFindVirtualMethodByDescriptor(clazz, methodName, 832 methodSignature); 833 } 834 if (method == NULL) { 835 ALOGE("dvmFindInlinableMethod: can't find method %s.%s %s", 836 clazz->descriptor, methodName, methodSignature); 837 return NULL; 838 } 839 840 /* 841 * Check that the method is appropriate for inlining. 842 */ 843 if (!dvmIsFinalClass(clazz) && !dvmIsFinalMethod(method)) { 844 ALOGE("dvmFindInlinableMethod: can't inline non-final method %s.%s", 845 clazz->descriptor, method->name); 846 return NULL; 847 } 848 if (dvmIsSynchronizedMethod(method) || 849 dvmIsDeclaredSynchronizedMethod(method)) { 850 ALOGE("dvmFindInlinableMethod: can't inline synchronized method %s.%s", 851 clazz->descriptor, method->name); 852 return NULL; 853 } 854 855 return method; 856 } 857 858 /* 859 * Populate the methods table on first use. It's possible the class 860 * hasn't been resolved yet, so we need to do the full "calling the 861 * method for the first time" routine. (It's probably okay to skip 862 * the access checks.) 863 * 864 * Currently assuming that we're only inlining stuff loaded by the 865 * bootstrap class loader. This is a safe assumption for many reasons. 866 */ 867 Method* dvmResolveInlineNative(int opIndex) 868 { 869 assert(opIndex >= 0 && opIndex < NELEM(gDvmInlineOpsTable)); 870 Method* method = gDvm.inlinedMethods[opIndex]; 871 if (method != NULL) { 872 return method; 873 } 874 875 method = dvmFindInlinableMethod( 876 gDvmInlineOpsTable[opIndex].classDescriptor, 877 gDvmInlineOpsTable[opIndex].methodName, 878 gDvmInlineOpsTable[opIndex].methodSignature); 879 880 if (method == NULL) { 881 /* We already reported the error. */ 882 return NULL; 883 } 884 885 gDvm.inlinedMethods[opIndex] = method; 886 IF_ALOGV() { 887 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 888 ALOGV("Registered for profile: %s.%s %s", 889 method->clazz->descriptor, method->name, desc); 890 free(desc); 891 } 892 893 return method; 894 } 895 896 /* 897 * Make an inline call for the "debug" interpreter, used when the debugger 898 * or profiler is active. 899 */ 900 bool dvmPerformInlineOp4Dbg(u4 arg0, u4 arg1, u4 arg2, u4 arg3, 901 JValue* pResult, int opIndex) 902 { 903 Method* method = dvmResolveInlineNative(opIndex); 904 if (method == NULL) { 905 return (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, 906 pResult); 907 } 908 909 Thread* self = dvmThreadSelf(); 910 TRACE_METHOD_ENTER(self, method); 911 bool result = (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, 912 pResult); 913 TRACE_METHOD_EXIT(self, method); 914 return result; 915 } 916