Check exceptions after calling Enum.ordinal() from Rust
[ldk-java] / java_strings.py
index a83671db48a27c1d23cd9e3875d5736765afca88..5ff98d9d4113a0c40cb11ee7b83ca77ad3d01f4a 100644 (file)
@@ -103,9 +103,10 @@ public class version {
 
         self.util_fn_pfx = """package org.ldk.structs;
 import org.ldk.impl.bindings;
+import org.ldk.enums.*;
+import org.ldk.util.*;
 import java.util.Arrays;
 import javax.annotation.Nullable;
-import org.ldk.enums.*;
 
 public class UtilMethods {
 """
@@ -128,6 +129,9 @@ class CommonBase {
 #include <stdatomic.h>
 #include <stdlib.h>
 
+#define LIKELY(v) __builtin_expect(!!(v), 1)
+#define UNLIKELY(v) __builtin_expect(!!(v), 0)
+
 """
 
         if self.target == Target.ANDROID:
@@ -163,6 +167,7 @@ void __attribute__((constructor)) spawn_stderr_redirection() {
             self.c_file_pfx = self.c_file_pfx + """#define MALLOC(a, _) malloc(a)
 #define FREE(p) if ((uint64_t)(p) > 4096) { free(p); }
 #define CHECK_ACCESS(p)
+#define CHECK_INNER_FIELD_ACCESS_OR_NULL(v)
 """
         if not DEBUG:
             self.c_file_pfx += """#define DO_ASSERT(a) (void)(a)
@@ -319,7 +324,7 @@ void __wrap_free(void* ptr) {
        __real_free(ptr);
 }
 
-static void CHECK_ACCESS(void* ptr) {
+static void CHECK_ACCESS(const void* ptr) {
        DO_ASSERT(!pthread_mutex_lock(&allocation_mtx));
        allocation* it = allocation_ll;
        while (it->ptr != ptr) {
@@ -336,6 +341,13 @@ static void CHECK_ACCESS(void* ptr) {
        }
        DO_ASSERT(!pthread_mutex_unlock(&allocation_mtx));
 }
+#define CHECK_INNER_FIELD_ACCESS_OR_NULL(v) \\
+       if (v.is_owned && v.inner != NULL) { \\
+               const void *p = __unmangle_inner_ptr(v.inner); \\
+               if (p != NULL) { \\
+                       CHECK_ACCESS(p); \\
+               } \\
+       }
 
 void* __real_realloc(void* ptr, size_t newlen);
 void* __wrap_realloc(void* ptr, size_t len) {
@@ -607,8 +619,13 @@ import javax.annotation.Nullable;
         out_java_enum = "package org.ldk.enums;\n\n"
         out_java = ""
         out_c = ""
-        out_c = out_c + "static inline LDK" + struct_name + " LDK" + struct_name + "_from_java(" + self.c_fn_args_pfx + ") {\n"
-        out_c = out_c + "\tswitch ((*env)->CallIntMethod(env, clz, ordinal_meth)) {\n"
+        out_c += "static inline LDK" + struct_name + " LDK" + struct_name + "_from_java(" + self.c_fn_args_pfx + ") {\n"
+        out_c += "\tjint ord = (*env)->CallIntMethod(env, clz, ordinal_meth);\n"
+        out_c += "\tif (UNLIKELY((*env)->ExceptionCheck(env))) {\n"
+        out_c += "\t\t(*env)->ExceptionDescribe(env);\n"
+        out_c += "\t\t(*env)->FatalError(env, \"A call to " + struct_name + ".ordinal() from rust threw an exception.\");\n"
+        out_c += "\t}\n"
+        out_c += "\tswitch (ord) {\n"
 
         if enum_doc_comment is not None:
             out_java_enum += "/**\n * " + enum_doc_comment.replace("\n", "\n * ") + "\n */\n"
@@ -624,9 +641,10 @@ import javax.annotation.Nullable;
         out_java_enum = out_java_enum + "\tstatic { init(); }\n"
         out_java_enum = out_java_enum + "}"
         out_java = out_java + "\tstatic { " + struct_name + ".values(); /* Force enum statics to run */ }\n"
-        out_c = out_c + "\t}\n"
-        out_c = out_c + "\tabort();\n"
-        out_c = out_c + "}\n"
+        out_c += "\t}\n"
+        out_c += "\t(*env)->FatalError(env, \"A call to " + struct_name + ".ordinal() from rust returned an invalid value.\");\n"
+        out_c += "\tabort(); // Unreachable, but will let the compiler know we don't return here\n"
+        out_c += "}\n"
 
         out_c = out_c + "static jclass " + struct_name + "_class = NULL;\n"
         for var, _ in variants:
@@ -892,7 +910,7 @@ import javax.annotation.Nullable;
                         out_c = out_c + ", " + arg_info.arg_name
                 out_c = out_c + ");\n"
 
-                out_c += "\tif ((*env)->ExceptionCheck(env)) {\n"
+                out_c += "\tif (UNLIKELY((*env)->ExceptionCheck(env))) {\n"
                 out_c += "\t\t(*env)->ExceptionDescribe(env);\n"
                 out_c += "\t\t(*env)->FatalError(env, \"A call to " + fn_line.fn_name + " in " + struct_name + " from rust threw an exception.\");\n"
                 out_c += "\t}\n"
@@ -1178,6 +1196,7 @@ import javax.annotation.Nullable;
                 out_java += (arg_conv_info.java_ty + " " + arg_conv_info.arg_name)
 
         out_java_struct = ""
+        extra_java_struct_out = ""
         if not args_known:
             out_java_struct += ("\t// Skipped " + method_name + "\n")
         else:
@@ -1192,7 +1211,18 @@ import javax.annotation.Nullable;
                     out_java_struct += "\tpublic static " + return_type_info.java_hu_ty + " with_default("
                 else:
                     out_java_struct += "\tpublic static " + return_type_info.java_hu_ty + " " + meth_n + "("
+            elif meth_n == "clone_ptr":
+                out_java_struct += ("\t" + return_type_info.java_hu_ty + " " + meth_n + "(")
             else:
+                if meth_n == "hash" and return_type_info.java_hu_ty == "long":
+                    extra_java_struct_out = "\t@Override public int hashCode() {\n"
+                    extra_java_struct_out += "\t\treturn (int)this.hash();\n"
+                    extra_java_struct_out += "\t}\n"
+                elif meth_n == "eq" and return_type_info.java_hu_ty == "boolean":
+                    extra_java_struct_out = "\t@Override public boolean equals(Object o) {\n"
+                    extra_java_struct_out += "\t\tif (!(o instanceof " + struct_meth + ")) return false;\n"
+                    extra_java_struct_out += "\t\treturn this.eq((" + struct_meth + ")o);\n"
+                    extra_java_struct_out += "\t}\n"
                 out_java_struct += ("\tpublic " + return_type_info.java_hu_ty + " " + meth_n + "(")
             for idx, arg in enumerate(argument_types):
                 if idx != 0:
@@ -1315,4 +1345,4 @@ import javax.annotation.Nullable;
                 out_java_struct += ("\t\treturn ret;\n")
             out_java_struct += ("\t}\n\n")
 
-        return (out_java, out_c, out_java_struct)
+        return (out_java, out_c, out_java_struct + extra_java_struct_out)