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 #ifndef VM_DART_API_STATE_H_ | 5 #ifndef VM_DART_API_STATE_H_ |
6 #define VM_DART_API_STATE_H_ | 6 #define VM_DART_API_STATE_H_ |
7 | 7 |
8 #include "include/dart_api.h" | 8 #include "include/dart_api.h" |
9 | 9 |
10 #include "platform/utils.h" | 10 #include "platform/utils.h" |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 DISALLOW_COPY_AND_ASSIGN(PersistentHandle); | 196 DISALLOW_COPY_AND_ASSIGN(PersistentHandle); |
197 }; | 197 }; |
198 | 198 |
199 | 199 |
200 // Implementation of persistent handles which are handed out through the | 200 // Implementation of persistent handles which are handed out through the |
201 // dart API. | 201 // dart API. |
202 class FinalizablePersistentHandle { | 202 class FinalizablePersistentHandle { |
203 public: | 203 public: |
204 static FinalizablePersistentHandle* New( | 204 static FinalizablePersistentHandle* New( |
205 Isolate* isolate, | 205 Isolate* isolate, |
206 bool is_prologue, | |
207 const Object& object, | 206 const Object& object, |
208 void* peer, | 207 void* peer, |
209 Dart_WeakPersistentHandleFinalizer callback, | 208 Dart_WeakPersistentHandleFinalizer callback, |
210 intptr_t external_size); | 209 intptr_t external_size); |
211 | 210 |
212 // Accessors. | 211 // Accessors. |
213 RawObject* raw() const { return raw_; } | 212 RawObject* raw() const { return raw_; } |
214 RawObject** raw_addr() { return &raw_; } | 213 RawObject** raw_addr() { return &raw_; } |
215 static intptr_t raw_offset() { | 214 static intptr_t raw_offset() { |
216 return OFFSET_OF(FinalizablePersistentHandle, raw_); | 215 return OFFSET_OF(FinalizablePersistentHandle, raw_); |
(...skipping 27 matching lines...) Expand all Loading... |
244 } | 243 } |
245 } | 244 } |
246 | 245 |
247 // Idempotent. Called when the handle is explicitly deleted or the | 246 // Idempotent. Called when the handle is explicitly deleted or the |
248 // referent becomes unreachable. | 247 // referent becomes unreachable. |
249 void EnsureFreeExternal(Isolate* isolate) { | 248 void EnsureFreeExternal(Isolate* isolate) { |
250 isolate->heap()->FreeExternal(external_size(), SpaceForExternal()); | 249 isolate->heap()->FreeExternal(external_size(), SpaceForExternal()); |
251 set_external_size(0); | 250 set_external_size(0); |
252 } | 251 } |
253 | 252 |
254 bool IsPrologueWeakPersistent() { | |
255 return PrologueWeakBit::decode(external_data_); | |
256 } | |
257 | |
258 void SetPrologueWeakPersistent(bool value) { | |
259 external_data_ = PrologueWeakBit::update(value, external_data_); | |
260 } | |
261 | |
262 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle); | 253 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle); |
263 | 254 |
264 private: | 255 private: |
265 enum { | 256 enum { |
266 kExternalNewSpaceBit = 0, | 257 kExternalNewSpaceBit = 0, |
267 kPrologueWeakBit = 1, | 258 kExternalSizeBits = 1, |
268 kExternalSizeBits = 2, | 259 kExternalSizeBitsSize = (kBitsPerWord - 1), |
269 kExternalSizeBitsSize = (kBitsPerWord - 2), | |
270 }; | 260 }; |
271 | 261 |
272 // This part of external_data_ is the number of externally allocated bytes. | 262 // This part of external_data_ is the number of externally allocated bytes. |
273 // TODO(koda): Measure size in words instead. | 263 // TODO(koda): Measure size in words instead. |
274 class ExternalSizeBits : public BitField<intptr_t, | 264 class ExternalSizeBits : public BitField<intptr_t, |
275 kExternalSizeBits, | 265 kExternalSizeBits, |
276 kExternalSizeBitsSize> {}; // NOLINT | 266 kExternalSizeBitsSize> {}; // NOLINT |
277 // This bit of external_data_ is true if the referent was created in new | 267 // This bit of external_data_ is true if the referent was created in new |
278 // space and UpdateRelocated has not yet detected any promotion. | 268 // space and UpdateRelocated has not yet detected any promotion. |
279 class ExternalNewSpaceBit : public BitField<bool, kExternalNewSpaceBit, 1> {}; | 269 class ExternalNewSpaceBit : public BitField<bool, kExternalNewSpaceBit, 1> {}; |
280 // This bit is used to indicate that it is a prologue weak persistent handle. | |
281 class PrologueWeakBit : public BitField<bool, kPrologueWeakBit, 1> {}; | |
282 | 270 |
283 friend class FinalizablePersistentHandles; | 271 friend class FinalizablePersistentHandles; |
284 | 272 |
285 FinalizablePersistentHandle() | 273 FinalizablePersistentHandle() |
286 : raw_(NULL), | 274 : raw_(NULL), |
287 peer_(NULL), | 275 peer_(NULL), |
288 external_data_(0), | 276 external_data_(0), |
289 callback_(NULL) { } | 277 callback_(NULL) { } |
290 ~FinalizablePersistentHandle() { } | 278 ~FinalizablePersistentHandle() { } |
291 | 279 |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 initial_capacity, | 654 initial_capacity, |
667 ApiNativeScope::Current()->zone()) {} | 655 ApiNativeScope::Current()->zone()) {} |
668 ApiGrowableArray() | 656 ApiGrowableArray() |
669 : BaseGrowableArray<T, ValueObject>( | 657 : BaseGrowableArray<T, ValueObject>( |
670 ApiNativeScope::Current()->zone()) {} | 658 ApiNativeScope::Current()->zone()) {} |
671 ApiGrowableArray(intptr_t initial_capacity, Zone* zone) | 659 ApiGrowableArray(intptr_t initial_capacity, Zone* zone) |
672 : BaseGrowableArray<T, ValueObject>(initial_capacity, zone) {} | 660 : BaseGrowableArray<T, ValueObject>(initial_capacity, zone) {} |
673 }; | 661 }; |
674 | 662 |
675 | 663 |
676 // Forward declarations. | |
677 class WeakReferenceSetBuilder; | |
678 class WeakReferenceSet; | |
679 | |
680 | |
681 // Implementation of the API State used in dart api for maintaining | 664 // Implementation of the API State used in dart api for maintaining |
682 // local scopes, persistent handles etc. These are setup on a per isolate | 665 // local scopes, persistent handles etc. These are setup on a per isolate |
683 // basis and destroyed when the isolate is shutdown. | 666 // basis and destroyed when the isolate is shutdown. |
684 class ApiState { | 667 class ApiState { |
685 public: | 668 public: |
686 ApiState() : persistent_handles_(), | 669 ApiState() : persistent_handles_(), |
687 weak_persistent_handles_(), | 670 weak_persistent_handles_(), |
688 prologue_weak_persistent_handles_(), | |
689 reusable_scope_(NULL), | 671 reusable_scope_(NULL), |
690 top_scope_(NULL), | 672 top_scope_(NULL), |
691 delayed_weak_reference_sets_(NULL), | |
692 null_(NULL), | 673 null_(NULL), |
693 true_(NULL), | 674 true_(NULL), |
694 false_(NULL), | 675 false_(NULL), |
695 acquired_error_(NULL) {} | 676 acquired_error_(NULL) {} |
696 ~ApiState() { | 677 ~ApiState() { |
697 while (top_scope_ != NULL) { | 678 while (top_scope_ != NULL) { |
698 ApiLocalScope* scope = top_scope_; | 679 ApiLocalScope* scope = top_scope_; |
699 top_scope_ = top_scope_->previous(); | 680 top_scope_ = top_scope_->previous(); |
700 delete scope; | 681 delete scope; |
701 } | 682 } |
(...skipping 23 matching lines...) Expand all Loading... |
725 } | 706 } |
726 ApiLocalScope* top_scope() const { return top_scope_; } | 707 ApiLocalScope* top_scope() const { return top_scope_; } |
727 void set_top_scope(ApiLocalScope* value) { top_scope_ = value; } | 708 void set_top_scope(ApiLocalScope* value) { top_scope_ = value; } |
728 | 709 |
729 PersistentHandles& persistent_handles() { return persistent_handles_; } | 710 PersistentHandles& persistent_handles() { return persistent_handles_; } |
730 | 711 |
731 FinalizablePersistentHandles& weak_persistent_handles() { | 712 FinalizablePersistentHandles& weak_persistent_handles() { |
732 return weak_persistent_handles_; | 713 return weak_persistent_handles_; |
733 } | 714 } |
734 | 715 |
735 FinalizablePersistentHandles& prologue_weak_persistent_handles() { | |
736 return prologue_weak_persistent_handles_; | |
737 } | |
738 | |
739 WeakReferenceSet* delayed_weak_reference_sets() { | |
740 return delayed_weak_reference_sets_; | |
741 } | |
742 void set_delayed_weak_reference_sets(WeakReferenceSet* reference_set) { | |
743 delayed_weak_reference_sets_ = reference_set; | |
744 } | |
745 | |
746 void UnwindScopes(uword stack_marker) { | 716 void UnwindScopes(uword stack_marker) { |
747 // Unwind all scopes using the same stack_marker, i.e. all scopes allocated | 717 // Unwind all scopes using the same stack_marker, i.e. all scopes allocated |
748 // under the same top_exit_frame_info. | 718 // under the same top_exit_frame_info. |
749 while (top_scope_ != NULL && | 719 while (top_scope_ != NULL && |
750 top_scope_->stack_marker() != 0 && | 720 top_scope_->stack_marker() != 0 && |
751 top_scope_->stack_marker() == stack_marker) { | 721 top_scope_->stack_marker() == stack_marker) { |
752 ApiLocalScope* scope = top_scope_; | 722 ApiLocalScope* scope = top_scope_; |
753 top_scope_ = top_scope_->previous(); | 723 top_scope_ = top_scope_->previous(); |
754 delete scope; | 724 delete scope; |
755 } | 725 } |
756 } | 726 } |
757 | 727 |
758 void VisitObjectPointers(ObjectPointerVisitor* visitor, | 728 void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
759 bool visit_prologue_weak_handles) { | |
760 ApiLocalScope* scope = top_scope_; | 729 ApiLocalScope* scope = top_scope_; |
761 while (scope != NULL) { | 730 while (scope != NULL) { |
762 scope->local_handles()->VisitObjectPointers(visitor); | 731 scope->local_handles()->VisitObjectPointers(visitor); |
763 scope = scope->previous(); | 732 scope = scope->previous(); |
764 } | 733 } |
765 persistent_handles().VisitObjectPointers(visitor); | 734 persistent_handles().VisitObjectPointers(visitor); |
766 if (visit_prologue_weak_handles) { | |
767 prologue_weak_persistent_handles().VisitObjectPointers(visitor); | |
768 } | |
769 } | 735 } |
770 | 736 |
771 void VisitWeakHandles(HandleVisitor* visitor, | 737 void VisitWeakHandles(HandleVisitor* visitor) { |
772 bool visit_prologue_weak_handles) { | |
773 weak_persistent_handles().VisitHandles(visitor); | 738 weak_persistent_handles().VisitHandles(visitor); |
774 if (visit_prologue_weak_handles) { | |
775 prologue_weak_persistent_handles().VisitHandles(visitor); | |
776 } | |
777 } | |
778 | |
779 void VisitPrologueWeakHandles(HandleVisitor* visitor) { | |
780 prologue_weak_persistent_handles().VisitHandles(visitor); | |
781 } | 739 } |
782 | 740 |
783 bool IsValidLocalHandle(Dart_Handle object) const { | 741 bool IsValidLocalHandle(Dart_Handle object) const { |
784 ApiLocalScope* scope = top_scope_; | 742 ApiLocalScope* scope = top_scope_; |
785 while (scope != NULL) { | 743 while (scope != NULL) { |
786 if (scope->local_handles()->IsValidHandle(object)) { | 744 if (scope->local_handles()->IsValidHandle(object)) { |
787 return true; | 745 return true; |
788 } | 746 } |
789 scope = scope->previous(); | 747 scope = scope->previous(); |
790 } | 748 } |
791 return false; | 749 return false; |
792 } | 750 } |
793 | 751 |
794 bool IsValidPersistentHandle(Dart_PersistentHandle object) const { | 752 bool IsValidPersistentHandle(Dart_PersistentHandle object) const { |
795 return persistent_handles_.IsValidHandle(object); | 753 return persistent_handles_.IsValidHandle(object); |
796 } | 754 } |
797 | 755 |
798 bool IsValidWeakPersistentHandle(Dart_WeakPersistentHandle object) const { | 756 bool IsValidWeakPersistentHandle(Dart_WeakPersistentHandle object) const { |
799 return weak_persistent_handles_.IsValidHandle(object); | 757 return weak_persistent_handles_.IsValidHandle(object); |
800 } | 758 } |
801 | 759 |
802 bool IsValidPrologueWeakPersistentHandle( | |
803 Dart_WeakPersistentHandle object) const { | |
804 return prologue_weak_persistent_handles_.IsValidHandle(object); | |
805 } | |
806 | |
807 bool IsProtectedHandle(PersistentHandle* object) const { | 760 bool IsProtectedHandle(PersistentHandle* object) const { |
808 if (object == NULL) return false; | 761 if (object == NULL) return false; |
809 return object == null_ || object == true_ || object == false_; | 762 return object == null_ || object == true_ || object == false_; |
810 } | 763 } |
811 | 764 |
812 int CountLocalHandles() const { | 765 int CountLocalHandles() const { |
813 int total = 0; | 766 int total = 0; |
814 ApiLocalScope* scope = top_scope_; | 767 ApiLocalScope* scope = top_scope_; |
815 while (scope != NULL) { | 768 while (scope != NULL) { |
816 total += scope->local_handles()->CountHandles(); | 769 total += scope->local_handles()->CountHandles(); |
(...skipping 21 matching lines...) Expand all Loading... |
838 "please release them using Dart_TypedDataReleaseData.")); | 791 "please release them using Dart_TypedDataReleaseData.")); |
839 acquired_error_ = persistent_handles().AllocateHandle(); | 792 acquired_error_ = persistent_handles().AllocateHandle(); |
840 acquired_error_->set_raw(ApiError::New(msg)); | 793 acquired_error_->set_raw(ApiError::New(msg)); |
841 } | 794 } |
842 | 795 |
843 PersistentHandle* AcquiredError() const { | 796 PersistentHandle* AcquiredError() const { |
844 ASSERT(acquired_error_ != NULL); | 797 ASSERT(acquired_error_ != NULL); |
845 return acquired_error_; | 798 return acquired_error_; |
846 } | 799 } |
847 | 800 |
848 WeakReferenceSetBuilder* NewWeakReferenceSetBuilder(); | |
849 | |
850 void DelayWeakReferenceSet(WeakReferenceSet* reference_set); | |
851 | |
852 WeakTable* acquired_table() { return &acquired_table_; } | 801 WeakTable* acquired_table() { return &acquired_table_; } |
853 | 802 |
854 private: | 803 private: |
855 PersistentHandles persistent_handles_; | 804 PersistentHandles persistent_handles_; |
856 FinalizablePersistentHandles weak_persistent_handles_; | 805 FinalizablePersistentHandles weak_persistent_handles_; |
857 FinalizablePersistentHandles prologue_weak_persistent_handles_; | |
858 ApiLocalScope* reusable_scope_; | 806 ApiLocalScope* reusable_scope_; |
859 ApiLocalScope* top_scope_; | 807 ApiLocalScope* top_scope_; |
860 WeakReferenceSet* delayed_weak_reference_sets_; | |
861 WeakTable acquired_table_; | 808 WeakTable acquired_table_; |
862 | 809 |
863 // Persistent handles to important objects. | 810 // Persistent handles to important objects. |
864 PersistentHandle* null_; | 811 PersistentHandle* null_; |
865 PersistentHandle* true_; | 812 PersistentHandle* true_; |
866 PersistentHandle* false_; | 813 PersistentHandle* false_; |
867 PersistentHandle* acquired_error_; | 814 PersistentHandle* acquired_error_; |
868 | 815 |
869 DISALLOW_COPY_AND_ASSIGN(ApiState); | 816 DISALLOW_COPY_AND_ASSIGN(ApiState); |
870 }; | 817 }; |
871 | 818 |
872 | 819 |
873 class WeakReferenceSet { | |
874 public: | |
875 explicit WeakReferenceSet(Zone* zone) | |
876 : next_(NULL), | |
877 keys_(1, zone), | |
878 values_(1, zone) { | |
879 } | |
880 ~WeakReferenceSet() {} | |
881 | |
882 WeakReferenceSet* next() const { return next_; } | |
883 | |
884 intptr_t num_keys() const { return keys_.length(); } | |
885 RawObject** get_key(intptr_t i) { | |
886 ASSERT(i >= 0); | |
887 ASSERT(i < num_keys()); | |
888 FinalizablePersistentHandle* ref = | |
889 FinalizablePersistentHandle::Cast(keys_[i]); | |
890 return ref->raw_addr(); | |
891 } | |
892 | |
893 intptr_t num_values() const { return values_.length(); } | |
894 RawObject** get_value(intptr_t i) { | |
895 ASSERT(i >= 0); | |
896 ASSERT(i < num_values()); | |
897 FinalizablePersistentHandle* ref = | |
898 FinalizablePersistentHandle::Cast(values_[i]); | |
899 return ref->raw_addr(); | |
900 } | |
901 | |
902 bool SingletonKeyEqualsValue() const { | |
903 ASSERT((num_keys() == 1) && (num_values() == 1)); | |
904 return (keys_[0] == values_[0]); | |
905 } | |
906 | |
907 void Append(Dart_WeakPersistentHandle key, Dart_WeakPersistentHandle value) { | |
908 keys_.Add(key); | |
909 values_.Add(value); | |
910 } | |
911 | |
912 void AppendKey(Dart_WeakPersistentHandle key) { | |
913 keys_.Add(key); | |
914 } | |
915 | |
916 void AppendValue(Dart_WeakPersistentHandle value) { | |
917 values_.Add(value); | |
918 } | |
919 | |
920 static WeakReferenceSet* Pop(WeakReferenceSet** queue) { | |
921 ASSERT(queue != NULL); | |
922 WeakReferenceSet* head = *queue; | |
923 if (head != NULL) { | |
924 *queue = head->next(); | |
925 head->next_ = NULL; | |
926 } | |
927 return head; | |
928 } | |
929 | |
930 static void Push(WeakReferenceSet* reference_set, WeakReferenceSet** queue) { | |
931 ASSERT(reference_set != NULL); | |
932 ASSERT(queue != NULL); | |
933 reference_set->next_ = *queue; | |
934 *queue = reference_set; | |
935 } | |
936 | |
937 void* operator new(uword size, Zone* zone) { | |
938 return reinterpret_cast<void*>(zone->AllocUnsafe(size)); | |
939 } | |
940 | |
941 // Disallow explicit deallocation of WeakReferenceSet. | |
942 void operator delete(void* pointer) { UNREACHABLE(); } | |
943 | |
944 private: | |
945 WeakReferenceSet* next_; | |
946 ApiGrowableArray<Dart_WeakPersistentHandle> keys_; | |
947 ApiGrowableArray<Dart_WeakPersistentHandle> values_; | |
948 | |
949 DISALLOW_COPY_AND_ASSIGN(WeakReferenceSet); | |
950 }; | |
951 | |
952 | |
953 class WeakReferenceSetBuilder { | |
954 public: | |
955 ApiState* api_state() const { | |
956 return api_state_; | |
957 } | |
958 | |
959 WeakReferenceSet* NewWeakReferenceSet() { | |
960 return new (zone_) WeakReferenceSet(zone_); | |
961 } | |
962 | |
963 private: | |
964 explicit WeakReferenceSetBuilder(ApiState* api_state) | |
965 : api_state_(api_state), | |
966 zone_(api_state->top_scope()->zone()) { | |
967 } | |
968 | |
969 ApiState* api_state_; | |
970 Zone* zone_; | |
971 | |
972 friend class ApiState; | |
973 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakReferenceSetBuilder); | |
974 }; | |
975 | |
976 | |
977 inline FinalizablePersistentHandle* FinalizablePersistentHandle::New( | 820 inline FinalizablePersistentHandle* FinalizablePersistentHandle::New( |
978 Isolate* isolate, | 821 Isolate* isolate, |
979 bool is_prologue, | |
980 const Object& object, | 822 const Object& object, |
981 void* peer, | 823 void* peer, |
982 Dart_WeakPersistentHandleFinalizer callback, | 824 Dart_WeakPersistentHandleFinalizer callback, |
983 intptr_t external_size) { | 825 intptr_t external_size) { |
984 ApiState* state = isolate->api_state(); | 826 ApiState* state = isolate->api_state(); |
985 ASSERT(state != NULL); | 827 ASSERT(state != NULL); |
986 FinalizablePersistentHandle* ref = is_prologue ? | 828 FinalizablePersistentHandle* ref = |
987 state->prologue_weak_persistent_handles().AllocateHandle() : | |
988 state->weak_persistent_handles().AllocateHandle(); | 829 state->weak_persistent_handles().AllocateHandle(); |
989 ref->SetPrologueWeakPersistent(is_prologue); | |
990 ref->set_raw(object); | 830 ref->set_raw(object); |
991 ref->set_peer(peer); | 831 ref->set_peer(peer); |
992 ref->set_callback(callback); | 832 ref->set_callback(callback); |
993 // This may trigger GC, so it must be called last. | 833 // This may trigger GC, so it must be called last. |
994 ref->SetExternalSize(external_size, isolate); | 834 ref->SetExternalSize(external_size, isolate); |
995 return ref; | 835 return ref; |
996 } | 836 } |
997 | 837 |
998 } // namespace dart | 838 } // namespace dart |
999 | 839 |
1000 #endif // VM_DART_API_STATE_H_ | 840 #endif // VM_DART_API_STATE_H_ |
OLD | NEW |