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 }