OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 | 658 |
659 // We never flush code for Api functions. | 659 // We never flush code for Api functions. |
660 Object* function_data = shared_info->function_data(); | 660 Object* function_data = shared_info->function_data(); |
661 if (function_data->IsHeapObject() && | 661 if (function_data->IsHeapObject() && |
662 (SafeMap(function_data)->instance_type() == | 662 (SafeMap(function_data)->instance_type() == |
663 FUNCTION_TEMPLATE_INFO_TYPE)) { | 663 FUNCTION_TEMPLATE_INFO_TYPE)) { |
664 return false; | 664 return false; |
665 } | 665 } |
666 | 666 |
667 // Only flush code for functions. | 667 // Only flush code for functions. |
668 if (shared_info->code()->kind() != Code::FUNCTION) return false; | 668 if (shared_info->code()->kind() != Code::FUNCTION) { |
| 669 return false; |
| 670 } |
669 | 671 |
670 // Function must be lazy compilable. | 672 // Function must be lazy compilable. |
671 if (!shared_info->allows_lazy_compilation()) return false; | 673 if (!shared_info->allows_lazy_compilation()) { |
| 674 return false; |
| 675 } |
672 | 676 |
673 // If this is a full script wrapped in a function we do no flush the code. | 677 // If this is a full script wrapped in a function we do no flush the code. |
674 if (shared_info->is_toplevel()) return false; | 678 if (shared_info->is_toplevel()) { |
| 679 return false; |
| 680 } |
675 | 681 |
676 // Age this shared function info. | 682 // Age this shared function info. |
677 if (shared_info->code_age() < kCodeAgeThreshold) { | 683 if (shared_info->code_age() < kCodeAgeThreshold) { |
678 shared_info->set_code_age(shared_info->code_age() + 1); | 684 shared_info->set_code_age(shared_info->code_age() + 1); |
679 return false; | 685 return false; |
680 } | 686 } |
681 | 687 |
682 return true; | 688 return true; |
683 } | 689 } |
684 | 690 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 // The function must have a valid context and not be a builtin. | 863 // The function must have a valid context and not be a builtin. |
858 bool flush_code_candidate = false; | 864 bool flush_code_candidate = false; |
859 if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) { | 865 if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) { |
860 flush_code_candidate = FlushCodeForFunction(heap, jsfunction); | 866 flush_code_candidate = FlushCodeForFunction(heap, jsfunction); |
861 } | 867 } |
862 | 868 |
863 if (!flush_code_candidate) { | 869 if (!flush_code_candidate) { |
864 collector->MarkObject(jsfunction->unchecked_shared()->unchecked_code()); | 870 collector->MarkObject(jsfunction->unchecked_shared()->unchecked_code()); |
865 | 871 |
866 if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) { | 872 if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) { |
867 // For optimized functions we should retain both non-optimized version | 873 collector->MarkInlinedFunctionsCode(jsfunction->unchecked_code()); |
868 // of it's code and non-optimized version of all inlined functions. | |
869 // This is required to support bailing out from inlined code. | |
870 DeoptimizationInputData* data = | |
871 reinterpret_cast<DeoptimizationInputData*>( | |
872 jsfunction->unchecked_code()->unchecked_deoptimization_data()); | |
873 | |
874 FixedArray* literals = data->UncheckedLiteralArray(); | |
875 | |
876 for (int i = 0, count = data->InlinedFunctionCount()->value(); | |
877 i < count; | |
878 i++) { | |
879 JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i)); | |
880 collector->MarkObject(inlined->unchecked_shared()->unchecked_code()); | |
881 } | |
882 } | 874 } |
883 } | 875 } |
884 | 876 |
885 VisitJSFunctionFields(map, | 877 VisitJSFunctionFields(map, |
886 reinterpret_cast<JSFunction*>(object), | 878 reinterpret_cast<JSFunction*>(object), |
887 flush_code_candidate); | 879 flush_code_candidate); |
888 } | 880 } |
889 | 881 |
890 | 882 |
891 static void VisitJSFunction(Map* map, HeapObject* object) { | 883 static void VisitJSFunction(Map* map, HeapObject* object) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 Heap* heap_; | 979 Heap* heap_; |
988 }; | 980 }; |
989 | 981 |
990 | 982 |
991 class CodeMarkingVisitor : public ThreadVisitor { | 983 class CodeMarkingVisitor : public ThreadVisitor { |
992 public: | 984 public: |
993 explicit CodeMarkingVisitor(MarkCompactCollector* collector) | 985 explicit CodeMarkingVisitor(MarkCompactCollector* collector) |
994 : collector_(collector) {} | 986 : collector_(collector) {} |
995 | 987 |
996 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 988 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
997 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 989 collector_->PrepareThreadForCodeFlushing(isolate, top); |
998 collector_->MarkObject(it.frame()->unchecked_code()); | |
999 } | |
1000 } | 990 } |
1001 | 991 |
1002 private: | 992 private: |
1003 MarkCompactCollector* collector_; | 993 MarkCompactCollector* collector_; |
1004 }; | 994 }; |
1005 | 995 |
1006 | 996 |
1007 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor { | 997 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor { |
1008 public: | 998 public: |
1009 explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector) | 999 explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector) |
(...skipping 10 matching lines...) Expand all Loading... |
1020 collector_->MarkObject(shared->unchecked_code()); | 1010 collector_->MarkObject(shared->unchecked_code()); |
1021 collector_->MarkObject(shared); | 1011 collector_->MarkObject(shared); |
1022 } | 1012 } |
1023 } | 1013 } |
1024 | 1014 |
1025 private: | 1015 private: |
1026 MarkCompactCollector* collector_; | 1016 MarkCompactCollector* collector_; |
1027 }; | 1017 }; |
1028 | 1018 |
1029 | 1019 |
| 1020 void MarkCompactCollector::MarkInlinedFunctionsCode(Code* code) { |
| 1021 // For optimized functions we should retain both non-optimized version |
| 1022 // of it's code and non-optimized version of all inlined functions. |
| 1023 // This is required to support bailing out from inlined code. |
| 1024 DeoptimizationInputData* data = |
| 1025 reinterpret_cast<DeoptimizationInputData*>( |
| 1026 code->unchecked_deoptimization_data()); |
| 1027 |
| 1028 FixedArray* literals = data->UncheckedLiteralArray(); |
| 1029 |
| 1030 for (int i = 0, count = data->InlinedFunctionCount()->value(); |
| 1031 i < count; |
| 1032 i++) { |
| 1033 JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i)); |
| 1034 MarkObject(inlined->unchecked_shared()->unchecked_code()); |
| 1035 } |
| 1036 } |
| 1037 |
| 1038 |
| 1039 void MarkCompactCollector::PrepareThreadForCodeFlushing(Isolate* isolate, |
| 1040 ThreadLocalTop* top) { |
| 1041 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
| 1042 // Note: for the frame that has a pending lazy deoptimization |
| 1043 // StackFrame::unchecked_code will return a non-optimized code object for |
| 1044 // the outermost function and StackFrame::LookupCode will return |
| 1045 // actual optimized code object. |
| 1046 StackFrame* frame = it.frame(); |
| 1047 Code* code = frame->unchecked_code(); |
| 1048 MarkObject(code); |
| 1049 if (frame->is_optimized()) { |
| 1050 MarkInlinedFunctionsCode(frame->LookupCode()); |
| 1051 } |
| 1052 } |
| 1053 } |
| 1054 |
| 1055 |
1030 void MarkCompactCollector::PrepareForCodeFlushing() { | 1056 void MarkCompactCollector::PrepareForCodeFlushing() { |
1031 ASSERT(heap() == Isolate::Current()->heap()); | 1057 ASSERT(heap() == Isolate::Current()->heap()); |
1032 | 1058 |
1033 if (!FLAG_flush_code) { | 1059 if (!FLAG_flush_code) { |
1034 EnableCodeFlushing(false); | 1060 EnableCodeFlushing(false); |
1035 return; | 1061 return; |
1036 } | 1062 } |
1037 | 1063 |
1038 #ifdef ENABLE_DEBUGGER_SUPPORT | 1064 #ifdef ENABLE_DEBUGGER_SUPPORT |
1039 if (heap()->isolate()->debug()->IsLoaded() || | 1065 if (heap()->isolate()->debug()->IsLoaded() || |
1040 heap()->isolate()->debug()->has_break_points()) { | 1066 heap()->isolate()->debug()->has_break_points()) { |
1041 EnableCodeFlushing(false); | 1067 EnableCodeFlushing(false); |
1042 return; | 1068 return; |
1043 } | 1069 } |
1044 #endif | 1070 #endif |
1045 EnableCodeFlushing(true); | 1071 EnableCodeFlushing(true); |
1046 | 1072 |
1047 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray | 1073 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray |
1048 // relies on it being marked before any other descriptor array. | 1074 // relies on it being marked before any other descriptor array. |
1049 MarkObject(heap()->raw_unchecked_empty_descriptor_array()); | 1075 MarkObject(heap()->raw_unchecked_empty_descriptor_array()); |
1050 | 1076 |
1051 // Make sure we are not referencing the code from the stack. | 1077 // Make sure we are not referencing the code from the stack. |
1052 ASSERT(this == heap()->mark_compact_collector()); | 1078 ASSERT(this == heap()->mark_compact_collector()); |
1053 for (StackFrameIterator it; !it.done(); it.Advance()) { | 1079 PrepareThreadForCodeFlushing(heap()->isolate(), |
1054 MarkObject(it.frame()->unchecked_code()); | 1080 heap()->isolate()->thread_local_top()); |
1055 } | |
1056 | 1081 |
1057 // Iterate the archived stacks in all threads to check if | 1082 // Iterate the archived stacks in all threads to check if |
1058 // the code is referenced. | 1083 // the code is referenced. |
1059 CodeMarkingVisitor code_marking_visitor(this); | 1084 CodeMarkingVisitor code_marking_visitor(this); |
1060 heap()->isolate()->thread_manager()->IterateArchivedThreads( | 1085 heap()->isolate()->thread_manager()->IterateArchivedThreads( |
1061 &code_marking_visitor); | 1086 &code_marking_visitor); |
1062 | 1087 |
1063 SharedFunctionInfoMarkingVisitor visitor(this); | 1088 SharedFunctionInfoMarkingVisitor visitor(this); |
1064 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); | 1089 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); |
1065 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); | 1090 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); |
(...skipping 2288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3354 } | 3379 } |
3355 | 3380 |
3356 | 3381 |
3357 void MarkCompactCollector::Initialize() { | 3382 void MarkCompactCollector::Initialize() { |
3358 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 3383 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
3359 StaticMarkingVisitor::Initialize(); | 3384 StaticMarkingVisitor::Initialize(); |
3360 } | 3385 } |
3361 | 3386 |
3362 | 3387 |
3363 } } // namespace v8::internal | 3388 } } // namespace v8::internal |
OLD | NEW |