bind: generate reverse functions the same way as methods

This CL restructures function generation to match the way methods
are generated, to avoid two different code paths for a coming CL.

Change-Id: I5a4f15e51ea5df101f9aa419ed4170ab36506418
Reviewed-on: https://go-review.googlesource.com/35185
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/bind/genclasses.go b/bind/genclasses.go
index 7934506..1833703 100644
--- a/bind/genclasses.go
+++ b/bind/genclasses.go
@@ -231,11 +231,16 @@
 func (g *ClassGen) GenC() {
 	g.Printf(classesCHeader)
 	for _, cls := range g.classes {
-		g.genC(cls)
 		g.Printf("static jclass class_%s;\n", cls.JNIName)
 		if _, ok := g.supers[cls.Name]; ok {
 			g.Printf("static jclass sclass_%s;\n", cls.JNIName)
 		}
+		for _, f := range cls.Funcs {
+			if !f.Public || !g.isFuncSupported(f) {
+				continue
+			}
+			g.Printf("static jmethodID m_s_%s_%s;\n", cls.JNIName, f.JNIName)
+		}
 		for _, f := range cls.AllMethods {
 			if g.isFuncSupported(f) {
 				g.Printf("static jmethodID m_%s_%s;\n", cls.JNIName, f.JNIName)
@@ -244,6 +249,7 @@
 				}
 			}
 		}
+		g.genC(cls)
 	}
 	g.Printf("\n")
 	g.Printf("void init_proxies() {\n")
@@ -257,6 +263,17 @@
 			g.Printf("sclass_%s = (*env)->GetSuperclass(env, clazz);\n", cls.JNIName)
 			g.Printf("sclass_%s = (*env)->NewGlobalRef(env, sclass_%s);\n", cls.JNIName, cls.JNIName)
 		}
+		for _, f := range cls.Funcs {
+			if !f.Public || !g.isFuncSupported(f) {
+				continue
+			}
+			g.Printf("m_s_%s_%s = ", cls.JNIName, f.JNIName)
+			if f.Constructor {
+				g.Printf("go_seq_get_method_id(clazz, \"<init>\", %q);\n", f.Desc)
+			} else {
+				g.Printf("go_seq_get_static_method_id(clazz, %q, %q);\n", f.Name, f.Desc)
+			}
+		}
 		for _, f := range cls.AllMethods {
 			if g.isFuncSupported(f) {
 				g.Printf("m_%s_%s = go_seq_get_method_id(clazz, %q, %q);\n", cls.JNIName, f.JNIName, f.Name, f.Desc)
@@ -387,7 +404,7 @@
 		} else {
 			g.Printf("(*env)->CallStaticVoidMethod(env")
 		}
-		g.Printf(", clazz, m")
+		g.Printf(", class_%s, m_s_%s_%s", cls.JNIName, cls.JNIName, f.JNIName)
 		for i := range f.Params {
 			g.Printf(", _a%d", i)
 		}
@@ -442,9 +459,12 @@
 		// Return only the exception, if any
 		g.Printf("jint")
 	}
-	g.Printf(" cproxy_s_%s_%s(jclass clazz, jmethodID m", jniName, f.JNIName)
+	g.Printf(" cproxy_s_%s_%s(", jniName, f.JNIName)
 	for i, a := range f.Params {
-		g.Printf(", %s a%d", a.CType(), i)
+		if i > 0 {
+			g.Printf(", ")
+		}
+		g.Printf("%s a%d", a.CType(), i)
 	}
 	g.Printf(")")
 }
@@ -464,42 +484,9 @@
 		if !f.Public || !g.isFuncSupported(f) {
 			continue
 		}
-		g.Printf("{\n")
-		g.Indent()
-		name := f.Name
-		if f.Constructor {
-			name = "<init>"
-		}
-		g.Printf("fn := C.CString(%q)\n", name)
-		g.Printf("fd := C.CString(%q)\n", f.Desc)
-		if f.Constructor {
-			g.Printf("m := C.go_seq_get_method_id(clazz, fn, fd)\n")
-		} else {
-			g.Printf("m := C.go_seq_get_static_method_id(clazz, fn, fd)\n")
-		}
-		g.Printf("C.free(unsafe.Pointer(fn))\n")
-		g.Printf("C.free(unsafe.Pointer(fd))\n")
-		g.Printf("if m != nil {\n")
-		g.Indent()
 		g.Printf("%s.%s = func", cls.PkgName, f.GoName)
 		g.genFuncDecl(false, f)
