Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(699)

Side by Side Diff: base/android/jni_generator/jni_generator.py

Issue 2361353002: Link stack frames of JNI stubs to JNI callbacks. (Closed)
Patch Set: Simplify - remove FakeStackFrame, etc. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Extracts native methods from a Java file and generates the JNI bindings. 6 """Extracts native methods from a Java file and generates the JNI bindings.
7 If you change this, please run and update the tests.""" 7 If you change this, please run and update the tests."""
8 8
9 import collections 9 import collections
10 import errno 10 import errno
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 // For 729 // For
730 // ${FULLY_QUALIFIED_CLASS} 730 // ${FULLY_QUALIFIED_CLASS}
731 731
732 #ifndef ${HEADER_GUARD} 732 #ifndef ${HEADER_GUARD}
733 #define ${HEADER_GUARD} 733 #define ${HEADER_GUARD}
734 734
735 #include <jni.h> 735 #include <jni.h>
736 736
737 ${INCLUDES} 737 ${INCLUDES}
738 738
739 ${PROFILING_INCLUDES}
739 #include "base/android/jni_int_wrapper.h" 740 #include "base/android/jni_int_wrapper.h"
740 741
741 // Step 1: forward declarations. 742 // Step 1: forward declarations.
742 namespace { 743 namespace {
743 $CLASS_PATH_DEFINITIONS 744 $CLASS_PATH_DEFINITIONS
744 745
745 } // namespace 746 } // namespace
746 747
747 $OPEN_NAMESPACE 748 $OPEN_NAMESPACE
748 749
(...skipping 14 matching lines...) Expand all
763 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, 764 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class,
764 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), 765 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(),
765 'CONSTANT_FIELDS': self.GetConstantFieldsString(), 766 'CONSTANT_FIELDS': self.GetConstantFieldsString(),
766 'METHOD_STUBS': self.GetMethodStubsString(), 767 'METHOD_STUBS': self.GetMethodStubsString(),
767 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), 768 'OPEN_NAMESPACE': self.GetOpenNamespaceString(),
768 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), 769 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(),
769 'REGISTER_NATIVES': self.GetRegisterNativesString(), 770 'REGISTER_NATIVES': self.GetRegisterNativesString(),
770 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), 771 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(),
771 'HEADER_GUARD': self.header_guard, 772 'HEADER_GUARD': self.header_guard,
772 'INCLUDES': self.GetIncludesString(), 773 'INCLUDES': self.GetIncludesString(),
774 'PROFILING_INCLUDES': self.GetProfilingIncludesString(),
773 } 775 }
774 assert ((values['JNI_NATIVE_METHODS'] == '') == 776 assert ((values['JNI_NATIVE_METHODS'] == '') ==
775 (values['REGISTER_NATIVES'] == '')) 777 (values['REGISTER_NATIVES'] == ''))
776 return WrapOutput(template.substitute(values)) 778 return WrapOutput(template.substitute(values))
777 779
778 def GetClassPathDefinitionsString(self): 780 def GetClassPathDefinitionsString(self):
779 ret = [] 781 ret = []
780 ret += [self.GetClassPathDefinitions()] 782 ret += [self.GetClassPathDefinitions()]
781 return '\n'.join(ret) 783 return '\n'.join(ret)
782 784
(...skipping 17 matching lines...) Expand all
800 def GetLazyCalledByNativeMethodStubs(self): 802 def GetLazyCalledByNativeMethodStubs(self):
801 return [self.GetLazyCalledByNativeMethodStub(called_by_native) 803 return [self.GetLazyCalledByNativeMethodStub(called_by_native)
802 for called_by_native in self.called_by_natives] 804 for called_by_native in self.called_by_natives]
803 805
804 def GetIncludesString(self): 806 def GetIncludesString(self):
805 if not self.options.includes: 807 if not self.options.includes:
806 return '' 808 return ''
807 includes = self.options.includes.split(',') 809 includes = self.options.includes.split(',')
808 return '\n'.join('#include "%s"' % x for x in includes) 810 return '\n'.join('#include "%s"' % x for x in includes)
809 811
812 def GetProfilingIncludesString(self):
813 if not self.options.enable_profiling:
814 return ''
815 return '#include "base/compiler_specific.h"'
816
810 def GetKMethodsString(self, clazz): 817 def GetKMethodsString(self, clazz):
811 ret = [] 818 ret = []
812 for native in self.natives: 819 for native in self.natives:
813 if (native.java_class_name == clazz or 820 if (native.java_class_name == clazz or
814 (not native.java_class_name and clazz == self.class_name)): 821 (not native.java_class_name and clazz == self.class_name)):
815 ret += [self.GetKMethodArrayEntry(native)] 822 ret += [self.GetKMethodArrayEntry(native)]
816 return '\n'.join(ret) 823 return '\n'.join(ret)
817 824
818 def SubstituteNativeMethods(self, template): 825 def SubstituteNativeMethods(self, template):
819 """Substitutes JAVA_CLASS and KMETHODS in the provided template.""" 826 """Substitutes JAVA_CLASS and KMETHODS in the provided template."""
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 else: 1001 else:
995 params_in_call.append(p.name) 1002 params_in_call.append(p.name)
996 params_in_call = ', '.join(params_in_call) 1003 params_in_call = ', '.join(params_in_call)
997 1004
998 return_type = return_declaration = JavaDataTypeToC(native.return_type) 1005 return_type = return_declaration = JavaDataTypeToC(native.return_type)
999 post_call = '' 1006 post_call = ''
1000 if re.match(RE_SCOPED_JNI_TYPES, return_type): 1007 if re.match(RE_SCOPED_JNI_TYPES, return_type):
1001 post_call = '.Release()' 1008 post_call = '.Release()'
1002 return_declaration = ('base::android::ScopedJavaLocalRef<' + return_type + 1009 return_declaration = ('base::android::ScopedJavaLocalRef<' + return_type +
1003 '>') 1010 '>')
1011 profiling_entered_native = ''
1012 if self.options.enable_profiling:
1013 profiling_entered_native = 'JNI_PROFILING_ENTERED_NATIVE;'
1004 values = { 1014 values = {
1005 'RETURN': return_type, 1015 'RETURN': return_type,
1006 'RETURN_DECLARATION': return_declaration, 1016 'RETURN_DECLARATION': return_declaration,
1007 'NAME': native.name, 1017 'NAME': native.name,
1008 'PARAMS': self.GetParamsInDeclaration(native), 1018 'PARAMS': self.GetParamsInDeclaration(native),
1009 'PARAMS_IN_STUB': self.GetParamsInStub(native), 1019 'PARAMS_IN_STUB': self.GetParamsInStub(native),
1010 'PARAMS_IN_CALL': params_in_call, 1020 'PARAMS_IN_CALL': params_in_call,
1011 'POST_CALL': post_call, 1021 'POST_CALL': post_call,
1012 'STUB_NAME': self.GetStubName(native), 1022 'STUB_NAME': self.GetStubName(native),
1023 'PROFILING_ENTERED_NATIVE': profiling_entered_native,
1013 } 1024 }
1014 1025
1015 if is_method: 1026 if is_method:
1016 optional_error_return = JavaReturnValueToC(native.return_type) 1027 optional_error_return = JavaReturnValueToC(native.return_type)
1017 if optional_error_return: 1028 if optional_error_return:
1018 optional_error_return = ', ' + optional_error_return 1029 optional_error_return = ', ' + optional_error_return
1019 values.update({ 1030 values.update({
1020 'OPTIONAL_ERROR_RETURN': optional_error_return, 1031 'OPTIONAL_ERROR_RETURN': optional_error_return,
1021 'PARAM0_NAME': native.params[0].name, 1032 'PARAM0_NAME': native.params[0].name,
1022 'P0_TYPE': native.p0_type, 1033 'P0_TYPE': native.p0_type,
1023 }) 1034 })
1024 template = Template("""\ 1035 template = Template("""\
1025 extern "C" __attribute__((visibility("default"))) 1036 extern "C" __attribute__((visibility("default")))
1026 ${RETURN} ${STUB_NAME}(JNIEnv* env, 1037 ${RETURN} ${STUB_NAME}(JNIEnv* env,
1027 ${PARAMS_IN_STUB}) { 1038 ${PARAMS_IN_STUB}) {
1039 ${PROFILING_ENTERED_NATIVE}
1028 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); 1040 ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME});
1029 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); 1041 CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN});
1030 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; 1042 return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL};
1031 } 1043 }
1032 """) 1044 """)
1033 else: 1045 else:
1034 template = Template(""" 1046 template = Template("""
1035 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); 1047 static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS});
1036 1048
1037 extern "C" __attribute__((visibility("default"))) 1049 extern "C" __attribute__((visibility("default")))
1038 ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { 1050 ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) {
1051 ${PROFILING_ENTERED_NATIVE}
1039 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; 1052 return ${NAME}(${PARAMS_IN_CALL})${POST_CALL};
1040 } 1053 }
1041 """) 1054 """)
1042 1055
1043 return template.substitute(values) 1056 return template.substitute(values)
1044 1057
1045 def GetArgument(self, param): 1058 def GetArgument(self, param):
1046 if param.datatype == 'int': 1059 if param.datatype == 'int':
1047 return 'as_jint(' + param.name + ')' 1060 return 'as_jint(' + param.name + ')'
1048 elif re.match(RE_SCOPED_JNI_TYPES, JavaDataTypeToC(param.datatype)): 1061 elif re.match(RE_SCOPED_JNI_TYPES, JavaDataTypeToC(param.datatype)):
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 return_declaration = '' 1099 return_declaration = ''
1087 return_clause = '' 1100 return_clause = ''
1088 if return_type != 'void': 1101 if return_type != 'void':
1089 pre_call = ' ' + pre_call 1102 pre_call = ' ' + pre_call
1090 return_declaration = return_type + ' ret =' 1103 return_declaration = return_type + ' ret ='
1091 if re.match(RE_SCOPED_JNI_TYPES, return_type): 1104 if re.match(RE_SCOPED_JNI_TYPES, return_type):
1092 return_type = 'base::android::ScopedJavaLocalRef<' + return_type + '>' 1105 return_type = 'base::android::ScopedJavaLocalRef<' + return_type + '>'
1093 return_clause = 'return ' + return_type + '(env, ret);' 1106 return_clause = 'return ' + return_type + '(env, ret);'
1094 else: 1107 else:
1095 return_clause = 'return ret;' 1108 return_clause = 'return ret;'
1109 profiling_leaving_native = ''
1110 if self.options.enable_profiling:
1111 profiling_leaving_native = 'JNI_PROFILING_LEAVING_NATIVE;'
1096 return { 1112 return {
1097 'JAVA_CLASS': java_class, 1113 'JAVA_CLASS': java_class,
1098 'RETURN_TYPE': return_type, 1114 'RETURN_TYPE': return_type,
1099 'OPTIONAL_ERROR_RETURN': optional_error_return, 1115 'OPTIONAL_ERROR_RETURN': optional_error_return,
1100 'RETURN_DECLARATION': return_declaration, 1116 'RETURN_DECLARATION': return_declaration,
1101 'RETURN_CLAUSE': return_clause, 1117 'RETURN_CLAUSE': return_clause,
1102 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, 1118 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration,
1103 'PARAMS_IN_DECLARATION': params_in_declaration, 1119 'PARAMS_IN_DECLARATION': params_in_declaration,
1104 'PRE_CALL': pre_call, 1120 'PRE_CALL': pre_call,
1105 'POST_CALL': post_call, 1121 'POST_CALL': post_call,
1106 'ENV_CALL': called_by_native.env_call, 1122 'ENV_CALL': called_by_native.env_call,
1107 'FIRST_PARAM_IN_CALL': first_param_in_call, 1123 'FIRST_PARAM_IN_CALL': first_param_in_call,
1108 'PARAMS_IN_CALL': params_in_call, 1124 'PARAMS_IN_CALL': params_in_call,
1109 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 1125 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
1110 'CHECK_EXCEPTION': check_exception, 1126 'CHECK_EXCEPTION': check_exception,
1111 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native) 1127 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native),
1128 'PROFILING_LEAVING_NATIVE': profiling_leaving_native,
1112 } 1129 }
1113 1130
1114 1131
1115 def GetLazyCalledByNativeMethodStub(self, called_by_native): 1132 def GetLazyCalledByNativeMethodStub(self, called_by_native):
1116 """Returns a string.""" 1133 """Returns a string."""
1117 function_signature_template = Template("""\ 1134 function_signature_template = Template("""\
1118 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ 1135 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\
1119 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") 1136 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""")
1120 function_header_template = Template("""\ 1137 function_header_template = Template("""\
1121 ${FUNCTION_SIGNATURE} {""") 1138 ${FUNCTION_SIGNATURE} {""")
1122 function_header_with_unused_template = Template("""\ 1139 function_header_with_unused_template = Template("""\
1123 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); 1140 ${FUNCTION_SIGNATURE} __attribute__ ((unused));
1124 ${FUNCTION_SIGNATURE} {""") 1141 ${FUNCTION_SIGNATURE} {""")
1125 template = Template(""" 1142 template = Template("""
1126 static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; 1143 static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0;
1127 ${FUNCTION_HEADER} 1144 ${FUNCTION_HEADER}
1128 CHECK_CLAZZ(env, ${FIRST_PARAM_IN_CALL}, 1145 CHECK_CLAZZ(env, ${FIRST_PARAM_IN_CALL},
1129 ${JAVA_CLASS}_clazz(env)${OPTIONAL_ERROR_RETURN}); 1146 ${JAVA_CLASS}_clazz(env)${OPTIONAL_ERROR_RETURN});
1130 jmethodID method_id = 1147 jmethodID method_id =
1131 ${GET_METHOD_ID_IMPL} 1148 ${GET_METHOD_ID_IMPL}
1149 ${PROFILING_LEAVING_NATIVE}
1132 ${RETURN_DECLARATION} 1150 ${RETURN_DECLARATION}
1133 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, 1151 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL},
1134 method_id${PARAMS_IN_CALL})${POST_CALL}; 1152 method_id${PARAMS_IN_CALL})${POST_CALL};
1135 ${CHECK_EXCEPTION} 1153 ${CHECK_EXCEPTION}
1136 ${RETURN_CLAUSE} 1154 ${RETURN_CLAUSE}
1137 }""") 1155 }""")
1138 values = self.GetCalledByNativeValues(called_by_native) 1156 values = self.GetCalledByNativeValues(called_by_native)
1139 values['FUNCTION_SIGNATURE'] = ( 1157 values['FUNCTION_SIGNATURE'] = (
1140 function_signature_template.substitute(values)) 1158 function_signature_template.substitute(values))
1141 if called_by_native.system_class: 1159 if called_by_native.system_class:
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 help='The type used to represent native pointers in ' 1374 help='The type used to represent native pointers in '
1357 'Java code. For 32-bit, use int; ' 1375 'Java code. For 32-bit, use int; '
1358 'for 64-bit, use long.') 1376 'for 64-bit, use long.')
1359 option_parser.add_option('--cpp', default='cpp', 1377 option_parser.add_option('--cpp', default='cpp',
1360 help='The path to cpp command.') 1378 help='The path to cpp command.')
1361 option_parser.add_option('--javap', default='javap', 1379 option_parser.add_option('--javap', default='javap',
1362 help='The path to javap command.') 1380 help='The path to javap command.')
1363 option_parser.add_option('--native_exports_optional', action='store_true', 1381 option_parser.add_option('--native_exports_optional', action='store_true',
1364 help='Support both explicit and native method' 1382 help='Support both explicit and native method'
1365 'registration.') 1383 'registration.')
1384 option_parser.add_option('--enable_profiling', action='store_true',
1385 help='Add additional profiling instrumentation.')
1366 options, args = option_parser.parse_args(argv) 1386 options, args = option_parser.parse_args(argv)
1367 if options.jar_file: 1387 if options.jar_file:
1368 input_file = ExtractJarInputFile(options.jar_file, options.input_file, 1388 input_file = ExtractJarInputFile(options.jar_file, options.input_file,
1369 options.output_dir) 1389 options.output_dir)
1370 elif options.input_file: 1390 elif options.input_file:
1371 input_file = options.input_file 1391 input_file = options.input_file
1372 else: 1392 else:
1373 option_parser.print_help() 1393 option_parser.print_help()
1374 print '\nError: Must specify --jar_file or --input_file.' 1394 print '\nError: Must specify --jar_file or --input_file.'
1375 return 1 1395 return 1
1376 output_file = None 1396 output_file = None
1377 if options.output_dir: 1397 if options.output_dir:
1378 root_name = os.path.splitext(os.path.basename(input_file))[0] 1398 root_name = os.path.splitext(os.path.basename(input_file))[0]
1379 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1399 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1380 GenerateJNIHeader(input_file, output_file, options) 1400 GenerateJNIHeader(input_file, output_file, options)
1381 1401
1382 if options.depfile: 1402 if options.depfile:
1383 build_utils.WriteDepfile(options.depfile, output_file) 1403 build_utils.WriteDepfile(options.depfile, output_file)
1384 1404
1385 1405
1386 if __name__ == '__main__': 1406 if __name__ == '__main__':
1387 sys.exit(main(sys.argv)) 1407 sys.exit(main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698