OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "lib/invocation_mirror.h" | 5 #include "lib/invocation_mirror.h" |
6 #include "vm/bootstrap_natives.h" | 6 #include "vm/bootstrap_natives.h" |
7 #include "vm/class_finalizer.h" | 7 #include "vm/class_finalizer.h" |
8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
10 #include "vm/exceptions.h" | 10 #include "vm/exceptions.h" |
11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
12 #include "vm/parser.h" | 12 #include "vm/parser.h" |
13 #include "vm/port.h" | 13 #include "vm/port.h" |
14 #include "vm/resolver.h" | 14 #include "vm/resolver.h" |
15 #include "vm/symbols.h" | 15 #include "vm/symbols.h" |
16 | 16 |
17 namespace dart { | 17 namespace dart { |
18 | 18 |
19 DEFINE_FLAG(bool, use_mirrored_compilation_error, false, | 19 DEFINE_FLAG(bool, use_mirrored_compilation_error, false, |
20 "Wrap compilation errors that occur during reflective access in a " | 20 "Wrap compilation errors that occur during reflective access in a " |
21 "MirroredCompilationError, rather than suspending the isolate."); | 21 "MirroredCompilationError, rather than suspending the isolate."); |
22 | 22 |
23 DEFINE_FLAG(bool, support_find_in_context, false, | |
24 "Experimental support for ClosureMirror.findInContext."); | |
25 | |
26 static RawInstance* CreateMirror(const String& mirror_class_name, | 23 static RawInstance* CreateMirror(const String& mirror_class_name, |
27 const Array& constructor_arguments) { | 24 const Array& constructor_arguments) { |
28 const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary()); | 25 const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary()); |
29 const String& constructor_name = Symbols::Dot(); | 26 const String& constructor_name = Symbols::Dot(); |
30 | 27 |
31 const Object& result = Object::Handle( | 28 const Object& result = Object::Handle( |
32 DartLibraryCalls::InstanceCreate(mirrors_lib, | 29 DartLibraryCalls::InstanceCreate(mirrors_lib, |
33 mirror_class_name, | 30 mirror_class_name, |
34 constructor_name, | 31 constructor_name, |
35 constructor_arguments)); | 32 constructor_arguments)); |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 UNREACHABLE(); | 662 UNREACHABLE(); |
666 } | 663 } |
667 | 664 |
668 // Fall through case: Indicate that we didn't find any function or field using | 665 // Fall through case: Indicate that we didn't find any function or field using |
669 // a special null instance. This is different from a field being null. Callers | 666 // a special null instance. This is different from a field being null. Callers |
670 // make sure that this null does not leak into Dartland. | 667 // make sure that this null does not leak into Dartland. |
671 return Object::sentinel().raw(); | 668 return Object::sentinel().raw(); |
672 } | 669 } |
673 | 670 |
674 | 671 |
675 // TODO(13656): Remove AllowPrivate. | |
676 static RawInstance* InvokeLibraryGetterAllowImports( | |
677 const Library& library, | |
678 const String& getter_name, | |
679 const bool throw_nsm_if_absent) { | |
680 // To access a top-level we may need to use the Field or the getter Function. | |
681 // The getter function may either be in the library or in the field's owner | |
682 // class, depending on whether it was an actual getter, or an uninitialized | |
683 // field. | |
684 const Field& field = Field::Handle( | |
685 library.LookupFieldAllowPrivate(getter_name)); | |
686 Function& getter = Function::Handle(); | |
687 if (field.IsNull()) { | |
688 // No field found. Check for a getter in the lib. | |
689 const String& internal_getter_name = | |
690 String::Handle(Field::GetterName(getter_name)); | |
691 getter = library.LookupFunctionAllowPrivate(internal_getter_name); | |
692 if (getter.IsNull()) { | |
693 getter = library.LookupFunctionAllowPrivate(getter_name); | |
694 if (!getter.IsNull()) { | |
695 // Looking for a getter but found a regular method: closurize it. | |
696 const Function& closure_function = | |
697 Function::Handle(getter.ImplicitClosureFunction()); | |
698 return closure_function.ImplicitStaticClosure(); | |
699 } | |
700 } | |
701 } else { | |
702 if (!field.IsUninitialized()) { | |
703 return field.value(); | |
704 } | |
705 // An uninitialized field was found. Check for a getter in the field's | |
706 // owner classs. | |
707 const Class& klass = Class::Handle(field.owner()); | |
708 const String& internal_getter_name = | |
709 String::Handle(Field::GetterName(getter_name)); | |
710 getter = klass.LookupStaticFunction(internal_getter_name); | |
711 } | |
712 | |
713 if (!getter.IsNull() && getter.is_visible()) { | |
714 // Invoke the getter and return the result. | |
715 const Object& result = Object::Handle( | |
716 DartEntry::InvokeFunction(getter, Object::empty_array())); | |
717 return ReturnResult(result); | |
718 } | |
719 | |
720 if (throw_nsm_if_absent) { | |
721 ThrowNoSuchMethod(Instance::null_instance(), | |
722 getter_name, | |
723 getter, | |
724 InvocationMirror::kTopLevel, | |
725 InvocationMirror::kGetter); | |
726 UNREACHABLE(); | |
727 } | |
728 | |
729 // Fall through case: Indicate that we didn't find any function or field using | |
730 // a special null instance. This is different from a field being null. Callers | |
731 // make sure that this null does not leak into Dartland. | |
732 return Object::sentinel().raw(); | |
733 } | |
734 | |
735 | |
736 static RawInstance* InvokeClassGetter(const Class& klass, | 672 static RawInstance* InvokeClassGetter(const Class& klass, |
737 const String& getter_name, | 673 const String& getter_name, |
738 const bool throw_nsm_if_absent) { | 674 const bool throw_nsm_if_absent) { |
739 // Note static fields do not have implicit getters. | 675 // Note static fields do not have implicit getters. |
740 const Field& field = Field::Handle(klass.LookupStaticField(getter_name)); | 676 const Field& field = Field::Handle(klass.LookupStaticField(getter_name)); |
741 if (field.IsNull() || field.IsUninitialized()) { | 677 if (field.IsNull() || field.IsUninitialized()) { |
742 const String& internal_getter_name = String::Handle( | 678 const String& internal_getter_name = String::Handle( |
743 Field::GetterName(getter_name)); | 679 Field::GetterName(getter_name)); |
744 Function& getter = Function::Handle( | 680 Function& getter = Function::Handle( |
745 klass.LookupStaticFunction(internal_getter_name)); | 681 klass.LookupStaticFunction(internal_getter_name)); |
(...skipping 24 matching lines...) Expand all Loading... |
770 | 706 |
771 // Invoke the getter and return the result. | 707 // Invoke the getter and return the result. |
772 const Object& result = Object::Handle( | 708 const Object& result = Object::Handle( |
773 DartEntry::InvokeFunction(getter, Object::empty_array())); | 709 DartEntry::InvokeFunction(getter, Object::empty_array())); |
774 return ReturnResult(result); | 710 return ReturnResult(result); |
775 } | 711 } |
776 return field.value(); | 712 return field.value(); |
777 } | 713 } |
778 | 714 |
779 | 715 |
780 | |
781 | |
782 static RawInstance* InvokeInstanceGetter(const Class& klass, | 716 static RawInstance* InvokeInstanceGetter(const Class& klass, |
783 const Instance& reflectee, | 717 const Instance& reflectee, |
784 const String& getter_name, | 718 const String& getter_name, |
785 const bool throw_nsm_if_absent) { | 719 const bool throw_nsm_if_absent) { |
786 const String& internal_getter_name = String::Handle( | 720 const String& internal_getter_name = String::Handle( |
787 Field::GetterName(getter_name)); | 721 Field::GetterName(getter_name)); |
788 Function& function = Function::Handle( | 722 Function& function = Function::Handle( |
789 Resolver::ResolveDynamicAnyArgs(klass, internal_getter_name)); | 723 Resolver::ResolveDynamicAnyArgs(klass, internal_getter_name)); |
790 | 724 |
791 if (!function.IsNull() || throw_nsm_if_absent) { | 725 if (!function.IsNull() || throw_nsm_if_absent) { |
(...skipping 11 matching lines...) Expand all Loading... |
803 args_descriptor); | 737 args_descriptor); |
804 } | 738 } |
805 | 739 |
806 // Fall through case: Indicate that we didn't find any function or field using | 740 // Fall through case: Indicate that we didn't find any function or field using |
807 // a special null instance. This is different from a field being null. Callers | 741 // a special null instance. This is different from a field being null. Callers |
808 // make sure that this null does not leak into Dartland. | 742 // make sure that this null does not leak into Dartland. |
809 return Object::sentinel().raw(); | 743 return Object::sentinel().raw(); |
810 } | 744 } |
811 | 745 |
812 | 746 |
813 static RawInstance* LookupFunctionOrFieldInLibraryPrefix( | |
814 const LibraryPrefix& prefix, | |
815 const String& lookup_name) { | |
816 const Object& entry = Object::Handle(prefix.LookupObject(lookup_name)); | |
817 if (!entry.IsNull()) { | |
818 if (entry.IsField()) { | |
819 const Field& field = Field::Cast(entry); | |
820 const Class& field_owner = Class::Handle(field.owner()); | |
821 const Library& field_library = Library::Handle(field_owner.library()); | |
822 const Instance& result = Instance::Handle( | |
823 InvokeLibraryGetterAllowImports(field_library, lookup_name, false)); | |
824 if (result.raw() != Object::sentinel().raw()) { | |
825 return result.raw(); | |
826 } | |
827 } else if (entry.IsFunction()) { | |
828 const Function& func = Function::Cast(entry); | |
829 const Function& closure_function = Function::Handle( | |
830 func.ImplicitClosureFunction()); | |
831 return closure_function.ImplicitStaticClosure(); | |
832 } | |
833 } | |
834 | |
835 // Fall through case: Indicate that we didn't find any function or field using | |
836 // a special null instance. This is different from a field being null. Callers | |
837 // make sure that this null does not leak into Dartland. | |
838 return Object::sentinel().raw(); | |
839 } | |
840 | |
841 | |
842 static RawInstance* LookupStaticFunctionOrFieldInClass( | |
843 const Class& klass, | |
844 const String& lookup_name) { | |
845 Instance& result = Instance::Handle( | |
846 InvokeClassGetter(klass, lookup_name, false)); | |
847 if (result.raw() != Object::sentinel().raw()) { | |
848 return result.raw(); | |
849 } | |
850 | |
851 const Function& func = | |
852 Function::Handle(klass.LookupStaticFunction(lookup_name)); | |
853 if (!func.IsNull()) { | |
854 const Function& closure_function = Function::Handle( | |
855 func.ImplicitClosureFunction()); | |
856 ASSERT(!closure_function.IsNull()); | |
857 return closure_function.ImplicitStaticClosure(); | |
858 } | |
859 | |
860 // Fall through case: Indicate that we didn't find any function or field using | |
861 // a special null instance. This is different from a field being null. Callers | |
862 // make sure that this null does not leak into Dartland. | |
863 return Object::sentinel().raw(); | |
864 } | |
865 | |
866 | |
867 static RawInstance* LookupFunctionOrFieldInFunctionContext( | |
868 const Function& func, | |
869 const Context& ctx, | |
870 const String& lookup_name) { | |
871 const ContextScope& ctx_scope = ContextScope::Handle(func.context_scope()); | |
872 intptr_t this_index = -1; | |
873 | |
874 // Search local context. | |
875 String& name = String::Handle(); | |
876 for (intptr_t i = 0; i < ctx_scope.num_variables(); i++) { | |
877 name ^= ctx_scope.NameAt(i); | |
878 if (name.Equals(lookup_name)) { | |
879 return ctx.At(i); | |
880 } else if (name.Equals(Symbols::This())) { | |
881 // Record instance index to search for the field in the instance | |
882 // afterwards. | |
883 this_index = i; | |
884 } | |
885 } | |
886 | |
887 // Search the instance this function is attached to. | |
888 if (this_index >= 0) { | |
889 // Since we want the closurized version of a function, we can access, both, | |
890 // functions and fields through their implicit getter name. If the implicit | |
891 // getter does not exist for the function, a method extractor will be | |
892 // created. | |
893 const Class& owner = Class::Handle(func.Owner()); | |
894 const Instance& receiver = Instance::Handle(ctx.At(this_index)); | |
895 return InvokeInstanceGetter(owner, receiver, lookup_name, false); | |
896 } | |
897 | |
898 // Fall through case: Indicate that we didn't find any function or field using | |
899 // a special null instance. This is different from a field being null. Callers | |
900 // make sure that this null does not leak into Dartland. | |
901 return Object::sentinel().raw(); | |
902 } | |
903 | |
904 | |
905 static RawInstance* LookupFunctionOrFieldInLibraryHelper( | |
906 const Library& library, | |
907 const String& class_name, | |
908 const String& lookup_name) { | |
909 if (class_name.IsNull()) { | |
910 const Instance& result = Instance::Handle( | |
911 InvokeLibraryGetterAllowImports(library, lookup_name, false)); | |
912 if (result.raw() != Object::sentinel().raw()) { | |
913 return result.raw(); | |
914 } | |
915 const Function& func = Function::Handle( | |
916 library.LookupLocalFunction(lookup_name)); | |
917 if (!func.IsNull()) { | |
918 const Function& closure_function = Function::Handle( | |
919 func.ImplicitClosureFunction()); | |
920 return closure_function.ImplicitStaticClosure(); | |
921 } | |
922 } else { | |
923 const Class& cls = Class::Handle( | |
924 library.LookupClass(class_name)); | |
925 if (!cls.IsNull()) { | |
926 return LookupStaticFunctionOrFieldInClass(cls, lookup_name); | |
927 } | |
928 } | |
929 | |
930 // Fall through case: Indicate that we didn't find any function or field using | |
931 // a special null instance. This is different from a field being null. Callers | |
932 // make sure that this null does not leak into Dartland. | |
933 return Object::sentinel().raw(); | |
934 } | |
935 | |
936 | |
937 static RawInstance* LookupFunctionOrFieldInLibrary(const Library& library, | |
938 const String& class_name, | |
939 const String& lookup_name) { | |
940 Instance& result = Instance::Handle(); | |
941 // Check current library. | |
942 result ^= LookupFunctionOrFieldInLibraryHelper( | |
943 library, class_name, lookup_name); | |
944 if (result.raw() != Object::sentinel().raw()) { | |
945 return result.raw(); | |
946 } | |
947 // Check all imports. | |
948 Library& lib_it = Library::Handle(); | |
949 for (intptr_t i = 0; i < library.num_imports(); i++) { | |
950 lib_it ^= library.ImportLibraryAt(i); | |
951 result ^= LookupFunctionOrFieldInLibraryHelper( | |
952 lib_it, class_name, lookup_name); | |
953 if (result.raw() != Object::sentinel().raw()) { | |
954 return result.raw(); | |
955 } | |
956 } | |
957 | |
958 // Fall through case: Indicate that we didn't find any function or field using | |
959 // a special null instance. This is different from a field being null. Callers | |
960 // make sure that this null does not leak into Dartland. | |
961 return Object::sentinel().raw(); | |
962 } | |
963 | |
964 | |
965 static RawAbstractType* InstantiateType(const AbstractType& type, | 747 static RawAbstractType* InstantiateType(const AbstractType& type, |
966 const AbstractType& instantiator) { | 748 const AbstractType& instantiator) { |
967 ASSERT(type.IsFinalized()); | 749 ASSERT(type.IsFinalized()); |
968 ASSERT(!type.IsMalformed()); | 750 ASSERT(!type.IsMalformed()); |
969 | 751 |
970 if (type.IsInstantiated()) { | 752 if (type.IsInstantiated()) { |
971 return type.Canonicalize(); | 753 return type.Canonicalize(); |
972 } | 754 } |
973 | 755 |
974 ASSERT(!instantiator.IsNull()); | 756 ASSERT(!instantiator.IsNull()); |
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1561 | 1343 |
1562 DEFINE_NATIVE_ENTRY(InstanceMirror_computeType, 1) { | 1344 DEFINE_NATIVE_ENTRY(InstanceMirror_computeType, 1) { |
1563 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); | 1345 GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); |
1564 const Type& type = Type::Handle(instance.GetType()); | 1346 const Type& type = Type::Handle(instance.GetType()); |
1565 // The static type of null is specified to be the bottom type, however, the | 1347 // The static type of null is specified to be the bottom type, however, the |
1566 // runtime type of null is the Null type, which we correctly return here. | 1348 // runtime type of null is the Null type, which we correctly return here. |
1567 return type.Canonicalize(); | 1349 return type.Canonicalize(); |
1568 } | 1350 } |
1569 | 1351 |
1570 | 1352 |
1571 DEFINE_NATIVE_ENTRY(ClosureMirror_find_in_context, 2) { | |
1572 if (!FLAG_support_find_in_context) { | |
1573 return Object::empty_array().raw(); | |
1574 } | |
1575 | |
1576 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); | |
1577 GET_NON_NULL_NATIVE_ARGUMENT(Array, lookup_parts, arguments->NativeArgAt(1)); | |
1578 ASSERT(lookup_parts.Length() >= 1 && lookup_parts.Length() <= 3); | |
1579 | |
1580 if (!closure.IsClosure()) { | |
1581 const Array& result_tuple = Array::Handle(Array::New(2)); | |
1582 result_tuple.SetAt(0, Bool::False()); | |
1583 return result_tuple.raw(); | |
1584 } | |
1585 | |
1586 Function& function = Function::Handle(); | |
1587 const bool callable = closure.IsCallable(&function, NULL); | |
1588 ASSERT(callable); | |
1589 | |
1590 const intptr_t parts_len = lookup_parts.Length(); | |
1591 // Lookup name is always the last part. | |
1592 const String& lookup_name = String::Handle(String::RawCast( | |
1593 lookup_parts.At(parts_len - 1))); | |
1594 | |
1595 String& part_name = String::Handle(); | |
1596 Class& owner = Class::Handle(function.Owner()); | |
1597 LibraryPrefix& prefix = LibraryPrefix::Handle(); | |
1598 Library& this_library = Library::Handle(owner.library()); | |
1599 Instance& result = Instance::Handle(Object::sentinel().raw()); | |
1600 if (parts_len == 1) { | |
1601 // Could be either a field in context, an instance or static field of the | |
1602 // enclosing class, or a field in the current library or any imported | |
1603 // library. | |
1604 result ^= LookupFunctionOrFieldInFunctionContext( | |
1605 function, Context::Handle(Closure::context(closure)), lookup_name); | |
1606 if (result.raw() == Object::sentinel().raw()) { | |
1607 result ^= LookupStaticFunctionOrFieldInClass(owner, lookup_name); | |
1608 } | |
1609 if (result.raw() == Object::sentinel().raw()) { | |
1610 result ^= LookupFunctionOrFieldInLibrary(this_library, | |
1611 part_name, | |
1612 lookup_name); | |
1613 } | |
1614 } else if (parts_len == 2) { | |
1615 // Could be either library.field or class.staticfield. | |
1616 part_name ^= lookup_parts.At(0); | |
1617 prefix ^= this_library.LookupLocalLibraryPrefix(part_name); | |
1618 if (prefix.IsNull()) { | |
1619 result ^= LookupFunctionOrFieldInLibrary(this_library, | |
1620 part_name, | |
1621 lookup_name); | |
1622 } else { | |
1623 result ^= LookupFunctionOrFieldInLibraryPrefix(prefix, lookup_name); | |
1624 } | |
1625 } else { | |
1626 ASSERT(parts_len == 3); | |
1627 // Can only be library.class.staticfield. | |
1628 part_name ^= lookup_parts.At(0); | |
1629 prefix ^= this_library.LookupLocalLibraryPrefix(part_name); | |
1630 if (!prefix.IsNull()) { | |
1631 part_name ^= lookup_parts.At(1); | |
1632 owner ^= prefix.LookupClass(part_name); | |
1633 if (!owner.IsNull()) { | |
1634 result ^= LookupStaticFunctionOrFieldInClass(owner, lookup_name); | |
1635 } | |
1636 } | |
1637 } | |
1638 | |
1639 // We return a tuple (list) where the first slot is a boolean indicates | |
1640 // whether we found a field or function and the second slot contains the | |
1641 // result. This is needed to distinguish between not finding a field and a | |
1642 // field containing null as value. | |
1643 const Array& result_tuple = Array::Handle(Array::New(2)); | |
1644 if (result.raw() == Object::sentinel().raw()) { | |
1645 result_tuple.SetAt(0, Bool::False()); | |
1646 // No need to set the value. | |
1647 } else { | |
1648 result_tuple.SetAt(0, Bool::True()); | |
1649 result_tuple.SetAt(1, result); | |
1650 } | |
1651 return result_tuple.raw(); | |
1652 } | |
1653 | |
1654 | |
1655 DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) { | 1353 DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) { |
1656 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); | 1354 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); |
1657 ASSERT(!closure.IsNull()); | 1355 ASSERT(!closure.IsNull()); |
1658 | 1356 |
1659 Function& function = Function::Handle(); | 1357 Function& function = Function::Handle(); |
1660 bool callable = closure.IsCallable(&function, NULL); | 1358 bool callable = closure.IsCallable(&function, NULL); |
1661 if (callable) { | 1359 if (callable) { |
1662 return CreateMethodMirror(function, Instance::null_instance()); | 1360 return CreateMethodMirror(function, Instance::null_instance()); |
1663 } | 1361 } |
1664 return Instance::null(); | 1362 return Instance::null(); |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2248 } | 1946 } |
2249 | 1947 |
2250 DEFINE_NATIVE_ENTRY(TypeMirror_moreSpecificTest, 2) { | 1948 DEFINE_NATIVE_ENTRY(TypeMirror_moreSpecificTest, 2) { |
2251 GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0)); | 1949 GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0)); |
2252 GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1)); | 1950 GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1)); |
2253 return Bool::Get(a.IsMoreSpecificThan(b, NULL)).raw(); | 1951 return Bool::Get(a.IsMoreSpecificThan(b, NULL)).raw(); |
2254 } | 1952 } |
2255 | 1953 |
2256 | 1954 |
2257 } // namespace dart | 1955 } // namespace dart |
OLD | NEW |