-		g.Printf(" {\n")
-		g.Indent()
-		for i, a := range f.Params {
-			g.genWrite(fmt.Sprintf("a%d", i), a, modeTransient)
-		}
-		g.Printf("res := C.cproxy_s_%s_%s(clazz, m", cls.JNIName, f.JNIName)
-		for i := range f.Params {
-			g.Printf(", _a%d", i)
-		}
-		g.Printf(")\n")
-		g.genFuncRet(f)
-		g.Outdent()
-		g.Printf("}\n")
-		g.Outdent()
-		g.Printf("}\n")
-		g.Outdent()
-		g.Printf("}\n")
+		g.genFuncBody(cls, f, "cproxy_s", true)
 	}
 	g.Printf("%s.Cast = func(v interface{}) Java.%s {\n", cls.PkgName, goClsName(cls.Name))
 	g.Indent()
@@ -522,7 +509,7 @@
 		}
 		g.Printf("func (p *proxy_class_%s) %s", cls.JNIName, f.GoName)
 		g.genFuncDecl(false, f)
-		g.genFuncBody(cls, f, "cproxy")
+		g.genFuncBody(cls, f, "cproxy", false)
 	}
 	if cls.Throwable {
 		g.Printf("func (p *proxy_class_%s) Error() string {\n", cls.JNIName)
@@ -540,20 +527,26 @@
 			}
 			g.Printf("func (p *super_%s) %s", cls.JNIName, f.GoName)
 			g.genFuncDecl(false, f)
-			g.genFuncBody(cls, f, "csuper")
+			g.genFuncBody(cls, f, "csuper", false)
 		}
 	}
 }
 
