| 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 |