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 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 static 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 (!dvmValidateObject((Object*) arg0))
    135         return false;
    136 
    137     //LOGI("String.charAt this=0x%08x index=%d\n", arg0, arg1);
    138     count = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
    139     if ((s4) arg1 < 0 || (s4) arg1 >= count) {
    140         dvmThrowException("Ljava/lang/StringIndexOutOfBoundsException;", NULL);
    141         return false;
    142     } else {
    143         offset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
    144         chars = (ArrayObject*)
    145             dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
    146 
    147         pResult->i = ((const u2*) chars->contents)[arg1 + offset];
    148         return true;
    149     }
    150 }
    151 
    152 #ifdef CHECK_MEMCMP16
    153 /*
    154  * Utility function when we're evaluating alternative implementations.
    155  */
    156 static void badMatch(StringObject* thisStrObj, StringObject* compStrObj,
    157     int expectResult, int newResult, const char* compareType)
    158 {
    159     ArrayObject* thisArray;
    160     ArrayObject* compArray;
    161     const char* thisStr;
    162     const char* compStr;
    163     int thisOffset, compOffset, thisCount, compCount;
    164 
    165     thisCount =
    166         dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_COUNT);
    167     compCount =
    168         dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_COUNT);
    169     thisOffset =
    170         dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_OFFSET);
    171     compOffset =
    172         dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_OFFSET);
    173     thisArray = (ArrayObject*)
    174         dvmGetFieldObject((Object*) thisStrObj, STRING_FIELDOFF_VALUE);
    175     compArray = (ArrayObject*)
    176         dvmGetFieldObject((Object*) compStrObj, STRING_FIELDOFF_VALUE);
    177 
    178     thisStr = dvmCreateCstrFromString(thisStrObj);
    179     compStr = dvmCreateCstrFromString(compStrObj);
    180 
    181     LOGE("%s expected %d got %d\n", compareType, expectResult, newResult);
    182     LOGE(" this (o=%d l=%d) '%s'\n", thisOffset, thisCount, thisStr);
    183     LOGE(" comp (o=%d l=%d) '%s'\n", compOffset, compCount, compStr);
    184     dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG,
    185         ((const u2*) thisArray->contents) + thisOffset, thisCount*2,
    186         kHexDumpLocal);
    187     dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG,
    188         ((const u2*) compArray->contents) + compOffset, compCount*2,
    189         kHexDumpLocal);
    190     dvmAbort();
    191 }
    192 #endif
    193 
    194 /*
    195  * public int compareTo(String s)
    196  */
    197 static bool javaLangString_compareTo(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    198     JValue* pResult)
    199 {
    200     /*
    201      * Null reference check on "this".  Normally this is performed during
    202      * the setup of the virtual method call.  We need to do it before
    203      * anything else.  While we're at it, check out the other string,
    204      * which must also be non-null.
    205      */
    206     if (!dvmValidateObject((Object*) arg0) ||
    207         !dvmValidateObject((Object*) arg1))
    208     {
    209         return false;
    210     }
    211 
    212     /* quick test for comparison with itself */
    213     if (arg0 == arg1) {
    214         pResult->i = 0;
    215         return true;
    216     }
    217 
    218     /*
    219      * This would be simpler and faster if we promoted StringObject to
    220      * a full representation, lining up the C structure fields with the
    221      * actual object fields.
    222      */
    223     int thisCount, thisOffset, compCount, compOffset;
    224     ArrayObject* thisArray;
    225     ArrayObject* compArray;
    226     const u2* thisChars;
    227     const u2* compChars;
    228     int minCount, countDiff;
    229 
    230     thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
    231     compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT);
    232     countDiff = thisCount - compCount;
    233     minCount = (countDiff < 0) ? thisCount : compCount;
    234     thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
    235     compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET);
    236     thisArray = (ArrayObject*)
    237         dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
    238     compArray = (ArrayObject*)
    239         dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
    240     thisChars = ((const u2*) thisArray->contents) + thisOffset;
    241     compChars = ((const u2*) compArray->contents) + compOffset;
    242 
    243 #ifdef HAVE__MEMCMP16
    244     /*
    245      * Use assembly version, which returns the difference between the
    246      * characters.  The annoying part here is that 0x00e9 - 0xffff != 0x00ea,
    247      * because the interpreter converts the characters to 32-bit integers
    248      * *without* sign extension before it subtracts them (which makes some
    249      * sense since "char" is unsigned).  So what we get is the result of
    250      * 0x000000e9 - 0x0000ffff, which is 0xffff00ea.
    251      */
    252     int otherRes = __memcmp16(thisChars, compChars, minCount);
    253 # ifdef CHECK_MEMCMP16
    254     int i;
    255     for (i = 0; i < minCount; i++) {
    256         if (thisChars[i] != compChars[i]) {
    257             pResult->i = (s4) thisChars[i] - (s4) compChars[i];
    258             if (pResult->i != otherRes) {
    259                 badMatch((StringObject*) arg0, (StringObject*) arg1,
    260                     pResult->i, otherRes, "compareTo");
    261             }
    262             return true;
    263         }
    264     }
    265 # endif
    266     if (otherRes != 0) {
    267         pResult->i = otherRes;
    268         return true;
    269     }
    270 
    271 #else
    272     /*
    273      * Straightforward implementation, examining 16 bits at a time.  Compare
    274      * the characters that overlap, and if they're all the same then return
    275      * the difference in lengths.
    276      */
    277     int i;
    278     for (i = 0; i < minCount; i++) {
    279         if (thisChars[i] != compChars[i]) {
    280             pResult->i = (s4) thisChars[i] - (s4) compChars[i];
    281             return true;
    282         }
    283     }
    284 #endif
    285 
    286     pResult->i = countDiff;
    287     return true;
    288 }
    289 
    290 /*
    291  * public boolean equals(Object anObject)
    292  */
    293 static bool javaLangString_equals(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    294     JValue* pResult)
    295 {
    296     /*
    297      * Null reference check on "this".
    298      */
    299     if (!dvmValidateObject((Object*) arg0))
    300         return false;
    301 
    302     /* quick test for comparison with itself */
    303     if (arg0 == arg1) {
    304         pResult->i = true;
    305         return true;
    306     }
    307 
    308     /*
    309      * See if the other object is also a String.
    310      *
    311      * str.equals(null) is expected to return false, presumably based on
    312      * the results of the instanceof test.
    313      */
    314     if (arg1 == 0 || ((Object*) arg0)->clazz != ((Object*) arg1)->clazz) {
    315         pResult->i = false;
    316         return true;
    317     }
    318 
    319     /*
    320      * This would be simpler and faster if we promoted StringObject to
    321      * a full representation, lining up the C structure fields with the
    322      * actual object fields.
    323      */
    324     int thisCount, thisOffset, compCount, compOffset;
    325     ArrayObject* thisArray;
    326     ArrayObject* compArray;
    327     const u2* thisChars;
    328     const u2* compChars;
    329 
    330     /* quick length check */
    331     thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
    332     compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT);
    333     if (thisCount != compCount) {
    334         pResult->i = false;
    335         return true;
    336     }
    337 
    338     thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
    339     compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET);
    340     thisArray = (ArrayObject*)
    341         dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
    342     compArray = (ArrayObject*)
    343         dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
    344     thisChars = ((const u2*) thisArray->contents) + thisOffset;
    345     compChars = ((const u2*) compArray->contents) + compOffset;
    346 
    347 #ifdef HAVE__MEMCMP16
    348     pResult->i = (__memcmp16(thisChars, compChars, thisCount) == 0);
    349 # ifdef CHECK_MEMCMP16
    350     int otherRes = (memcmp(thisChars, compChars, thisCount * 2) == 0);
    351     if (pResult->i != otherRes) {
    352         badMatch((StringObject*) arg0, (StringObject*) arg1,
    353             otherRes, pResult->i, "equals-1");
    354     }
    355 # endif
    356 #else
    357     /*
    358      * Straightforward implementation, examining 16 bits at a time.  The
    359      * direction of the loop doesn't matter, and starting at the end may
    360      * give us an advantage when comparing certain types of strings (e.g.
    361      * class names).
    362      *
    363      * We want to go forward for benchmarks against __memcmp16 so we get a
    364      * meaningful comparison when the strings don't match (could also test
    365      * with palindromes).
    366      */
    367     int i;
    368     //for (i = 0; i < thisCount; i++)
    369     for (i = thisCount-1; i >= 0; --i)
    370     {
    371         if (thisChars[i] != compChars[i]) {
    372             pResult->i = false;
    373             return true;
    374         }
    375     }
    376     pResult->i = true;
    377 #endif
    378 
    379     return true;
    380 }
    381 
    382 /*
    383  * public int length()
    384  */
    385 static bool javaLangString_length(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    386     JValue* pResult)
    387 {
    388     //LOGI("String.length this=0x%08x pResult=%p\n", arg0, pResult);
    389 
    390     /* null reference check on "this" */
    391     if (!dvmValidateObject((Object*) arg0))
    392         return false;
    393 
    394     pResult->i = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
    395     return true;
    396 }
    397 
    398 /*
    399  * public boolean isEmpty()
    400  */
    401 static bool javaLangString_isEmpty(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    402     JValue* pResult)
    403 {
    404     //LOGI("String.isEmpty this=0x%08x pResult=%p\n", arg0, pResult);
    405 
    406     /* null reference check on "this" */
    407     if (!dvmValidateObject((Object*) arg0))
    408         return false;
    409 
    410     pResult->i = (dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT) == 0);
    411     return true;
    412 }
    413 
    414 /*
    415  * Determine the index of the first character matching "ch".  The string
    416  * to search is described by "chars", "offset", and "count".
    417  *
    418  * The character must be <= 0xffff. Supplementary characters are handled in
    419  * Java.
    420  *
    421  * The "start" parameter must be clamped to [0..count].
    422  *
    423  * Returns -1 if no match is found.
    424  */
    425 static inline int indexOfCommon(Object* strObj, int ch, int start)
    426 {
    427     //if ((ch & 0xffff) != ch)        /* 32-bit code point */
    428     //    return -1;
    429 
    430     /* pull out the basic elements */
    431     ArrayObject* charArray =
    432         (ArrayObject*) dvmGetFieldObject(strObj, STRING_FIELDOFF_VALUE);
    433     const u2* chars = (const u2*) charArray->contents;
    434     int offset = dvmGetFieldInt(strObj, STRING_FIELDOFF_OFFSET);
    435     int count = dvmGetFieldInt(strObj, STRING_FIELDOFF_COUNT);
    436     //LOGI("String.indexOf(0x%08x, 0x%04x, %d) off=%d count=%d\n",
    437     //    (u4) strObj, ch, start, offset, count);
    438 
    439     /* factor out the offset */
    440     chars += offset;
    441 
    442     if (start < 0)
    443         start = 0;
    444 
    445 #if 0
    446     /* 16-bit loop, simple */
    447     while (start < count) {
    448         if (chars[start] == ch)
    449             return start;
    450         start++;
    451     }
    452 #else
    453     /* 16-bit loop, slightly better on ARM */
    454     const u2* ptr = chars + start;
    455     const u2* endPtr = chars + count;
    456     while (ptr < endPtr) {
    457         if (*ptr++ == ch)
    458             return (ptr-1) - chars;
    459     }
    460 #endif
    461 
    462     return -1;
    463 }
    464 
    465 /*
    466  * public int indexOf(int c, int start)
    467  *
    468  * Scan forward through the string for a matching character.
    469  * The character must be <= 0xffff; this method does not handle supplementary
    470  * characters.
    471  */
    472 static bool javaLangString_fastIndexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    473     JValue* pResult)
    474 {
    475     /* null reference check on "this" */
    476     if (!dvmValidateObject((Object*) arg0))
    477         return false;
    478 
    479     pResult->i = indexOfCommon((Object*) arg0, arg1, arg2);
    480     return true;
    481 }
    482 
    483 
    484 /*
    485  * ===========================================================================
    486  *      java.lang.Math
    487  * ===========================================================================
    488  */
    489 
    490 typedef union {
    491     u4 arg;
    492     float ff;
    493 } Convert32;
    494 
    495 typedef union {
    496     u4 arg[2];
    497     s8 ll;
    498     double dd;
    499 } Convert64;
    500 
    501 /*
    502  * public static int abs(int)
    503  */
    504 static bool javaLangMath_abs_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    505     JValue* pResult)
    506 {
    507     s4 val = (s4) arg0;
    508     pResult->i = (val >= 0) ? val : -val;
    509     return true;
    510 }
    511 
    512 /*
    513  * public static long abs(long)
    514  */
    515 static bool javaLangMath_abs_long(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    516     JValue* pResult)
    517 {
    518     Convert64 convert;
    519     convert.arg[0] = arg0;
    520     convert.arg[1] = arg1;
    521     s8 val = convert.ll;
    522     pResult->j = (val >= 0) ? val : -val;
    523     return true;
    524 }
    525 
    526 /*
    527  * public static float abs(float)
    528  */
    529 static bool javaLangMath_abs_float(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    530     JValue* pResult)
    531 {
    532     Convert32 convert;
    533     /* clear the sign bit; assumes a fairly common fp representation */
    534     convert.arg = arg0 & 0x7fffffff;
    535     pResult->f = convert.ff;
    536     return true;
    537 }
    538 
    539 /*
    540  * public static double abs(double)
    541  */
    542 static bool javaLangMath_abs_double(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    543     JValue* pResult)
    544 {
    545     Convert64 convert;
    546     convert.arg[0] = arg0;
    547     convert.arg[1] = arg1;
    548     /* clear the sign bit in the (endian-dependent) high word */
    549     convert.ll &= 0x7fffffffffffffffULL;
    550     pResult->d = convert.dd;
    551     return true;
    552 }
    553 
    554 /*
    555  * public static int min(int)
    556  */
    557 static bool javaLangMath_min_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    558     JValue* pResult)
    559 {
    560     pResult->i = ((s4) arg0 < (s4) arg1) ? arg0 : arg1;
    561     return true;
    562 }
    563 
    564 /*
    565  * public static int max(int)
    566  */
    567 static bool javaLangMath_max_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    568     JValue* pResult)
    569 {
    570     pResult->i = ((s4) arg0 > (s4) arg1) ? arg0 : arg1;
    571     return true;
    572 }
    573 
    574 /*
    575  * public static double sqrt(double)
    576  *
    577  * With ARM VFP enabled, gcc turns this into an fsqrtd instruction, followed
    578  * by an fcmpd of the result against itself.  If it doesn't match (i.e.
    579  * it's NaN), the libm sqrt() is invoked.
    580  */
    581 static bool javaLangMath_sqrt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    582     JValue* pResult)
    583 {
    584     Convert64 convert;
    585     convert.arg[0] = arg0;
    586     convert.arg[1] = arg1;
    587     pResult->d = sqrt(convert.dd);
    588     return true;
    589 }
    590 
    591 /*
    592  * public static double cos(double)
    593  */
    594 static bool javaLangMath_cos(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    595     JValue* pResult)
    596 {
    597     Convert64 convert;
    598     convert.arg[0] = arg0;
    599     convert.arg[1] = arg1;
    600     pResult->d = cos(convert.dd);
    601     return true;
    602 }
    603 
    604 /*
    605  * public static double sin(double)
    606  */
    607 static bool javaLangMath_sin(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 = sin(convert.dd);
    614     return true;
    615 }
    616 
    617 /*
    618  * ===========================================================================
    619  *      java.lang.Float
    620  * ===========================================================================
    621  */
    622 
    623 static bool javaLangFloat_floatToIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
    624     JValue* pResult)
    625 {
    626     Convert32 convert;
    627     convert.arg = arg0;
    628     pResult->i = isnanf(convert.ff) ? 0x7fc00000 : arg0;
    629     return true;
    630 }
    631 
    632 static bool javaLangFloat_floatToRawIntBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
    633     JValue* pResult)
    634 {
    635     pResult->i = arg0;
    636     return true;
    637 }
    638 
    639 static bool javaLangFloat_intBitsToFloat(u4 arg0, u4 arg1, u4 arg2, u4 arg,
    640     JValue* pResult)
    641 {
    642     Convert32 convert;
    643     convert.arg = arg0;
    644     pResult->f = convert.ff;
    645     return true;
    646 }
    647 
    648 /*
    649  * ===========================================================================
    650  *      java.lang.Double
    651  * ===========================================================================
    652  */
    653 
    654 static bool javaLangDouble_doubleToLongBits(u4 arg0, u4 arg1, u4 arg2, u4 arg,
    655     JValue* pResult)
    656 {
    657     Convert64 convert;
    658     convert.arg[0] = arg0;
    659     convert.arg[1] = arg1;
    660     pResult->j = isnan(convert.dd) ? 0x7ff8000000000000LL : convert.ll;
    661     return true;
    662 }
    663 
    664 static bool javaLangDouble_doubleToRawLongBits(u4 arg0, u4 arg1, u4 arg2,
    665     u4 arg, JValue* pResult)
    666 {
    667     Convert64 convert;
    668     convert.arg[0] = arg0;
    669     convert.arg[1] = arg1;
    670     pResult->j = convert.ll;
    671     return true;
    672 }
    673 
    674 static bool javaLangDouble_longBitsToDouble(u4 arg0, u4 arg1, u4 arg2, u4 arg,
    675     JValue* pResult)
    676 {
    677     Convert64 convert;
    678     convert.arg[0] = arg0;
    679     convert.arg[1] = arg1;
    680     pResult->d = convert.dd;
    681     return true;
    682 }
    683 
    684 /*
    685  * ===========================================================================
    686  *      Infrastructure
    687  * ===========================================================================
    688  */
    689 
    690 /*
    691  * Table of methods.
    692  *
    693  * The DEX optimizer uses the class/method/signature string fields to decide
    694  * which calls it can trample.  The interpreter just uses the function
    695  * pointer field.
    696  *
    697  * IMPORTANT: you must update DALVIK_VM_BUILD in DalvikVersion.h if you make
    698  * changes to this table.
    699  *
    700  * NOTE: If present, the JIT will also need to know about changes
    701  * to this table.  Update the NativeInlineOps enum in InlineNative.h and
    702  * the dispatch code in compiler/codegen/<target>/Codegen.c.
    703  */
    704 const InlineOperation gDvmInlineOpsTable[] = {
    705     { org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod,
    706         "Lorg/apache/harmony/dalvik/NativeTestTarget;",
    707         "emptyInlineMethod", "()V" },
    708 
    709     { javaLangString_charAt,
    710         "Ljava/lang/String;", "charAt", "(I)C" },
    711     { javaLangString_compareTo,
    712         "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I" },
    713     { javaLangString_equals,
    714         "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" },
    715     { javaLangString_fastIndexOf_II,
    716         "Ljava/lang/String;", "fastIndexOf", "(II)I" },
    717     { javaLangString_isEmpty,
    718         "Ljava/lang/String;", "isEmpty", "()Z" },
    719     { javaLangString_length,
    720         "Ljava/lang/String;", "length", "()I" },
    721 
    722     { javaLangMath_abs_int,
    723         "Ljava/lang/Math;", "abs", "(I)I" },
    724     { javaLangMath_abs_long,
    725         "Ljava/lang/Math;", "abs", "(J)J" },
    726     { javaLangMath_abs_float,
    727         "Ljava/lang/Math;", "abs", "(F)F" },
    728     { javaLangMath_abs_double,
    729         "Ljava/lang/Math;", "abs", "(D)D" },
    730     { javaLangMath_min_int,
    731         "Ljava/lang/Math;", "min", "(II)I" },
    732     { javaLangMath_max_int,
    733         "Ljava/lang/Math;", "max", "(II)I" },
    734     { javaLangMath_sqrt,
    735         "Ljava/lang/Math;", "sqrt", "(D)D" },
    736     { javaLangMath_cos,
    737         "Ljava/lang/Math;", "cos", "(D)D" },
    738     { javaLangMath_sin,
    739         "Ljava/lang/Math;", "sin", "(D)D" },
    740 
    741     { javaLangFloat_floatToIntBits,
    742         "Ljava/lang/Float;", "floatToIntBits", "(F)I" },
    743     { javaLangFloat_floatToRawIntBits,
    744         "Ljava/lang/Float;", "floatToRawIntBits", "(F)I" },
    745     { javaLangFloat_intBitsToFloat,
    746         "Ljava/lang/Float;", "intBitsToFloat", "(I)F" },
    747 
    748     { javaLangDouble_doubleToLongBits,
    749         "Ljava/lang/Double;", "doubleToLongBits", "(D)J" },
    750     { javaLangDouble_doubleToRawLongBits,
    751         "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J" },
    752     { javaLangDouble_longBitsToDouble,
    753         "Ljava/lang/Double;", "longBitsToDouble", "(J)D" },
    754 };
    755 
    756 /*
    757  * Allocate some tables.
    758  */
    759 bool dvmInlineNativeStartup(void)
    760 {
    761     gDvm.inlinedMethods =
    762         (Method**) calloc(NELEM(gDvmInlineOpsTable), sizeof(Method*));
    763     if (gDvm.inlinedMethods == NULL)
    764         return false;
    765 
    766     return true;
    767 }
    768 
    769 /*
    770  * Free generated tables.
    771  */
    772 void dvmInlineNativeShutdown(void)
    773 {
    774     free(gDvm.inlinedMethods);
    775 }
    776 
    777 
    778 /*
    779  * Get a pointer to the inlineops table.
    780  */
    781 const InlineOperation* dvmGetInlineOpsTable(void)
    782 {
    783     return gDvmInlineOpsTable;
    784 }
    785 
    786 /*
    787  * Get the number of entries in the inlineops table.
    788  */
    789 int dvmGetInlineOpsTableLength(void)
    790 {
    791     return NELEM(gDvmInlineOpsTable);
    792 }
    793 
    794 /*
    795  * Make an inline call for the "debug" interpreter, used when the debugger
    796  * or profiler is active.
    797  */
    798 bool dvmPerformInlineOp4Dbg(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    799     JValue* pResult, int opIndex)
    800 {
    801     Thread* self = dvmThreadSelf();
    802     bool result;
    803 
    804     assert(opIndex >= 0 && opIndex < NELEM(gDvmInlineOpsTable));
    805 
    806     /*
    807      * Populate the methods table on first use.  It's possible the class
    808      * hasn't been resolved yet, so we need to do the full "calling the
    809      * method for the first time" routine.  (It's probably okay to skip
    810      * the access checks.)
    811      *
    812      * Currently assuming that we're only inlining stuff loaded by the
    813      * bootstrap class loader.  This is a safe assumption for many reasons.
    814      */
    815     Method* method = gDvm.inlinedMethods[opIndex];
    816     if (method == NULL) {
    817         ClassObject* clazz;
    818 
    819         clazz = dvmFindClassNoInit(
    820                 gDvmInlineOpsTable[opIndex].classDescriptor, NULL);
    821         if (clazz == NULL) {
    822             LOGW("Warning: can't find class '%s'\n", clazz->descriptor);
    823             goto skip_prof;
    824         }
    825         method = dvmFindDirectMethodByDescriptor(clazz,
    826                     gDvmInlineOpsTable[opIndex].methodName,
    827                     gDvmInlineOpsTable[opIndex].methodSignature);
    828         if (method == NULL)
    829             method = dvmFindVirtualMethodByDescriptor(clazz,
    830                         gDvmInlineOpsTable[opIndex].methodName,
    831                         gDvmInlineOpsTable[opIndex].methodSignature);
    832         if (method == NULL) {
    833             LOGW("Warning: can't find method %s.%s %s\n",
    834                 clazz->descriptor,
    835                 gDvmInlineOpsTable[opIndex].methodName,
    836                 gDvmInlineOpsTable[opIndex].methodSignature);
    837             goto skip_prof;
    838         }
    839 
    840         gDvm.inlinedMethods[opIndex] = method;
    841         IF_LOGV() {
    842             char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
    843             LOGV("Registered for profile: %s.%s %s\n",
    844                 method->clazz->descriptor, method->name, desc);
    845             free(desc);
    846         }
    847     }
    848 
    849     TRACE_METHOD_ENTER(self, method);
    850     result = (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3,
    851                 pResult);
    852     TRACE_METHOD_EXIT(self, method);
    853     return result;
    854 
    855 skip_prof:
    856     return (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult);
    857 }
    858