Home | History | Annotate | Download | only in vm
      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,
    736         "Ljava/lang/String;", "charAt", "(I)C" },
    737     { javaLangString_compareTo,
    738         "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I" },
    739     { javaLangString_equals,
    740         "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" },
    741     { javaLangString_fastIndexOf_II,
    742         "Ljava/lang/String;", "fastIndexOf", "(II)I" },
    743     { javaLangString_isEmpty,
    744         "Ljava/lang/String;", "isEmpty", "()Z" },
    745     { javaLangString_length,
    746         "Ljava/lang/String;", "length", "()I" },
    747 
    748     { javaLangMath_abs_int,
    749         "Ljava/lang/Math;", "abs", "(I)I" },
    750     { javaLangMath_abs_long,
    751         "Ljava/lang/Math;", "abs", "(J)J" },
    752     { javaLangMath_abs_float,
    753         "Ljava/lang/Math;", "abs", "(F)F" },
    754     { javaLangMath_abs_double,
    755         "Ljava/lang/Math;", "abs", "(D)D" },
    756     { javaLangMath_min_int,
    757         "Ljava/lang/Math;", "min", "(II)I" },
    758     { javaLangMath_max_int,
    759         "Ljava/lang/Math;", "max", "(II)I" },
    760     { javaLangMath_sqrt,
    761         "Ljava/lang/Math;", "sqrt", "(D)D" },
    762     { javaLangMath_cos,
    763         "Ljava/lang/Math;", "cos", "(D)D" },
    764     { javaLangMath_sin,
    765         "Ljava/lang/Math;", "sin", "(D)D" },
    766 
    767     { javaLangFloat_floatToIntBits,
    768         "Ljava/lang/Float;", "floatToIntBits", "(F)I" },
    769     { javaLangFloat_floatToRawIntBits,
    770         "Ljava/lang/Float;", "floatToRawIntBits", "(F)I" },
    771     { javaLangFloat_intBitsToFloat,
    772         "Ljava/lang/Float;", "intBitsToFloat", "(I)F" },
    773 
    774     { javaLangDouble_doubleToLongBits,
    775         "Ljava/lang/Double;", "doubleToLongBits", "(D)J" },
    776     { javaLangDouble_doubleToRawLongBits,
    777         "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J" },
    778     { javaLangDouble_longBitsToDouble,
    779         "Ljava/lang/Double;", "longBitsToDouble", "(J)D" },
    780 };
    781 
    782 /*
    783  * Allocate some tables.
    784  */
    785 bool dvmInlineNativeStartup()
    786 {
    787     gDvm.inlinedMethods =
    788         (Method**) calloc(NELEM(gDvmInlineOpsTable), sizeof(Method*));
    789     if (gDvm.inlinedMethods == NULL)
    790         return false;
    791 
    792     return true;
    793 }
    794 
    795 /*
    796  * Free generated tables.
    797  */
    798 void dvmInlineNativeShutdown()
    799 {
    800     free(gDvm.inlinedMethods);
    801 }
    802 
    803 
    804 /*
    805  * Get a pointer to the inlineops table.
    806  */
    807 const InlineOperation* dvmGetInlineOpsTable()
    808 {
    809     return gDvmInlineOpsTable;
    810 }
    811 
    812 /*
    813  * Get the number of entries in the inlineops table.
    814  */
    815 int dvmGetInlineOpsTableLength()
    816 {
    817     return NELEM(gDvmInlineOpsTable);
    818 }
    819 
    820 Method* dvmFindInlinableMethod(const char* classDescriptor,
    821     const char* methodName, const char* methodSignature)
    822 {
    823     /*
    824      * Find the class.
    825      */
    826     ClassObject* clazz = dvmFindClassNoInit(classDescriptor, NULL);
    827     if (clazz == NULL) {
    828         ALOGE("dvmFindInlinableMethod: can't find class '%s'",
    829             classDescriptor);
    830         dvmClearException(dvmThreadSelf());
    831         return NULL;
    832     }
    833 
    834     /*
    835      * Method could be virtual or direct.  Try both.  Don't use
    836      * the "hier" versions.
    837      */
    838     Method* method = dvmFindDirectMethodByDescriptor(clazz, methodName,
    839         methodSignature);
    840     if (method == NULL) {
    841         method = dvmFindVirtualMethodByDescriptor(clazz, methodName,
    842             methodSignature);
    843     }
    844     if (method == NULL) {
    845         ALOGE("dvmFindInlinableMethod: can't find method %s.%s %s",
    846             clazz->descriptor, methodName, methodSignature);
    847         return NULL;
    848     }
    849 
    850     /*
    851      * Check that the method is appropriate for inlining.
    852      */
    853     if (!dvmIsFinalClass(clazz) && !dvmIsFinalMethod(method)) {
    854         ALOGE("dvmFindInlinableMethod: can't inline non-final method %s.%s",
    855             clazz->descriptor, method->name);
    856         return NULL;
    857     }
    858     if (dvmIsSynchronizedMethod(method) ||
    859             dvmIsDeclaredSynchronizedMethod(method)) {
    860         ALOGE("dvmFindInlinableMethod: can't inline synchronized method %s.%s",
    861             clazz->descriptor, method->name);
    862         return NULL;
    863     }
    864 
    865     return method;
    866 }
    867 
    868 /*
    869  * Populate the methods table on first use.  It's possible the class
    870  * hasn't been resolved yet, so we need to do the full "calling the
    871  * method for the first time" routine.  (It's probably okay to skip
    872  * the access checks.)
    873  *
    874  * Currently assuming that we're only inlining stuff loaded by the
    875  * bootstrap class loader.  This is a safe assumption for many reasons.
    876  */
    877 Method* dvmResolveInlineNative(int opIndex)
    878 {
    879     assert(opIndex >= 0 && opIndex < NELEM(gDvmInlineOpsTable));
    880     Method* method = gDvm.inlinedMethods[opIndex];
    881     if (method != NULL) {
    882         return method;
    883     }
    884 
    885     method = dvmFindInlinableMethod(
    886         gDvmInlineOpsTable[opIndex].classDescriptor,
    887         gDvmInlineOpsTable[opIndex].methodName,
    888         gDvmInlineOpsTable[opIndex].methodSignature);
    889 
    890     if (method == NULL) {
    891         /* We already reported the error. */
    892         return NULL;
    893     }
    894 
    895     gDvm.inlinedMethods[opIndex] = method;
    896     IF_ALOGV() {
    897         char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
    898         ALOGV("Registered for profile: %s.%s %s",
    899             method->clazz->descriptor, method->name, desc);
    900         free(desc);
    901     }
    902 
    903     return method;
    904 }
    905 
    906 /*
    907  * Make an inline call for the "debug" interpreter, used when the debugger
    908  * or profiler is active.
    909  */
    910 bool dvmPerformInlineOp4Dbg(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    911     JValue* pResult, int opIndex)
    912 {
    913     Method* method = dvmResolveInlineNative(opIndex);
    914     if (method == NULL) {
    915         return (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3,
    916             pResult);
    917     }
    918 
    919     Thread* self = dvmThreadSelf();
    920     TRACE_METHOD_ENTER(self, method);
    921     bool result = (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3,
    922         pResult);
    923     TRACE_METHOD_EXIT(self, method);
    924     return result;
    925 }
    926