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

Side by Side Diff: Source/bindings/scripts/v8_interface.py

Issue 657523002: Skip expensive hasInstance() type-checks in overloads (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 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 # Copyright (C) 2013 Google Inc. All rights reserved. 1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 # coding=utf-8 2 # coding=utf-8
3 # 3 #
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 def resolution_tests_methods(effective_overloads): 675 def resolution_tests_methods(effective_overloads):
676 """Yields resolution test and associated method, in resolution order, for ef fective overloads of a given length. 676 """Yields resolution test and associated method, in resolution order, for ef fective overloads of a given length.
677 677
678 This is the heart of the resolution algorithm. 678 This is the heart of the resolution algorithm.
679 http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm 679 http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
680 680
681 Note that a given method can be listed multiple times, with different tests! 681 Note that a given method can be listed multiple times, with different tests!
682 This is to handle implicit type conversion. 682 This is to handle implicit type conversion.
683 683
684 Returns: 684 Returns:
685 [(test, method)] 685 [(test, method)]
bashi 2014/10/15 00:02:12 Could you update this comment?
686 """ 686 """
687 methods = [effective_overload[0] 687 methods = [effective_overload[0]
688 for effective_overload in effective_overloads] 688 for effective_overload in effective_overloads]
689 if len(methods) == 1: 689 if len(methods) == 1:
690 # If only one method with a given length, no test needed 690 # If only one method with a given length, no test needed
691 yield 'true', methods[0] 691 yield 'true', methods[0], -1
692 return 692 return
693 693
694 # 6. If there is more than one entry in S, then set d to be the 694 # 6. If there is more than one entry in S, then set d to be the
695 # distinguishing argument index for the entries of S. 695 # distinguishing argument index for the entries of S.
696 index = distinguishing_argument_index(effective_overloads) 696 index = distinguishing_argument_index(effective_overloads)
697 # (7-9 are for handling |undefined| values for optional arguments before 697 # (7-9 are for handling |undefined| values for optional arguments before
698 # the distinguishing argument (as “missing”), so you can specify only some 698 # the distinguishing argument (as “missing”), so you can specify only some
699 # optional arguments. We don’t support this, so we skip these steps.) 699 # optional arguments. We don’t support this, so we skip these steps.)
700 # 10. If i = d, then: 700 # 10. If i = d, then:
701 # (d is the distinguishing argument index) 701 # (d is the distinguishing argument index)
702 # 1. Let V be argi. 702 # 1. Let V be argi.
703 # Note: This is the argument that will be used to resolve which 703 # Note: This is the argument that will be used to resolve which
704 # overload is selected. 704 # overload is selected.
705 cpp_value = 'info[%s]' % index 705 cpp_value = 'info[%s]' % index
706 706
707 # Extract argument and IDL type to simplify accessing these in each loop. 707 # Extract argument and IDL type to simplify accessing these in each loop.
708 arguments = [method['arguments'][index] for method in methods] 708 arguments = [method['arguments'][index] for method in methods]
709 arguments_methods = zip(arguments, methods) 709 arguments_methods = zip(arguments, methods)
710 idl_types = [argument['idl_type_object'] for argument in arguments] 710 idl_types = [argument['idl_type_object'] for argument in arguments]
711 idl_types_methods = zip(idl_types, methods) 711 idl_types_methods = zip(idl_types, methods)
712 712
713 for argument in arguments:
714 argument['is_distinguishing_argument'] = True
715
713 # We can’t do a single loop through all methods or simply sort them, because 716 # We can’t do a single loop through all methods or simply sort them, because
714 # a method may be listed in multiple steps of the resolution algorithm, and 717 # a method may be listed in multiple steps of the resolution algorithm, and
715 # which test to apply differs depending on the step. 718 # which test to apply differs depending on the step.
716 # 719 #
717 # Instead, we need to go through all methods at each step, either finding 720 # Instead, we need to go through all methods at each step, either finding
718 # first match (if only one test is allowed) or filtering to matches (if 721 # first match (if only one test is allowed) or filtering to matches (if
719 # multiple tests are allowed), and generating an appropriate tests. 722 # multiple tests are allowed), and generating an appropriate tests.
720 723
721 # 2. If V is undefined, and there is an entry in S whose list of 724 # 2. If V is undefined, and there is an entry in S whose list of
722 # optionality values has “optional” at index i, then remove from S all 725 # optionality values has “optional” at index i, then remove from S all
723 # other entries. 726 # other entries.
724 try: 727 try:
725 method = next(method for argument, method in arguments_methods 728 method = next(method for argument, method in arguments_methods
726 if argument['is_optional']) 729 if argument['is_optional'])
727 test = '%s->IsUndefined()' % cpp_value 730 test = '%s->IsUndefined()' % cpp_value
728 yield test, method 731 yield test, method, -1
729 except StopIteration: 732 except StopIteration:
730 pass 733 pass
731 734
732 # 3. Otherwise: if V is null or undefined, and there is an entry in S that 735 # 3. Otherwise: if V is null or undefined, and there is an entry in S that
733 # has one of the following types at position i of its type list, 736 # has one of the following types at position i of its type list,
734 # • a nullable type 737 # • a nullable type
735 try: 738 try:
736 method = next(method for idl_type, method in idl_types_methods 739 method = next(method for idl_type, method in idl_types_methods
737 if idl_type.is_nullable) 740 if idl_type.is_nullable)
738 test = 'isUndefinedOrNull(%s)' % cpp_value 741 test = 'isUndefinedOrNull(%s)' % cpp_value
739 yield test, method 742 yield test, method, -1
740 except StopIteration: 743 except StopIteration:
741 pass 744 pass
742 745
743 # 4. Otherwise: if V is a platform object – but not a platform array 746 # 4. Otherwise: if V is a platform object – but not a platform array
744 # object – and there is an entry in S that has one of the following 747 # object – and there is an entry in S that has one of the following
745 # types at position i of its type list, 748 # types at position i of its type list,
746 # • an interface type that V implements 749 # • an interface type that V implements
747 # (Unlike most of these tests, this can return multiple methods, since we 750 # (Unlike most of these tests, this can return multiple methods, since we
748 # test if it implements an interface. Thus we need a for loop, not a next.) 751 # test if it implements an interface. Thus we need a for loop, not a next.)
749 # (We distinguish wrapper types from built-in interface types.) 752 # (We distinguish wrapper types from built-in interface types.)
750 for idl_type, method in ((idl_type, method) 753 for idl_type, method in ((idl_type, method)
751 for idl_type, method in idl_types_methods 754 for idl_type, method in idl_types_methods
752 if idl_type.is_wrapper_type): 755 if idl_type.is_wrapper_type):
753 test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.forma t(idl_type=idl_type.base_type, cpp_value=cpp_value) 756 test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.forma t(idl_type=idl_type.base_type, cpp_value=cpp_value)
754 yield test, method 757 yield test, method, index
755 758
756 # 8. Otherwise: if V is any kind of object except for a native Date object, 759 # 8. Otherwise: if V is any kind of object except for a native Date object,
757 # a native RegExp object, and there is an entry in S that has one of the 760 # a native RegExp object, and there is an entry in S that has one of the
758 # following types at position i of its type list, 761 # following types at position i of its type list,
759 # • an array type 762 # • an array type
760 # • a sequence type 763 # • a sequence type
761 # ... 764 # ...
762 # • a dictionary 765 # • a dictionary
763 # 766 #
764 # FIXME: 767 # FIXME:
765 # We don't strictly follow the algorithm here. The algorithm says "remove 768 # We don't strictly follow the algorithm here. The algorithm says "remove
766 # all other entries" if there is "one entry" matching, but we yield all 769 # all other entries" if there is "one entry" matching, but we yield all
767 # entries to support following constructors: 770 # entries to support following constructors:
768 # [constructor(sequence<DOMString> arg), constructor(Dictionary arg)] 771 # [constructor(sequence<DOMString> arg), constructor(Dictionary arg)]
769 # interface I { ... } 772 # interface I { ... }
770 # (Need to check array types before objects because an array is an object) 773 # (Need to check array types before objects because an array is an object)
771 for idl_type, method in idl_types_methods: 774 for idl_type, method in idl_types_methods:
772 if idl_type.native_array_element_type: 775 if idl_type.native_array_element_type:
773 # (We test for Array instead of generic Object to type-check.) 776 # (We test for Array instead of generic Object to type-check.)
774 # FIXME: test for Object during resolution, then have type check for 777 # FIXME: test for Object during resolution, then have type check for
775 # Array in overloaded method: http://crbug.com/262383 778 # Array in overloaded method: http://crbug.com/262383
776 yield '%s->IsArray()' % cpp_value, method 779 yield '%s->IsArray()' % cpp_value, method, index
777 for idl_type, method in idl_types_methods: 780 for idl_type, method in idl_types_methods:
778 if idl_type.is_dictionary or idl_type.name == 'Dictionary': 781 if idl_type.is_dictionary or idl_type.name == 'Dictionary':
779 # FIXME: should be '{1}->IsObject() && !{1}->IsDate() && !{1}->IsReg Exp()'.format(cpp_value) 782 # FIXME: should be '{1}->IsObject() && !{1}->IsDate() && !{1}->IsReg Exp()'.format(cpp_value)
780 # FIXME: the IsDate and IsRegExp checks can be skipped if we've 783 # FIXME: the IsDate and IsRegExp checks can be skipped if we've
781 # already generated tests for them. 784 # already generated tests for them.
782 yield '%s->IsObject()' % cpp_value, method 785 yield '%s->IsObject()' % cpp_value, method, index
783 786
784 # (Check for exact type matches before performing automatic type conversion; 787 # (Check for exact type matches before performing automatic type conversion;
785 # only needed if distinguishing between primitive types.) 788 # only needed if distinguishing between primitive types.)
786 if len([idl_type.is_primitive_type for idl_type in idl_types]) > 1: 789 if len([idl_type.is_primitive_type for idl_type in idl_types]) > 1:
787 # (Only needed if match in step 11, otherwise redundant.) 790 # (Only needed if match in step 11, otherwise redundant.)
788 if any(idl_type.is_string_type or idl_type.is_enum 791 if any(idl_type.is_string_type or idl_type.is_enum
789 for idl_type in idl_types): 792 for idl_type in idl_types):
790 # 10. Otherwise: if V is a Number value, and there is an entry in S 793 # 10. Otherwise: if V is a Number value, and there is an entry in S
791 # that has one of the following types at position i of its type 794 # that has one of the following types at position i of its type
792 # list, 795 # list,
793 # • a numeric type 796 # • a numeric type
794 try: 797 try:
795 method = next(method for idl_type, method in idl_types_methods 798 method = next(method for idl_type, method in idl_types_methods
796 if idl_type.is_numeric_type) 799 if idl_type.is_numeric_type)
797 test = '%s->IsNumber()' % cpp_value 800 test = '%s->IsNumber()' % cpp_value
798 yield test, method 801 yield test, method, index
799 except StopIteration: 802 except StopIteration:
800 pass 803 pass
801 804
802 # (Perform automatic type conversion, in order. If any of these match, 805 # (Perform automatic type conversion, in order. If any of these match,
803 # that’s the end, and no other tests are needed.) To keep this code simple, 806 # that’s the end, and no other tests are needed.) To keep this code simple,
804 # we rely on the C++ compiler's dead code elimination to deal with the 807 # we rely on the C++ compiler's dead code elimination to deal with the
805 # redundancy if both cases below trigger. 808 # redundancy if both cases below trigger.
806 809
807 # 11. Otherwise: if there is an entry in S that has one of the following 810 # 11. Otherwise: if there is an entry in S that has one of the following
808 # types at position i of its type list, 811 # types at position i of its type list,
809 # • DOMString 812 # • DOMString
810 # • ByteString 813 # • ByteString
811 # • ScalarValueString [a DOMString typedef, per definition.] 814 # • ScalarValueString [a DOMString typedef, per definition.]
812 # • an enumeration type 815 # • an enumeration type
813 try: 816 try:
814 method = next(method for idl_type, method in idl_types_methods 817 method = next(method for idl_type, method in idl_types_methods
815 if idl_type.is_string_type or idl_type.is_enum) 818 if idl_type.is_string_type or idl_type.is_enum)
816 yield 'true', method 819 yield 'true', method, -1
817 except StopIteration: 820 except StopIteration:
818 pass 821 pass
819 822
820 # 12. Otherwise: if there is an entry in S that has one of the following 823 # 12. Otherwise: if there is an entry in S that has one of the following
821 # types at position i of its type list, 824 # types at position i of its type list,
822 # • a numeric type 825 # • a numeric type
823 try: 826 try:
824 method = next(method for idl_type, method in idl_types_methods 827 method = next(method for idl_type, method in idl_types_methods
825 if idl_type.is_numeric_type) 828 if idl_type.is_numeric_type)
826 yield 'true', method 829 yield 'true', method, -1
827 except StopIteration: 830 except StopIteration:
828 pass 831 pass
829 832
830 833
831 ################################################################################ 834 ################################################################################
832 # Utility functions 835 # Utility functions
833 ################################################################################ 836 ################################################################################
834 837
835 def Counter(iterable): 838 def Counter(iterable):
836 # Once using Python 2.7, using collections.Counter 839 # Once using Python 2.7, using collections.Counter
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 deleter = next( 1136 deleter = next(
1134 method 1137 method
1135 for method in interface.operations 1138 for method in interface.operations
1136 if ('deleter' in method.specials and 1139 if ('deleter' in method.specials and
1137 len(method.arguments) == 1 and 1140 len(method.arguments) == 1 and
1138 str(method.arguments[0].idl_type) == 'DOMString')) 1141 str(method.arguments[0].idl_type) == 'DOMString'))
1139 except StopIteration: 1142 except StopIteration:
1140 return None 1143 return None
1141 1144
1142 return property_deleter(deleter) 1145 return property_deleter(deleter)
OLDNEW
« no previous file with comments | « no previous file | Source/bindings/scripts/v8_methods.py » ('j') | Source/bindings/scripts/v8_methods.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698