-func (g *ClassGen) genFuncBody(cls *java.Class, f *java.Func, prefix string) {
+func (g *ClassGen) genFuncBody(cls *java.Class, f *java.Func, prefix string, static bool) {
 	g.Printf(" {\n")
 	g.Indent()
 	for i, a := range f.Params {
 		g.genWrite(fmt.Sprintf("a%d", i), a, modeTransient)
 	}
-	g.Printf("res := C.%s_%s_%s(C.jint(p.Bind_proxy_refnum__())", prefix, cls.JNIName, f.JNIName)
+	g.Printf("res := C.%s_%s_%s(", prefix, cls.JNIName, f.JNIName)
+	if !static {
+		g.Printf("C.jint(p.Bind_proxy_refnum__())")
+	}
 	for i := range f.Params {
-		g.Printf(", _a%d", i)
+		if !static || i > 0 {
+			g.Printf(", ")
+		}
+		g.Printf("_a%d", i)
 	}
 	g.Printf(")\n")
 	g.genFuncRet(f)
diff --git a/bind/testdata/classes.go.golden b/bind/testdata/classes.go.golden
index ee32517..c0c20cd 100644
--- a/bind/testdata/classes.go.golden
+++ b/bind/testdata/classes.go.golden
@@ -662,42 +662,34 @@
 		return
 	}
 	class_java_util_Spliterators = clazz
-	{
-		fn := C.CString("iterator")
-		fd := C.CString("(Ljava/util/Spliterator$OfInt;)Ljava/util/PrimitiveIterator$OfInt;")
-		m := C.go_seq_get_static_method_id(clazz, fn, fd)
-		C.free(unsafe.Pointer(fn))
-		C.free(unsafe.Pointer(fd))
-		if m != nil {
-			Spliterators.Iterator_Ljava_util_Spliterator_00024OfInt_2 = func(a0 Java.Java_util_Spliterator_OfInt) Java.Java_util_PrimitiveIterator_OfInt {
-				var _a0 C.jint = _seq.NullRefNum
-				if a0 != nil {
-					_a0 = C.jint(_seq.ToRefNum(a0))
-				}
-				res := C.cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(clazz, m, _a0)
-				var _res Java.Java_util_PrimitiveIterator_OfInt
-				_res_ref := _seq.FromRefNum(int32(res.res))
-				if _res_ref != nil {
-					if res.res < 0 { // go object
-						_res = _res_ref.Get().(Java.Java_util_PrimitiveIterator_OfInt)
-					} else { // foreign object
-						_res = (*proxy_class_java_util_PrimitiveIterator_OfInt)(_res_ref)
-					}
-				}
-				var _exc error
-				_exc_ref := _seq.FromRefNum(int32(res.exc))
-				if _exc_ref != nil {
-					if res.exc < 0 { // go object
-						_exc = _exc_ref.Get().(error)
-					} else { // foreign object
-						_exc = (*proxy_error)(_exc_ref)
-					}
-				}
-				if (_exc != nil) { panic(_exc) }
-				return _res
+	Spliterators.Iterator_Ljava_util_Spliterator_00024OfInt_2 = func(a0 Java.Java_util_Spliterator_OfInt) Java.Java_util_PrimitiveIterator_OfInt {
+		var _a0 C.jint = _seq.NullRefNum
+		if a0 != nil {
+			_a0 = C.jint(_seq.ToRefNum(a0))
+		}
+		res := C.cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(_a0)
+		var _res Java.Java_util_PrimitiveIterator_OfInt
+		_res_ref := _seq.FromRefNum(int32(res.res))
+		if _res_ref != nil {
+			if res.res < 0 { // go object
+				_res = _res_ref.Get().(Java.Java_util_PrimitiveIterator_OfInt)
+			} else { // foreign object
+				_res = (*proxy_class_java_util_PrimitiveIterator_OfInt)(_res_ref)
 			}
 		}
+		var _exc error
+		_exc_ref := _seq.FromRefNum(int32(res.exc))
+		if _exc_ref != nil {
+			if res.exc < 0 { // go object
+				_exc = _exc_ref.Get().(error)
+			} else { // foreign object
+				_exc = (*proxy_error)(_exc_ref)
+			}
+		}
+		if (_exc != nil) { panic(_exc) }
+		return _res
 	}
+	
 	Spliterators.Cast = func(v interface{}) Java.Java_util_Spliterators {
 		t := reflect.TypeOf((*proxy_class_java_util_Spliterators)(nil))
 		cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_java_util_Spliterators)
@@ -723,38 +715,30 @@
 		return
 	}
 	class_java_lang_System = clazz
-	{
-		fn := C.CString("console")
-		fd := C.CString("()Ljava/io/Console;")
-		m := C.go_seq_get_static_method_id(clazz, fn, fd)
-		C.free(unsafe.Pointer(fn))
-		C.free(unsafe.Pointer(fd))
-		if m != nil {
-			System.Console = func() Java.Java_io_Console {
-				res := C.cproxy_s_java_lang_System_console(clazz, m)
-				var _res Java.Java_io_Console
-				_res_ref := _seq.FromRefNum(int32(res.res))
-				if _res_ref != nil {
-					if res.res < 0 { // go object
-						_res = _res_ref.Get().(Java.Java_io_Console)
-					} else { // foreign object
-						_res = (*proxy_class_java_io_Console)(_res_ref)
-					}
-				}
-				var _exc error
-				_exc_ref := _seq.FromRefNum(int32(res.exc))
-				if _exc_ref != nil {
-					if res.exc < 0 { // go object
-						_exc = _exc_ref.Get().(error)
-					} else { // foreign object
-						_exc = (*proxy_error)(_exc_ref)
-					}
-				}
-				if (_exc != nil) { panic(_exc) }
-				return _res
+	System.Console = func() Java.Java_io_Console {
+		res := C.cproxy_s_java_lang_System_console()
+		var _res Java.Java_io_Console
+		_res_ref := _seq.FromRefNum(int32(res.res))
+		if _res_ref != nil {
+			if res.res < 0 { // go object
+				_res = _res_ref.Get().(Java.Java_io_Console)
+			} else { // foreign object
+				_res = (*proxy_class_java_io_Console)(_res_ref)
 			}
 		}
+		var _exc error
+		_exc_ref := _seq.FromRefNum(int32(res.exc))
+		if _exc_ref != nil {
+			if res.exc < 0 { // go object
+				_exc = _exc_ref.Get().(error)
+			} else { // foreign object
+				_exc = (*proxy_error)(_exc_ref)
+			}
+		}
+		if (_exc != nil) { panic(_exc) }
+		return _res
 	}
+	
 	System.Cast = func(v interface{}) Java.Java_lang_System {
 		t := reflect.TypeOf((*proxy_class_java_lang_System)(nil))
 		cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_java_lang_System)
diff --git a/bind/testdata/classes.java.c.golden b/bind/testdata/classes.java.c.golden
index 62da76a..a5d7a46 100644
--- a/bind/testdata/classes.java.c.golden
+++ b/bind/testdata/classes.java.c.golden
@@ -13,25 +13,12 @@
 static jmethodID m_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit_2;
 static jclass class_java_lang_Object;
 static jclass class_java_util_concurrent_TimeUnit;
-ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(jclass clazz, jmethodID m, jint a0) {
+static jclass class_java_util_Spliterators;
+static jmethodID m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2;
+ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(jint a0) {
 	JNIEnv *env = go_seq_push_local_frame(1);
 	jobject _a0 = go_seq_from_refnum(env, a0, NULL, NULL);
-	jobject res = (*env)->CallStaticObjectMethod(env, clazz, m, _a0);
-	jobject _exc = go_seq_get_exception(env);
-	int32_t _exc_ref = go_seq_to_refnum(env, _exc);
-	if (_exc != NULL) {
-		res = NULL;
-	}
-	jint _res = go_seq_to_refnum(env, res);
-	go_seq_pop_local_frame(env);
-	ret_jint __res = {_res, _exc_ref};
-	return __res;
-}
-
-static jclass class_java_util_Spliterators;
-ret_jint cproxy_s_java_lang_System_console(jclass clazz, jmethodID m) {
-	JNIEnv *env = go_seq_push_local_frame(0);
-	jobject res = (*env)->CallStaticObjectMethod(env, clazz, m);
+	jobject res = (*env)->CallStaticObjectMethod(env, class_java_util_Spliterators, m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2, _a0);
 	jobject _exc = go_seq_get_exception(env);
 	int32_t _exc_ref = go_seq_to_refnum(env, _exc);
 	if (_exc != NULL) {
@@ -44,6 +31,21 @@
 }
 
 static jclass class_java_lang_System;
+static jmethodID m_s_java_lang_System_console;
+ret_jint cproxy_s_java_lang_System_console() {
+	JNIEnv *env = go_seq_push_local_frame(0);
+	jobject res = (*env)->CallStaticObjectMethod(env, class_java_lang_System, m_s_java_lang_System_console);
+	jobject _exc = go_seq_get_exception(env);
+	int32_t _exc_ref = go_seq_to_refnum(env, _exc);
+	if (_exc != NULL) {
+		res = NULL;
+	}
+	jint _res = go_seq_to_refnum(env, res);
+	go_seq_pop_local_frame(env);
+	ret_jint __res = {_res, _exc_ref};
+	return __res;
+}
+
 static jclass class_java_Future;
 static jclass sclass_java_Future;
 static jmethodID m_java_Future_get__;
@@ -84,8 +86,10 @@
 	class_java_util_concurrent_TimeUnit = (*env)->NewGlobalRef(env, clazz);
 	clazz = (*env)->FindClass(env, "java/util/Spliterators");
 	class_java_util_Spliterators = (*env)->NewGlobalRef(env, clazz);
+	m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2 = go_seq_get_static_method_id(clazz, "iterator", "(Ljava/util/Spliterator$OfInt;)Ljava/util/PrimitiveIterator$OfInt;");
 	clazz = (*env)->FindClass(env, "java/lang/System");
 	class_java_lang_System = (*env)->NewGlobalRef(env, clazz);
+	m_s_java_lang_System_console = go_seq_get_static_method_id(clazz, "console", "()Ljava/io/Console;");
 	clazz = (*env)->FindClass(env, "java/Future");
 	class_java_Future = (*env)->NewGlobalRef(env, clazz);
 	sclass_java_Future = (*env)->GetSuperclass(env, clazz);
diff --git a/bind/testdata/classes.java.h.golden b/bind/testdata/classes.java.h.golden
index 4e8aed1..16362ed 100644
--- a/bind/testdata/classes.java.h.golden
+++ b/bind/testdata/classes.java.h.golden
@@ -59,8 +59,8 @@
 extern jint cproxy_java_Runnable_run(jint this);
 extern jint csuper_java_Runnable_run(jint this);
 extern jint cproxy_java_io_Console_flush(jint this);
-extern ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(jclass clazz, jmethodID m, jint a0);
-extern ret_jint cproxy_s_java_lang_System_console(jclass clazz, jmethodID m);
+extern ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(jint a0);
+extern ret_jint cproxy_s_java_lang_System_console();
 // JNI function headers for the Go <=> Java bridge.
 //   gobind -lang=java classes
 //