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

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

Issue 11038015: Android: lazy initialization for method id. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moves to MethodID Created 8 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 | Annotate | Revision Log
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 # TODO (qinmin): Need to refactor this file as base should not know about 6 # TODO (qinmin): Need to refactor this file as base should not know about
7 # higher level concepts. Currently this file has knowledge about higher level 7 # higher level concepts. Currently this file has knowledge about higher level
8 # java classes. 8 # java classes.
9 9
10 """Extracts native methods from a Java file and generates the JNI bindings. 10 """Extracts native methods from a Java file and generates the JNI bindings.
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 namespace { 594 namespace {
595 $CLASS_PATH_DEFINITIONS 595 $CLASS_PATH_DEFINITIONS
596 } // namespace 596 } // namespace
597 597
598 $OPEN_NAMESPACE 598 $OPEN_NAMESPACE
599 $FORWARD_DECLARATIONS 599 $FORWARD_DECLARATIONS
600 600
601 // Step 2: method stubs. 601 // Step 2: method stubs.
602 $METHOD_STUBS 602 $METHOD_STUBS
603 603
604 // Step 3: GetMethodIDs and RegisterNatives. 604 // Step 3: RegisterNatives.
605 static void GetMethodIDsImpl(JNIEnv* env) {
606 $GET_METHOD_IDS_IMPL
607 }
608 605
609 static bool RegisterNativesImpl(JNIEnv* env) { 606 static bool RegisterNativesImpl(JNIEnv* env) {
610 GetMethodIDsImpl(env);
joth 2012/10/04 17:59:59 one thing I did remember this morning: currently i
bulach 2012/10/04 18:58:17 I agree in principle, but for app classes, how can
611 $REGISTER_NATIVES_IMPL 607 $REGISTER_NATIVES_IMPL
612 return true; 608 return true;
613 } 609 }
614 $CLOSE_NAMESPACE 610 $CLOSE_NAMESPACE
615 #endif // ${HEADER_GUARD} 611 #endif // ${HEADER_GUARD}
616 """) 612 """)
617 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) 613 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep)
618 base_index = script_components.index('base') 614 base_index = script_components.index('base')
619 script_name = os.sep.join(script_components[base_index:]) 615 script_name = os.sep.join(script_components[base_index:])
620 values = { 616 values = {
621 'SCRIPT_NAME': script_name, 617 'SCRIPT_NAME': script_name,
622 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, 618 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class,
623 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), 619 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(),
624 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), 620 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(),
625 'METHOD_STUBS': self.GetMethodStubsString(), 621 'METHOD_STUBS': self.GetMethodStubsString(),
626 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), 622 'OPEN_NAMESPACE': self.GetOpenNamespaceString(),
627 'GET_METHOD_IDS_IMPL': self.GetMethodIDsImplString(),
628 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(), 623 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString(),
629 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), 624 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(),
630 'HEADER_GUARD': self.header_guard, 625 'HEADER_GUARD': self.header_guard,
631 } 626 }
632 return WrapOutput(template.substitute(values)) 627 return WrapOutput(template.substitute(values))
633 628
634 def GetClassPathDefinitionsString(self): 629 def GetClassPathDefinitionsString(self):
635 ret = [] 630 ret = []
636 ret += [self.GetClassPathDefinitions()] 631 ret += [self.GetClassPathDefinitions()]
637 return '\n'.join(ret) 632 return '\n'.join(ret)
(...skipping 15 matching lines...) Expand all
653 return '\n'.join(ret) 648 return '\n'.join(ret)
654 649
655 def GetKMethodsString(self, clazz): 650 def GetKMethodsString(self, clazz):
656 ret = [] 651 ret = []
657 for native in self.natives: 652 for native in self.natives:
658 if (native.java_class_name == clazz or 653 if (native.java_class_name == clazz or
659 (not native.java_class_name and clazz == self.class_name)): 654 (not native.java_class_name and clazz == self.class_name)):
660 ret += [self.GetKMethodArrayEntry(native)] 655 ret += [self.GetKMethodArrayEntry(native)]
661 return '\n'.join(ret) 656 return '\n'.join(ret)
662 657
663 def GetMethodIDsImplString(self):
664 ret = []
665 ret += [self.GetFindClasses()]
666 for called_by_native in self.called_by_natives:
667 ret += [self.GetMethodIDImpl(called_by_native)]
668 return '\n'.join(ret)
669
670 def GetRegisterNativesImplString(self): 658 def GetRegisterNativesImplString(self):
671 """Returns the implementation for RegisterNatives.""" 659 """Returns the implementation for RegisterNatives."""
672 template = Template("""\ 660 template = Template("""\
673 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { 661 static const JNINativeMethod kMethods${JAVA_CLASS}[] = {
674 ${KMETHODS} 662 ${KMETHODS}
675 }; 663 };
676 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); 664 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS});
677 665
678 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz, 666 if (env->RegisterNatives(g_${JAVA_CLASS}_clazz,
679 kMethods${JAVA_CLASS}, 667 kMethods${JAVA_CLASS},
680 kMethods${JAVA_CLASS}Size) < 0) { 668 kMethods${JAVA_CLASS}Size) < 0) {
681 LOG(ERROR) << "RegisterNatives failed in " << __FILE__; 669 LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
682 return false; 670 return false;
683 } 671 }
684 """) 672 """)
685 ret = [] 673 ret = [self.GetFindClasses()]
686 all_classes = self.GetUniqueClasses(self.natives) 674 all_classes = self.GetUniqueClasses(self.natives)
687 all_classes[self.class_name] = self.fully_qualified_class 675 all_classes[self.class_name] = self.fully_qualified_class
688 for clazz in all_classes: 676 for clazz in all_classes:
689 kmethods = self.GetKMethodsString(clazz) 677 kmethods = self.GetKMethodsString(clazz)
690 if kmethods: 678 if kmethods:
691 values = {'JAVA_CLASS': clazz, 679 values = {'JAVA_CLASS': clazz,
692 'KMETHODS': kmethods} 680 'KMETHODS': kmethods}
693 ret += [template.substitute(values)] 681 ret += [template.substitute(values)]
694 if not ret: return '' 682 if not ret: return ''
695 return '\n' + '\n'.join(ret) 683 return '\n' + '\n'.join(ret)
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 """Returns a string.""" 772 """Returns a string."""
785 function_signature_template = Template("""\ 773 function_signature_template = Template("""\
786 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ 774 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\
787 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") 775 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""")
788 function_header_template = Template("""\ 776 function_header_template = Template("""\
789 ${FUNCTION_SIGNATURE} {""") 777 ${FUNCTION_SIGNATURE} {""")
790 function_header_with_unused_template = Template("""\ 778 function_header_with_unused_template = Template("""\
791 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); 779 ${FUNCTION_SIGNATURE} __attribute__ ((unused));
792 ${FUNCTION_SIGNATURE} {""") 780 ${FUNCTION_SIGNATURE} {""")
793 template = Template(""" 781 template = Template("""
794 static jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; 782 static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0;
795 ${FUNCTION_HEADER} 783 ${FUNCTION_HEADER}
796 /* Must call RegisterNativesImpl() */ 784 /* Must call RegisterNativesImpl() */
797 DCHECK(g_${JAVA_CLASS}_clazz); 785 DCHECK(g_${JAVA_CLASS}_clazz);
798 DCHECK(g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); 786 jmethodID method_id =
787 ${GET_METHOD_ID_IMPL}
799 ${RETURN_DECLARATION} 788 ${RETURN_DECLARATION}
800 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, 789 ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL},
801 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL}; 790 method_id${PARAMS_IN_CALL})${POST_CALL};
802 ${CHECK_EXCEPTION} 791 ${CHECK_EXCEPTION}
803 ${RETURN_CLAUSE} 792 ${RETURN_CLAUSE}
804 }""") 793 }""")
805 if called_by_native.static or called_by_native.is_constructor: 794 if called_by_native.static or called_by_native.is_constructor:
806 first_param_in_declaration = '' 795 first_param_in_declaration = ''
807 first_param_in_call = ('g_%s_clazz' % 796 first_param_in_call = ('g_%s_clazz' %
808 (called_by_native.java_class_name or 797 (called_by_native.java_class_name or
809 self.class_name)) 798 self.class_name))
810 else: 799 else:
811 first_param_in_declaration = ', jobject obj' 800 first_param_in_declaration = ', jobject obj'
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, 835 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration,
847 'PARAMS_IN_DECLARATION': params_in_declaration, 836 'PARAMS_IN_DECLARATION': params_in_declaration,
848 'STATIC': 'Static' if called_by_native.static else '', 837 'STATIC': 'Static' if called_by_native.static else '',
849 'PRE_CALL': pre_call, 838 'PRE_CALL': pre_call,
850 'POST_CALL': post_call, 839 'POST_CALL': post_call,
851 'ENV_CALL': called_by_native.env_call, 840 'ENV_CALL': called_by_native.env_call,
852 'FIRST_PARAM_IN_CALL': first_param_in_call, 841 'FIRST_PARAM_IN_CALL': first_param_in_call,
853 'PARAMS_IN_CALL': params_for_call, 842 'PARAMS_IN_CALL': params_for_call,
854 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 843 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
855 'CHECK_EXCEPTION': check_exception, 844 'CHECK_EXCEPTION': check_exception,
845 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native)
856 } 846 }
857 values['FUNCTION_SIGNATURE'] = ( 847 values['FUNCTION_SIGNATURE'] = (
858 function_signature_template.substitute(values)) 848 function_signature_template.substitute(values))
859 if called_by_native.system_class: 849 if called_by_native.system_class:
860 values['FUNCTION_HEADER'] = ( 850 values['FUNCTION_HEADER'] = (
861 function_header_with_unused_template.substitute(values)) 851 function_header_with_unused_template.substitute(values))
862 else: 852 else:
863 values['FUNCTION_HEADER'] = function_header_template.substitute(values) 853 values['FUNCTION_HEADER'] = function_header_template.substitute(values)
864 return template.substitute(values) 854 return template.substitute(values)
865 855
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( 904 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
915 base::android::GetUnscopedClass(env, k${JAVA_CLASS}ClassPath)));""") 905 base::android::GetUnscopedClass(env, k${JAVA_CLASS}ClassPath)));""")
916 ret = [] 906 ret = []
917 for clazz in self.GetUniqueClasses(self.called_by_natives): 907 for clazz in self.GetUniqueClasses(self.called_by_natives):
918 values = {'JAVA_CLASS': clazz} 908 values = {'JAVA_CLASS': clazz}
919 ret += [template.substitute(values)] 909 ret += [template.substitute(values)]
920 return '\n'.join(ret) 910 return '\n'.join(ret)
921 911
922 def GetMethodIDImpl(self, called_by_native): 912 def GetMethodIDImpl(self, called_by_native):
923 """Returns the implementation of GetMethodID.""" 913 """Returns the implementation of GetMethodID."""
924 template = Template("""\ 914 template = Template("""
925 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 915 base::android::MethodID::LazyGet<
926 base::android::Get${STATIC}MethodID${SUFFIX}( 916 base::android::MethodID::METHODTYPE_${STATIC},
927 env, g_${JAVA_CLASS}_clazz, 917 base::android::MethodID::EXCEPTIONCHECK_${CHECK_EXCEPTION}>(
928 "${JNI_NAME}", 918 env, g_${JAVA_CLASS}_clazz,
929 ${JNI_SIGNATURE}); 919 "${JNI_NAME}",
920 ${JNI_SIGNATURE},
921 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME});
930 """) 922 """)
931 jni_name = called_by_native.name 923 jni_name = called_by_native.name
932 jni_return_type = called_by_native.return_type 924 jni_return_type = called_by_native.return_type
933 if called_by_native.is_constructor: 925 if called_by_native.is_constructor:
934 jni_name = '<init>' 926 jni_name = '<init>'
935 jni_return_type = 'void' 927 jni_return_type = 'void'
936 values = { 928 values = {
937 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 929 'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
938 'JNI_NAME': jni_name, 930 'JNI_NAME': jni_name,
939 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 931 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
940 'STATIC': 'Static' if called_by_native.static else '', 932 'STATIC': 'STATIC' if called_by_native.static else 'NORMAL',
941 'SUFFIX': 'OrNull' if called_by_native.system_class else '', 933 'CHECK_EXCEPTION': 'NO' if called_by_native.system_class else 'YES',
942 'JNI_SIGNATURE': JniSignature(called_by_native.params, 934 'JNI_SIGNATURE': JniSignature(called_by_native.params,
943 jni_return_type, 935 jni_return_type,
944 True) 936 True)
945 } 937 }
946 return template.substitute(values) 938 return template.substitute(values)
947 939
948 940
949 def WrapOutput(output): 941 def WrapOutput(output):
950 ret = [] 942 ret = []
951 for line in output.splitlines(): 943 for line in output.splitlines():
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 input_file = options.input_file 1036 input_file = options.input_file
1045 output_file = None 1037 output_file = None
1046 if options.output_dir: 1038 if options.output_dir:
1047 root_name = os.path.splitext(os.path.basename(input_file))[0] 1039 root_name = os.path.splitext(os.path.basename(input_file))[0]
1048 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1040 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1049 GenerateJNIHeader(input_file, output_file, options.namespace) 1041 GenerateJNIHeader(input_file, output_file, options.namespace)
1050 1042
1051 1043
1052 if __name__ == '__main__': 1044 if __name__ == '__main__':
1053 sys.exit(main(sys.argv)) 1045 sys.exit(main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698