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 */ 29static 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 ALOGE("bad ffitype 0x%02x", sigType); 45 dvmAbort(); 46 return NULL; 47 } 48} 49 50/* We will call this generic function if there are no hints */ 51#ifdef __mips__ 52#define dvmPlatformInvoke dvmPlatformInvokeFFI 53 54extern "C" void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, 55 int argc, const u4* argv, const char* signature, void* func, JValue* pResult); 56#endif 57 58/* 59 * Call "func" with the specified arguments. 60 * 61 * The second argument to JNI native functions is either the object (the 62 * "this" pointer) or, for static functions, a pointer to the class object. 63 * The Dalvik instructions will push "this" into argv[0], but it's up to 64 * us to insert the class object. 65 * 66 * Because there is no such thing in as a null "this" pointer, we use 67 * the non-NULL state of "clazz" to determine whether or not it's static. 68 * 69 * For maximum efficiency we should compute the CIF once and save it with 70 * the method. However, this requires storing the data with every native 71 * method. Since the goal is to have custom assembly versions of this 72 * on the platforms where performance matters, I'm recomputing the CIF on 73 * every call. 74 */ 75void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc, 76 const u4* argv, const char* shorty, void* func, JValue* pReturn) 77{ 78 const int kMaxArgs = argc+2; /* +1 for env, maybe +1 for clazz */ 79 ffi_cif cif; 80 ffi_type* types[kMaxArgs]; 81 void* values[kMaxArgs]; 82 ffi_type* retType; 83 char sigByte; 84 int srcArg, dstArg; 85 86 types[0] = &ffi_type_pointer; 87 values[0] = &pEnv; 88 89 types[1] = &ffi_type_pointer; 90 if (clazz != NULL) { 91 values[1] = &clazz; 92 srcArg = 0; 93 } else { 94 values[1] = (void*) argv++; 95 srcArg = 1; 96 } 97 dstArg = 2; 98 99 /* 100 * Scan the types out of the short signature. Use them to fill out the 101 * "types" array. Store the start address of the argument in "values". 102 */ 103 retType = getFfiType(*shorty); 104 while ((sigByte = *++shorty) != '\0') { 105 types[dstArg] = getFfiType(sigByte); 106 values[dstArg++] = (void*) argv++; 107 if (sigByte == 'D' || sigByte == 'J') 108 argv++; 109 } 110 111 /* 112 * Prep the CIF (Call InterFace object). 113 */ 114 if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, dstArg, retType, types) != FFI_OK) { 115 ALOGE("ffi_prep_cif failed"); 116 dvmAbort(); 117 } 118 119 ffi_call(&cif, FFI_FN(func), pReturn, values); 120} 121