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

Side by Side Diff: runtime/lib/mirrors.cc

Issue 276043003: Lay waste to ClosureMirror.findInContext. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: remove stub in dart2js Created 6 years, 7 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
« no previous file with comments | « no previous file | runtime/lib/mirrors_impl.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/mirrors_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698