Chromium Code Reviews| Index: runtime/vm/pages.cc |
| =================================================================== |
| --- runtime/vm/pages.cc (revision 28803) |
| +++ runtime/vm/pages.cc (working copy) |
| @@ -23,6 +23,12 @@ |
| "Print free list statistics before a GC"); |
| DEFINE_FLAG(bool, print_free_list_after_gc, false, |
| "Print free list statistics after a GC"); |
| +DEFINE_FLAG(bool, collect_code, true, |
| + "Attempt to GC infrequently used code."); |
| +DEFINE_FLAG(int, code_collection_interval, 30000000, |
| + "Time between attempts to collect unused code."); |
| +DEFINE_FLAG(bool, log_code_drop, false, |
| + "Emit a log message when pointers to unused code are dropped."); |
| HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) { |
| ASSERT(memory->size() > VirtualMemory::PageSize()); |
| @@ -378,11 +384,66 @@ |
| } |
| + |
| +class CodeDropperVisitor : public ObjectVisitor { |
| + public: |
| + explicit CodeDropperVisitor(Isolate* isolate) : ObjectVisitor(isolate) { } |
| + |
| + virtual void VisitObject(RawObject* obj); |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(CodeDropperVisitor); |
| +}; |
| + |
| + |
| +void CodeDropperVisitor::VisitObject(RawObject* raw_obj) { |
|
hausner
2013/10/18 17:46:17
You should also check whether there are breakpoint
zra
2013/10/22 16:13:24
Added !fn.HasBreakpoint() to the conditions for de
|
| + Isolate* isolate = Isolate::Current(); |
| + HANDLESCOPE(isolate); |
| + const Object& obj = Object::Handle(raw_obj); |
| + if (obj.GetClassId() == kFunctionCid) { |
| + const Function& fn = Function::Cast(obj); |
| + if ((fn.CurrentCode() == fn.unoptimized_code()) && |
| + (fn.usage_counter() > 0)) { |
|
srdjan
2013/10/18 18:04:32
Use !fn.HasOptimizedCode()
zra
2013/10/22 16:13:24
Done.
|
| + fn.set_usage_counter(fn.usage_counter() / 2); |
| + if (fn.usage_counter() == 0) { |
| + if (FLAG_log_code_drop) { |
| + const String& name = String::Handle(fn.name()); |
| + OS::Print("Dropping code for function %s\n", name.ToCString()); |
| + } |
| + fn.DetachCode(); |
| + fn.set_unoptimized_code(Code::Handle()); |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| +void PageSpace::TryDroppingCode() { |
| + // Try to collect code if enough time has passed since the last attempt. |
| + const int64_t start = OS::GetCurrentTimeMicros(); |
| + const int64_t last_code_collection = |
| + page_space_controller_.last_code_collection(); |
| + if ((start - last_code_collection) > FLAG_code_collection_interval) { |
| + if (FLAG_log_code_drop) { |
| + OS::Print("Trying to drop code.\n"); |
| + } |
| + Isolate* isolate = Isolate::Current(); |
| + CodeDropperVisitor code_dropper(isolate); |
| + heap_->IterateObjects(&code_dropper); |
| + page_space_controller_.set_last_code_collection(start); |
| + } |
| +} |
| + |
| + |
| void PageSpace::MarkSweep(bool invoke_api_callbacks) { |
| // MarkSweep is not reentrant. Make sure that is the case. |
| ASSERT(!sweeping_); |
| sweeping_ = true; |
| Isolate* isolate = Isolate::Current(); |
| + if (FLAG_collect_code) { |
| + TryDroppingCode(); |
| + } |
| + |
| NoHandleScope no_handles(isolate); |
| if (FLAG_print_free_list_before_gc) { |
| @@ -398,7 +459,7 @@ |
| OS::PrintErr(" done.\n"); |
| } |
| - int64_t start = OS::GetCurrentTimeMicros(); |
| + const int64_t start = OS::GetCurrentTimeMicros(); |
| // Mark all reachable old-gen objects. |
| GCMarker marker(heap_); |
| @@ -490,7 +551,8 @@ |
| heap_growth_ratio_(heap_growth_ratio), |
| desired_utilization_((100.0 - heap_growth_ratio) / 100.0), |
| heap_growth_rate_(heap_growth_rate), |
| - garbage_collection_time_ratio_(garbage_collection_time_ratio) { |
| + garbage_collection_time_ratio_(garbage_collection_time_ratio), |
| + last_code_collection_(OS::GetCurrentTimeMicros()) { |
| } |