| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
| 6 | 6 |
| 7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 // the marking stack. Instead, we mark them as both marked and overflowed. | 897 // the marking stack. Instead, we mark them as both marked and overflowed. |
| 898 // When the stack is in the overflowed state, objects marked as overflowed | 898 // When the stack is in the overflowed state, objects marked as overflowed |
| 899 // have been reached and marked but their children have not been visited yet. | 899 // have been reached and marked but their children have not been visited yet. |
| 900 // After emptying the marking stack, we clear the overflow flag and traverse | 900 // After emptying the marking stack, we clear the overflow flag and traverse |
| 901 // the heap looking for objects marked as overflowed, push them on the stack, | 901 // the heap looking for objects marked as overflowed, push them on the stack, |
| 902 // and continue with marking. This process repeats until all reachable | 902 // and continue with marking. This process repeats until all reachable |
| 903 // objects have been marked. | 903 // objects have been marked. |
| 904 | 904 |
| 905 void CodeFlusher::ProcessJSFunctionCandidates() { | 905 void CodeFlusher::ProcessJSFunctionCandidates() { |
| 906 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); | 906 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); |
| 907 Code* interpreter_entry_trampoline = |
| 908 isolate_->builtins()->builtin(Builtins::kInterpreterEntryTrampoline); |
| 907 Object* undefined = isolate_->heap()->undefined_value(); | 909 Object* undefined = isolate_->heap()->undefined_value(); |
| 908 | 910 |
| 909 JSFunction* candidate = jsfunction_candidates_head_; | 911 JSFunction* candidate = jsfunction_candidates_head_; |
| 910 JSFunction* next_candidate; | 912 JSFunction* next_candidate; |
| 911 while (candidate != NULL) { | 913 while (candidate != NULL) { |
| 912 next_candidate = GetNextCandidate(candidate); | 914 next_candidate = GetNextCandidate(candidate); |
| 913 ClearNextCandidate(candidate, undefined); | 915 ClearNextCandidate(candidate, undefined); |
| 914 | 916 |
| 915 SharedFunctionInfo* shared = candidate->shared(); | 917 SharedFunctionInfo* shared = candidate->shared(); |
| 916 | 918 |
| 917 Code* code = shared->code(); | 919 Code* code = shared->code(); |
| 918 MarkBit code_mark = ObjectMarking::MarkBitFrom(code); | 920 MarkBit code_mark = ObjectMarking::MarkBitFrom(code); |
| 919 if (Marking::IsWhite(code_mark)) { | 921 if (Marking::IsWhite(code_mark)) { |
| 920 if (FLAG_trace_code_flushing && shared->is_compiled()) { | 922 if (FLAG_trace_code_flushing && shared->is_compiled()) { |
| 921 PrintF("[code-flushing clears: "); | 923 PrintF("[code-flushing clears: "); |
| 922 shared->ShortPrint(); | 924 shared->ShortPrint(); |
| 923 PrintF(" - age: %d]\n", code->GetAge()); | 925 PrintF(" - age: %d]\n", code->GetAge()); |
| 924 } | 926 } |
| 925 // Always flush the optimized code map if there is one. | 927 // Always flush the optimized code map if there is one. |
| 926 if (!shared->OptimizedCodeMapIsCleared()) { | 928 if (!shared->OptimizedCodeMapIsCleared()) { |
| 927 shared->ClearOptimizedCodeMap(); | 929 shared->ClearOptimizedCodeMap(); |
| 928 } | 930 } |
| 929 shared->set_code(lazy_compile); | 931 if (shared->HasBytecodeArray()) { |
| 930 candidate->set_code(lazy_compile); | 932 shared->set_code(interpreter_entry_trampoline); |
| 933 candidate->set_code(interpreter_entry_trampoline); |
| 934 } else { |
| 935 shared->set_code(lazy_compile); |
| 936 candidate->set_code(lazy_compile); |
| 937 } |
| 931 } else { | 938 } else { |
| 932 DCHECK(Marking::IsBlack(code_mark)); | 939 DCHECK(Marking::IsBlack(code_mark)); |
| 933 candidate->set_code(code); | 940 candidate->set_code(code); |
| 934 } | 941 } |
| 935 | 942 |
| 936 // We are in the middle of a GC cycle so the write barrier in the code | 943 // We are in the middle of a GC cycle so the write barrier in the code |
| 937 // setter did not record the slot update and we have to do that manually. | 944 // setter did not record the slot update and we have to do that manually. |
| 938 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; | 945 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; |
| 939 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); | 946 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); |
| 940 isolate_->heap()->mark_compact_collector()->RecordCodeEntrySlot( | 947 isolate_->heap()->mark_compact_collector()->RecordCodeEntrySlot( |
| 941 candidate, slot, target); | 948 candidate, slot, target); |
| 942 | 949 |
| 943 Object** shared_code_slot = | 950 Object** shared_code_slot = |
| 944 HeapObject::RawField(shared, SharedFunctionInfo::kCodeOffset); | 951 HeapObject::RawField(shared, SharedFunctionInfo::kCodeOffset); |
| 945 isolate_->heap()->mark_compact_collector()->RecordSlot( | 952 isolate_->heap()->mark_compact_collector()->RecordSlot( |
| 946 shared, shared_code_slot, *shared_code_slot); | 953 shared, shared_code_slot, *shared_code_slot); |
| 947 | 954 |
| 948 candidate = next_candidate; | 955 candidate = next_candidate; |
| 949 } | 956 } |
| 950 | 957 |
| 951 jsfunction_candidates_head_ = NULL; | 958 jsfunction_candidates_head_ = NULL; |
| 952 } | 959 } |
| 953 | 960 |
| 954 | 961 |
| 955 void CodeFlusher::ProcessSharedFunctionInfoCandidates() { | 962 void CodeFlusher::ProcessSharedFunctionInfoCandidates() { |
| 956 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); | 963 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); |
| 957 | 964 Code* interpreter_entry_trampoline = |
| 965 isolate_->builtins()->builtin(Builtins::kInterpreterEntryTrampoline); |
| 958 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; | 966 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; |
| 959 SharedFunctionInfo* next_candidate; | 967 SharedFunctionInfo* next_candidate; |
| 960 while (candidate != NULL) { | 968 while (candidate != NULL) { |
| 961 next_candidate = GetNextCandidate(candidate); | 969 next_candidate = GetNextCandidate(candidate); |
| 962 ClearNextCandidate(candidate); | 970 ClearNextCandidate(candidate); |
| 963 | 971 |
| 964 Code* code = candidate->code(); | 972 Code* code = candidate->code(); |
| 965 MarkBit code_mark = ObjectMarking::MarkBitFrom(code); | 973 MarkBit code_mark = ObjectMarking::MarkBitFrom(code); |
| 966 if (Marking::IsWhite(code_mark)) { | 974 if (Marking::IsWhite(code_mark)) { |
| 967 if (FLAG_trace_code_flushing && candidate->is_compiled()) { | 975 if (FLAG_trace_code_flushing && candidate->is_compiled()) { |
| 968 PrintF("[code-flushing clears: "); | 976 PrintF("[code-flushing clears: "); |
| 969 candidate->ShortPrint(); | 977 candidate->ShortPrint(); |
| 970 PrintF(" - age: %d]\n", code->GetAge()); | 978 PrintF(" - age: %d]\n", code->GetAge()); |
| 971 } | 979 } |
| 972 // Always flush the optimized code map if there is one. | 980 // Always flush the optimized code map if there is one. |
| 973 if (!candidate->OptimizedCodeMapIsCleared()) { | 981 if (!candidate->OptimizedCodeMapIsCleared()) { |
| 974 candidate->ClearOptimizedCodeMap(); | 982 candidate->ClearOptimizedCodeMap(); |
| 975 } | 983 } |
| 976 candidate->set_code(lazy_compile); | 984 if (candidate->HasBytecodeArray()) { |
| 985 candidate->set_code(interpreter_entry_trampoline); |
| 986 } else { |
| 987 candidate->set_code(lazy_compile); |
| 988 } |
| 977 } | 989 } |
| 978 | 990 |
| 979 Object** code_slot = | 991 Object** code_slot = |
| 980 HeapObject::RawField(candidate, SharedFunctionInfo::kCodeOffset); | 992 HeapObject::RawField(candidate, SharedFunctionInfo::kCodeOffset); |
| 981 isolate_->heap()->mark_compact_collector()->RecordSlot(candidate, code_slot, | 993 isolate_->heap()->mark_compact_collector()->RecordSlot(candidate, code_slot, |
| 982 *code_slot); | 994 *code_slot); |
| 983 | 995 |
| 984 candidate = next_candidate; | 996 candidate = next_candidate; |
| 985 } | 997 } |
| 986 | 998 |
| (...skipping 3081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4068 // The target is always in old space, we don't have to record the slot in | 4080 // The target is always in old space, we don't have to record the slot in |
| 4069 // the old-to-new remembered set. | 4081 // the old-to-new remembered set. |
| 4070 DCHECK(!heap()->InNewSpace(target)); | 4082 DCHECK(!heap()->InNewSpace(target)); |
| 4071 RecordRelocSlot(host, &rinfo, target); | 4083 RecordRelocSlot(host, &rinfo, target); |
| 4072 } | 4084 } |
| 4073 } | 4085 } |
| 4074 } | 4086 } |
| 4075 | 4087 |
| 4076 } // namespace internal | 4088 } // namespace internal |
| 4077 } // namespace v8 | 4089 } // namespace v8 |
| OLD | NEW |