1# Copyright 2023 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""Codegen for GEN_JNI.java.""" 5 6import common 7import java_types 8 9 10def _stub_for_missing_native(sb, native): 11 sb(f'public static {native.proxy_return_type.to_java()} {native.proxy_name}') 12 with sb.param_list() as plist: 13 plist.extend(p.to_java_declaration() for p in native.proxy_params) 14 with sb.block(): 15 sb('throw new RuntimeException("Native method not present");\n') 16 17 18def _forwarding_method(sb, jni_mode, native, target_class_name): 19 sb(f'public static {native.proxy_return_type.to_java()} {native.proxy_name}') 20 sb.param_list([p.to_java_declaration() for p in native.proxy_params]) 21 with sb.block(): 22 with sb.statement(): 23 if not native.proxy_return_type.is_void(): 24 sb('return ') 25 if jni_mode.is_muxing: 26 sb(f'{target_class_name}.{native.muxed_name}') 27 with sb.param_list() as plist: 28 if native.muxed_switch_num != -1: 29 plist.append(str(native.muxed_switch_num)) 30 plist.extend(p.name for p in native.muxed_params) 31 else: 32 sb(f'{target_class_name}.{native.hashed_name}') 33 sb.param_list([p.name for p in native.proxy_params]) 34 35 36def _native_method(sb, jni_mode, native): 37 name = native.boundary_name(jni_mode) 38 if jni_mode.is_hashing: 39 sb(f'// Original name: {native.java_class.full_name_with_dots}#{native.name}\n' 40 ) 41 elif not jni_mode.is_muxing: 42 sb(f'// Hashed name: Java_J_N_{native.hashed_name}\n') 43 with sb.statement(): 44 sb(f'public static native {native.proxy_return_type.to_java()} {name}') 45 with sb.param_list() as plist: 46 if jni_mode.is_muxing: 47 if native.muxed_switch_num != -1: 48 plist.append('int _switchNum') 49 for i, p in enumerate(native.muxed_params): 50 plist.append(f'{p.java_type.to_java()} p{i}') 51 else: 52 plist.extend(p.to_java_declaration() for p in native.proxy_params) 53 54 55def generate_forwarding(jni_mode, script_name, full_gen_jni_class, 56 short_gen_jni_class, present_proxy_natives, 57 absent_proxy_natives): 58 """GEN_JNI.java that forwards calls to native methods on N.java.""" 59 sb = common.StringBuilder() 60 sb(f"""\ 61// 62// This file was generated by {script_name} 63// 64 65package {full_gen_jni_class.package_with_dots}; 66 67public class {full_gen_jni_class.name}""") 68 with sb.block(): 69 short_class_with_dots = short_gen_jni_class.full_name_with_dots 70 for native in present_proxy_natives: 71 _forwarding_method(sb, jni_mode, native, short_class_with_dots) 72 73 for native in absent_proxy_natives: 74 _stub_for_missing_native(sb, native) 75 return sb.to_string() 76 77 78def generate_impl(jni_mode, 79 script_name, 80 gen_jni_class, 81 boundary_proxy_natives, 82 absent_proxy_natives, 83 *, 84 whole_hash=None, 85 priority_hash=None): 86 """GEN_JNI.java (or N.java) that has all "public static native" methods.""" 87 sb = common.StringBuilder() 88 sb(f"""\ 89// 90// This file was generated by {script_name} 91// 92 93package {gen_jni_class.package_with_dots}; 94 95public class {gen_jni_class.name}""") 96 with sb.block(): 97 if jni_mode.is_muxing: 98 sb(f"""\ 99public static final long WHOLE_HASH = {whole_hash}L; 100public static final long PRIORITY_HASH = {priority_hash}L; 101 102""") 103 104 for native in boundary_proxy_natives: 105 _native_method(sb, jni_mode, native) 106 for native in absent_proxy_natives: 107 _stub_for_missing_native(sb, native) 108 return sb.to_string() 109