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 * This uses the FFI (Foreign Function Interface) library to abstract away 19 * the system-dependent stuff. The FFI code is slower than a custom 20 * assembly version, but has the distinct advantage of having been 21 * written already for several platforms. 22 */ 23 #include "Dalvik.h" 24 #include "ffi.h" 25 26 /* 27 * Convert a signature type character to an FFI type. 28 */ 29 static ffi_type* getFfiType(char sigType) 30 { 31 switch (sigType) { 32 case 'V': return &ffi_type_void; 33 case 'Z': return &ffi_type_uint8; 34 case 'B': return &ffi_type_sint8; 35 case 'C': return &ffi_type_uint16; 36 case 'S': return &ffi_type_sint16; 37 case 'I': return &ffi_type_sint32; 38 case 'F': return &ffi_type_float; 39 case 'J': return &ffi_type_sint64; 40 case 'D': return &ffi_type_double; 41 case '[': 42 case 'L': return &ffi_type_pointer; 43 default: 44 LOGE("bad ffitype 0x%02x", sigType); 45 dvmAbort(); 46 return NULL; 47 } 48 } 49 50 /* 51 * Call "func" with the specified arguments. 52 * 53 * The second argument to JNI native functions is either the object (the 54 * "this" pointer) or, for static functions, a pointer to the class object. 55 * The Dalvik instructions will push "this" into argv[0], but it's up to 56 * us to insert the class object. 57 * 58 * Because there is no such thing in as a null "this" pointer, we use 59 * the non-NULL state of "clazz" to determine whether or not it's static. 60 * 61 * For maximum efficiency we should compute the CIF once and save it with 62 * the method. However, this requires storing the data with every native 63 * method. Since the goal is to have custom assembly versions of this 64 * on the platforms where performance matters, I'm recomputing the CIF on 65 * every call. 66 */ 67 void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc, 68 const u4* argv, const char* shorty, void* func, JValue* pReturn) 69 { 70 const int kMaxArgs = argc+2; /* +1 for env, maybe +1 for clazz */ 71 ffi_cif cif; 72 ffi_type* types[kMaxArgs]; 73 void* values[kMaxArgs]; 74 ffi_type* retType; 75 char sigByte; 76 int srcArg, dstArg; 77 78 types[0] = &ffi_type_pointer; 79 values[0] = &pEnv; 80 81 types[1] = &ffi_type_pointer; 82 if (clazz != NULL) { 83 values[1] = &clazz; 84 srcArg = 0; 85 } else { 86 values[1] = (void*) argv++; 87 srcArg = 1; 88 } 89 dstArg = 2; 90 91 /* 92 * Scan the types out of the short signature. Use them to fill out the 93 * "types" array. Store the start address of the argument in "values". 94 */ 95 retType = getFfiType(*shorty); 96 while ((sigByte = *++shorty) != '\0') { 97 types[dstArg] = getFfiType(sigByte); 98 values[dstArg++] = (void*) argv++; 99 if (sigByte == 'D' || sigByte == 'J') 100 argv++; 101 } 102 103 /* 104 * Prep the CIF (Call InterFace object). 105 */ 106 if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, dstArg, retType, types) != FFI_OK) { 107 LOGE("ffi_prep_cif failed"); 108 dvmAbort(); 109 } 110 111 ffi_call(&cif, FFI_FN(func), pReturn, values); 112 } 113