2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Inlined native functions. These definitions replace interpreted or
19 * native implementations at runtime; "intrinsic" might be a better word.
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);
34 * Some notes on "inline" functions.
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
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.
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.
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).
58 * DO NOT replace "synchronized" methods. We do not support method
59 * synchronization here.
61 * Remember that these functions are executing while the thread is in
62 * the "RUNNING" state, not the "NATIVE" state. If you perform a blocking
63 * operation you can stall the entire VM if the GC or debugger wants to
64 * suspend the thread. Since these are arguably native implementations
65 * rather than VM internals, prefer NATIVE to VMWAIT if you want to change
68 * Always write results to 32-bit or 64-bit fields in "pResult", e.g. do
69 * not write boolean results to pResult->z. The interpreter expects
70 * 32 or 64 bits to be set.
72 * Inline op methods return "false" if an exception was thrown, "true" if
73 * everything went well.
75 * DO NOT provide implementations of methods that can be overridden by a
76 * subclass, as polymorphism does not work correctly. For safety you should
77 * only provide inline functions for classes/methods declared "final".
79 * It's best to avoid inlining the overridden version of a method. For
80 * example, String.hashCode() is inherited from Object.hashCode(). Code
81 * calling String.hashCode() through an Object reference will run the
82 * "slow" version, while calling it through a String reference gets
83 * the inlined version. It's best to have just one version unless there
84 * are clear performance gains.
86 * Because the actual method is not called, debugger breakpoints on these
87 * methods will not happen. (TODO: have the code here find the original
88 * method and call it when the debugger is active.) Additional steps have
89 * been taken to allow method profiling to produce correct results.
94 * ===========================================================================
95 * org.apache.harmony.dalvik.NativeTestTarget
96 * ===========================================================================
100 * public static void emptyInlineMethod
102 * This exists only for benchmarks.
104 static bool org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod(
105 u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
113 * ===========================================================================
115 * ===========================================================================
119 * public char charAt(int index)
121 static bool javaLangString_charAt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
127 /* null reference check on "this" */
128 if (!dvmValidateObject((Object*) arg0))
131 //LOGI("String.charAt this=0x%08x index=%d\n", arg0, arg1);
132 count = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
133 if ((s4) arg1 < 0 || (s4) arg1 >= count) {
134 dvmThrowException("Ljava/lang/StringIndexOutOfBoundsException;", NULL);
137 offset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
138 chars = (ArrayObject*)
139 dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
141 pResult->i = ((const u2*) chars->contents)[arg1 + offset];
146 #ifdef CHECK_MEMCMP16
148 * Utility function when we're evaluating alternative implementations.
150 static void badMatch(StringObject* thisStrObj, StringObject* compStrObj,
151 int expectResult, int newResult, const char* compareType)
153 ArrayObject* thisArray;
154 ArrayObject* compArray;
157 int thisOffset, compOffset, thisCount, compCount;
160 dvmGetFieldInt((Object*) thisStrObj, gDvm.offJavaLangString_count);
162 dvmGetFieldInt((Object*) compStrObj, gDvm.offJavaLangString_count);
164 dvmGetFieldInt((Object*) thisStrObj, gDvm.offJavaLangString_offset);
166 dvmGetFieldInt((Object*) compStrObj, gDvm.offJavaLangString_offset);
167 thisArray = (ArrayObject*)
168 dvmGetFieldObject((Object*) thisStrObj, gDvm.offJavaLangString_value);
169 compArray = (ArrayObject*)
170 dvmGetFieldObject((Object*) compStrObj, gDvm.offJavaLangString_value);
172 thisStr = dvmCreateCstrFromString(thisStrObj);
173 compStr = dvmCreateCstrFromString(compStrObj);
175 LOGE("%s expected %d got %d\n", compareType, expectResult, newResult);
176 LOGE(" this (o=%d l=%d) '%s'\n", thisOffset, thisCount, thisStr);
177 LOGE(" comp (o=%d l=%d) '%s'\n", compOffset, compCount, compStr);
178 dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG,
179 ((const u2*) thisArray->contents) + thisOffset, thisCount*2,
181 dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG,
182 ((const u2*) compArray->contents) + compOffset, compCount*2,
189 * public int compareTo(String s)
191 static bool javaLangString_compareTo(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
195 * Null reference check on "this". Normally this is performed during
196 * the setup of the virtual method call. We need to do it before
197 * anything else. While we're at it, check out the other string,
198 * which must also be non-null.
200 if (!dvmValidateObject((Object*) arg0) ||
201 !dvmValidateObject((Object*) arg1))
206 /* quick test for comparison with itself */
213 * This would be simpler and faster if we promoted StringObject to
214 * a full representation, lining up the C structure fields with the
215 * actual object fields.
217 int thisCount, thisOffset, compCount, compOffset;
218 ArrayObject* thisArray;
219 ArrayObject* compArray;
222 int i, minCount, countDiff;
224 thisCount = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
225 compCount = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_count);
226 countDiff = thisCount - compCount;
227 minCount = (countDiff < 0) ? thisCount : compCount;
228 thisOffset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
229 compOffset = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_offset);
230 thisArray = (ArrayObject*)
231 dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
232 compArray = (ArrayObject*)
233 dvmGetFieldObject((Object*) arg1, gDvm.offJavaLangString_value);
234 thisChars = ((const u2*) thisArray->contents) + thisOffset;
235 compChars = ((const u2*) compArray->contents) + compOffset;
237 #ifdef HAVE__MEMCMP16
239 * Use assembly version, which returns the difference between the
240 * characters. The annoying part here is that 0x00e9 - 0xffff != 0x00ea,
241 * because the interpreter converts the characters to 32-bit integers
242 * *without* sign extension before it subtracts them (which makes some
243 * sense since "char" is unsigned). So what we get is the result of
244 * 0x000000e9 - 0x0000ffff, which is 0xffff00ea.
246 int otherRes = __memcmp16(thisChars, compChars, minCount);
247 # ifdef CHECK_MEMCMP16
248 for (i = 0; i < minCount; i++) {
249 if (thisChars[i] != compChars[i]) {
250 pResult->i = (s4) thisChars[i] - (s4) compChars[i];
251 if (pResult->i != otherRes) {
252 badMatch((StringObject*) arg0, (StringObject*) arg1,
253 pResult->i, otherRes, "compareTo");
260 pResult->i = otherRes;
266 * Straightforward implementation, examining 16 bits at a time. Compare
267 * the characters that overlap, and if they're all the same then return
268 * the difference in lengths.
270 for (i = 0; i < minCount; i++) {
271 if (thisChars[i] != compChars[i]) {
272 pResult->i = (s4) thisChars[i] - (s4) compChars[i];
278 pResult->i = countDiff;
283 * public boolean equals(Object anObject)
285 static bool javaLangString_equals(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
289 * Null reference check on "this".
291 if (!dvmValidateObject((Object*) arg0))
294 /* quick test for comparison with itself */
301 * See if the other object is also a String.
303 * str.equals(null) is expected to return false, presumably based on
304 * the results of the instanceof test.
306 if (arg1 == 0 || ((Object*) arg0)->clazz != ((Object*) arg1)->clazz) {
312 * This would be simpler and faster if we promoted StringObject to
313 * a full representation, lining up the C structure fields with the
314 * actual object fields.
316 int thisCount, thisOffset, compCount, compOffset;
317 ArrayObject* thisArray;
318 ArrayObject* compArray;
323 /* quick length check */
324 thisCount = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
325 compCount = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_count);
326 if (thisCount != compCount) {
331 thisOffset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
332 compOffset = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_offset);
333 thisArray = (ArrayObject*)
334 dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
335 compArray = (ArrayObject*)
336 dvmGetFieldObject((Object*) arg1, gDvm.offJavaLangString_value);
337 thisChars = ((const u2*) thisArray->contents) + thisOffset;
338 compChars = ((const u2*) compArray->contents) + compOffset;
340 #ifdef HAVE__MEMCMP16
341 pResult->i = (__memcmp16(thisChars, compChars, thisCount) == 0);
342 # ifdef CHECK_MEMCMP16
343 int otherRes = (memcmp(thisChars, compChars, thisCount * 2) == 0);
344 if (pResult->i != otherRes) {
345 badMatch((StringObject*) arg0, (StringObject*) arg1,
346 otherRes, pResult->i, "equals-1");
351 * Straightforward implementation, examining 16 bits at a time. The
352 * direction of the loop doesn't matter, and starting at the end may
353 * give us an advantage when comparing certain types of strings (e.g.
356 * We want to go forward for benchmarks against __memcmp16 so we get a
357 * meaningful comparison when the strings don't match (could also test
360 //for (i = 0; i < thisCount; i++)
361 for (i = thisCount-1; i >= 0; --i)
363 if (thisChars[i] != compChars[i]) {
375 * public int length()
377 static bool javaLangString_length(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
380 //LOGI("String.length this=0x%08x pResult=%p\n", arg0, pResult);
382 /* null reference check on "this" */
383 if (!dvmValidateObject((Object*) arg0))
386 pResult->i = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
392 * ===========================================================================
394 * ===========================================================================
398 * public static int abs(int)
400 static bool javaLangMath_abs_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
404 pResult->i = (val >= 0) ? val : -val;
409 * public static long abs(long)
411 static bool javaLangMath_abs_long(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
419 convert.arg[0] = arg0;
420 convert.arg[1] = arg1;
422 pResult->j = (val >= 0) ? val : -val;
427 * public static float abs(float)
429 static bool javaLangMath_abs_float(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
437 /* clear the sign bit; assumes a fairly common fp representation */
438 convert.arg = arg0 & 0x7fffffff;
439 pResult->f = convert.ff;
444 * public static double abs(double)
446 static bool javaLangMath_abs_double(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
455 /* clear the sign bit in the (endian-dependent) high word */
456 convert.arg[0] = arg0;
457 convert.arg[1] = arg1;
458 convert.ll &= 0x7fffffffffffffffULL;
459 pResult->d = convert.dd;
464 * public static int min(int)
466 static bool javaLangMath_min_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
469 pResult->i = ((s4) arg0 < (s4) arg1) ? arg0 : arg1;
474 * public static int max(int)
476 static bool javaLangMath_max_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
479 pResult->i = ((s4) arg0 > (s4) arg1) ? arg0 : arg1;
484 * public static double sqrt(double)
486 * With ARM VFP enabled, gcc turns this into an fsqrtd instruction, followed
487 * by an fcmpd of the result against itself. If it doesn't match (i.e.
488 * it's NaN), the libm sqrt() is invoked.
490 static bool javaLangMath_sqrt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
498 convert.arg[0] = arg0;
499 convert.arg[1] = arg1;
500 pResult->d = sqrt(convert.dd);
505 * public static double cos(double)
507 static bool javaLangMath_cos(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
515 convert.arg[0] = arg0;
516 convert.arg[1] = arg1;
517 pResult->d = cos(convert.dd);
522 * public static double sin(double)
524 static bool javaLangMath_sin(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
532 convert.arg[0] = arg0;
533 convert.arg[1] = arg1;
534 pResult->d = sin(convert.dd);
540 * ===========================================================================
542 * ===========================================================================
548 * The DEX optimizer uses the class/method/signature string fields to decide
549 * which calls it can trample. The interpreter just uses the function
552 * IMPORTANT: you must update DALVIK_VM_BUILD in DalvikVersion.h if you make
553 * changes to this table. Must also be kept in sync with NativeInlineOps
554 * enum in InlineNative.h.
556 const InlineOperation gDvmInlineOpsTable[] = {
557 { org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod,
558 "Lorg/apache/harmony/dalvik/NativeTestTarget;",
559 "emptyInlineMethod", "()V" },
561 { javaLangString_charAt,
562 "Ljava/lang/String;", "charAt", "(I)C" },
563 { javaLangString_compareTo,
564 "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I" },
565 { javaLangString_equals,
566 "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" },
567 { javaLangString_length,
568 "Ljava/lang/String;", "length", "()I" },
570 { javaLangMath_abs_int,
571 "Ljava/lang/Math;", "abs", "(I)I" },
572 { javaLangMath_abs_long,
573 "Ljava/lang/Math;", "abs", "(J)J" },
574 { javaLangMath_abs_float,
575 "Ljava/lang/Math;", "abs", "(F)F" },
576 { javaLangMath_abs_double,
577 "Ljava/lang/Math;", "abs", "(D)D" },
578 { javaLangMath_min_int,
579 "Ljava/lang/Math;", "min", "(II)I" },
580 { javaLangMath_max_int,
581 "Ljava/lang/Math;", "max", "(II)I" },
583 "Ljava/lang/Math;", "sqrt", "(D)D" },
585 "Ljava/lang/Math;", "cos", "(D)D" },
587 "Ljava/lang/Math;", "sin", "(D)D" },
592 * Allocate some tables.
594 bool dvmInlineNativeStartup(void)
597 gDvm.inlinedMethods =
598 (Method**) calloc(NELEM(gDvmInlineOpsTable), sizeof(Method*));
599 if (gDvm.inlinedMethods == NULL)
607 * Free generated tables.
609 void dvmInlineNativeShutdown(void)
612 free(gDvm.inlinedMethods);
618 * Get a pointer to the inlineops table.
620 const InlineOperation* dvmGetInlineOpsTable(void)
622 return gDvmInlineOpsTable;
626 * Get the number of entries in the inlineops table.
628 int dvmGetInlineOpsTableLength(void)
630 return NELEM(gDvmInlineOpsTable);
634 * Make an inline call for the "debug" interpreter, used when the debugger
635 * or profiler is active.
637 bool dvmPerformInlineOp4Dbg(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
638 JValue* pResult, int opIndex)
640 Thread* self = dvmThreadSelf();
643 assert(opIndex >= 0 && opIndex < NELEM(gDvmInlineOpsTable));
647 * Populate the methods table on first use. It's possible the class
648 * hasn't been resolved yet, so we need to do the full "calling the
649 * method for the first time" routine. (It's probably okay to skip
650 * the access checks.)
652 * Currently assuming that we're only inlining stuff loaded by the
653 * bootstrap class loader. This is a safe assumption for many reasons.
655 Method* method = gDvm.inlinedMethods[opIndex];
656 if (method == NULL) {
659 clazz = dvmFindClassNoInit(
660 gDvmInlineOpsTable[opIndex].classDescriptor, NULL);
662 LOGW("Warning: can't find class '%s'\n", clazz->descriptor);
665 method = dvmFindDirectMethodByDescriptor(clazz,
666 gDvmInlineOpsTable[opIndex].methodName,
667 gDvmInlineOpsTable[opIndex].methodSignature);
669 method = dvmFindVirtualMethodByDescriptor(clazz,
670 gDvmInlineOpsTable[opIndex].methodName,
671 gDvmInlineOpsTable[opIndex].methodSignature);
672 if (method == NULL) {
673 LOGW("Warning: can't find method %s.%s %s\n",
675 gDvmInlineOpsTable[opIndex].methodName,
676 gDvmInlineOpsTable[opIndex].methodSignature);
680 gDvm.inlinedMethods[opIndex] = method;
682 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
683 LOGV("Registered for profile: %s.%s %s\n",
684 method->clazz->descriptor, method->name, desc);
689 TRACE_METHOD_ENTER(self, method);
690 result = (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3,
692 TRACE_METHOD_EXIT(self, method);
697 return (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult);