001 /******************************************************************************* 002 * Copyright (c) 2009 Progress Software, Inc. 003 * Copyright (c) 2004, 2007 IBM Corporation and others. 004 * 005 * All rights reserved. This program and the accompanying materials 006 * are made available under the terms of the Eclipse Public License v1.0 007 * which accompanies this distribution, and is available at 008 * http://www.eclipse.org/legal/epl-v10.html 009 * 010 *******************************************************************************/ 011 package org.fusesource.hawtjni.generator; 012 013 import java.lang.reflect.Modifier; 014 import java.util.List; 015 016 import org.fusesource.hawtjni.generator.model.JNIClass; 017 import org.fusesource.hawtjni.generator.model.JNIMethod; 018 019 /** 020 * 021 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 022 */ 023 public class StatsGenerator extends JNIGenerator { 024 025 boolean header; 026 027 public StatsGenerator(boolean header) { 028 this.header = header; 029 } 030 031 public void generateCopyright() { 032 outputln(fixDelimiter(getCopyright())); 033 } 034 035 public void generateIncludes() { 036 if (!header) { 037 outputln("#include \"hawtjni.h\""); 038 outputln("#include \""+getOutputName()+"_stats.h\""); 039 outputln(); 040 } 041 } 042 043 public void generate(JNIClass clazz) { 044 if (header) { 045 generateHeaderFile(clazz); 046 } else { 047 generateSourceFile(clazz); 048 } 049 } 050 051 void generateHeaderFile(JNIClass clazz) { 052 generateNATIVEMacros(clazz); 053 List<JNIMethod> methods = clazz.getDeclaredMethods(); 054 sortMethods(methods); 055 generateFunctionEnum(methods); 056 } 057 058 void generateNATIVEMacros(JNIClass clazz) { 059 String className = clazz.getSimpleName(); 060 outputln("#ifdef NATIVE_STATS"); 061 output("extern int "); 062 output(className); 063 outputln("_nativeFunctionCount;"); 064 output("extern int "); 065 output(className); 066 outputln("_nativeFunctionCallCount[];"); 067 output("extern char* "); 068 output(className); 069 outputln("_nativeFunctionNames[];"); 070 output("#define "); 071 output(className); 072 output("_NATIVE_ENTER(env, that, func) "); 073 output(className); 074 outputln("_nativeFunctionCallCount[func]++;"); 075 output("#define "); 076 output(className); 077 outputln("_NATIVE_EXIT(env, that, func) "); 078 outputln("#else"); 079 output("#ifndef "); 080 output(className); 081 outputln("_NATIVE_ENTER"); 082 output("#define "); 083 output(className); 084 outputln("_NATIVE_ENTER(env, that, func) "); 085 outputln("#endif"); 086 output("#ifndef "); 087 output(className); 088 outputln("_NATIVE_EXIT"); 089 output("#define "); 090 output(className); 091 outputln("_NATIVE_EXIT(env, that, func) "); 092 outputln("#endif"); 093 outputln("#endif"); 094 outputln(); 095 } 096 097 void generateSourceFile(JNIClass clazz) { 098 outputln("#ifdef NATIVE_STATS"); 099 outputln(); 100 List<JNIMethod> methods = clazz.getDeclaredMethods(); 101 int methodCount = 0; 102 for (JNIMethod method : methods) { 103 if ((method.getModifiers() & Modifier.NATIVE) == 0) 104 continue; 105 methodCount++; 106 } 107 String className = clazz.getSimpleName(); 108 output("int "); 109 output(className); 110 output("_nativeFunctionCount = "); 111 output(String.valueOf(methodCount)); 112 outputln(";"); 113 output("int "); 114 output(className); 115 output("_nativeFunctionCallCount["); 116 output(String.valueOf(methodCount)); 117 outputln("];"); 118 output("char * "); 119 output(className); 120 outputln("_nativeFunctionNames[] = {"); 121 sortMethods(methods); 122 for (JNIMethod method : methods) { 123 if ((method.getModifiers() & Modifier.NATIVE) == 0) 124 continue; 125 String function = getFunctionName(method), function64 = getFunctionName(method, method.getParameterTypes64()); 126 if (!function.equals(function64)) { 127 output("#ifndef "); 128 output(JNI64); 129 outputln(); 130 } 131 output("\t\""); 132 output(function); 133 outputln("\","); 134 if (!function.equals(function64)) { 135 outputln("#else"); 136 output("\t\""); 137 output(function64); 138 outputln("\","); 139 outputln("#endif"); 140 } 141 if (progress != null) 142 progress.step(); 143 } 144 outputln("};"); 145 outputln(); 146 generateStatsNatives(className); 147 outputln(); 148 outputln("#endif"); 149 } 150 151 void generateStatsNatives(String className) { 152 outputln("#define STATS_NATIVE(func) Java_org_fusesource_hawtjni_runtime_NativeStats_##func"); 153 outputln(); 154 155 output("JNIEXPORT jint JNICALL STATS_NATIVE("); 156 output(toC(className + "_GetFunctionCount")); 157 outputln(")"); 158 outputln("\t(JNIEnv *env, jclass that)"); 159 outputln("{"); 160 output("\treturn "); 161 output(className); 162 outputln("_nativeFunctionCount;"); 163 outputln("}"); 164 outputln(); 165 166 output("JNIEXPORT jstring JNICALL STATS_NATIVE("); 167 output(toC(className + "_GetFunctionName")); 168 outputln(")"); 169 outputln("\t(JNIEnv *env, jclass that, jint index)"); 170 outputln("{"); 171 output("\treturn "); 172 if (isCPP) { 173 output("env->NewStringUTF("); 174 } else { 175 output("(*env)->NewStringUTF(env, "); 176 } 177 output(className); 178 outputln("_nativeFunctionNames[index]);"); 179 outputln("}"); 180 outputln(); 181 182 output("JNIEXPORT jint JNICALL STATS_NATIVE("); 183 output(toC(className + "_GetFunctionCallCount")); 184 outputln(")"); 185 outputln("\t(JNIEnv *env, jclass that, jint index)"); 186 outputln("{"); 187 output("\treturn "); 188 output(className); 189 outputln("_nativeFunctionCallCount[index];"); 190 outputln("}"); 191 } 192 193 void generateFunctionEnum(List<JNIMethod> methods) { 194 if (methods.isEmpty()) 195 return; 196 outputln("typedef enum {"); 197 for (JNIMethod method : methods) { 198 if ((method.getModifiers() & Modifier.NATIVE) == 0) 199 continue; 200 String function = getFunctionName(method), function64 = getFunctionName(method, method.getParameterTypes64()); 201 if (!function.equals(function64)) { 202 output("#ifndef "); 203 output(JNI64); 204 outputln(); 205 } 206 output("\t"); 207 output(method.getDeclaringClass().getSimpleName()+"_"+function); 208 outputln("_FUNC,"); 209 if (!function.equals(function64)) { 210 outputln("#else"); 211 output("\t"); 212 output(method.getDeclaringClass().getSimpleName()+"_"+function64); 213 outputln("_FUNC,"); 214 outputln("#endif"); 215 } 216 if (progress != null) 217 progress.step(); 218 } 219 JNIClass clazz = methods.get(0).getDeclaringClass(); 220 output("} "); 221 output(clazz.getSimpleName()); 222 outputln("_FUNCS;"); 223 } 224 225 }