| Index: runtime/vm/gc_marker.cc
|
| diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
|
| index b8da4fe42382385090068c855475b65a9e2ddba2..4ad7e8f1ddc586ac1859384b955fbc710a37f005 100644
|
| --- a/runtime/vm/gc_marker.cc
|
| +++ b/runtime/vm/gc_marker.cc
|
| @@ -74,6 +74,70 @@ class DelaySet {
|
| };
|
|
|
|
|
| +class SkippedCodeFunctions : public ZoneAllocated {
|
| + public:
|
| + SkippedCodeFunctions() {}
|
| +
|
| + void Add(RawFunction* func) {
|
| + skipped_code_functions_.Add(func);
|
| + }
|
| +
|
| + void DetachCode() {
|
| + intptr_t unoptimized_code_count = 0;
|
| + intptr_t current_code_count = 0;
|
| + for (int i = 0; i < skipped_code_functions_.length(); i++) {
|
| + RawFunction* func = skipped_code_functions_[i];
|
| + RawCode* code = func->ptr()->instructions_->ptr()->code_;
|
| + if (!code->IsMarked()) {
|
| + // If the code wasn't strongly visited through other references
|
| + // after skipping the function's code pointer, then we disconnect the
|
| + // code from the function.
|
| + func->StorePointer(
|
| + &(func->ptr()->instructions_),
|
| + StubCode::LazyCompile_entry()->code()->ptr()->instructions_);
|
| + uword entry_point = StubCode::LazyCompile_entry()->EntryPoint();
|
| + func->ptr()->entry_point_ = entry_point;
|
| + if (FLAG_log_code_drop) {
|
| + // NOTE: This code runs while GC is in progress and runs within
|
| + // a NoHandleScope block. Hence it is not okay to use a regular Zone
|
| + // or Scope handle. We use a direct stack handle so the raw pointer in
|
| + // this handle is not traversed. The use of a handle is mainly to
|
| + // be able to reuse the handle based code and avoid having to add
|
| + // helper functions to the raw object interface.
|
| + String name;
|
| + name = func->ptr()->name_;
|
| + ISL_Print("Detaching code: %s\n", name.ToCString());
|
| + current_code_count++;
|
| + }
|
| + }
|
| +
|
| + code = func->ptr()->unoptimized_code_;
|
| + if (!code->IsMarked()) {
|
| + // If the code wasn't strongly visited through other references
|
| + // after skipping the function's code pointer, then we disconnect the
|
| + // code from the function.
|
| + func->StorePointer(&(func->ptr()->unoptimized_code_), Code::null());
|
| + if (FLAG_log_code_drop) {
|
| + unoptimized_code_count++;
|
| + }
|
| + }
|
| + }
|
| + if (FLAG_log_code_drop) {
|
| + ISL_Print(" total detached current: %" Pd "\n", current_code_count);
|
| + ISL_Print(" total detached unoptimized: %" Pd "\n",
|
| + unoptimized_code_count);
|
| + }
|
| + // Clean up.
|
| + skipped_code_functions_.Clear();
|
| + }
|
| +
|
| + private:
|
| + GrowableArray<RawFunction*> skipped_code_functions_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SkippedCodeFunctions);
|
| +};
|
| +
|
| +
|
| class MarkingVisitor : public ObjectPointerVisitor {
|
| public:
|
| MarkingVisitor(Isolate* isolate,
|
| @@ -81,7 +145,7 @@ class MarkingVisitor : public ObjectPointerVisitor {
|
| PageSpace* page_space,
|
| MarkingStack* marking_stack,
|
| DelaySet* delay_set,
|
| - bool visit_function_code)
|
| + SkippedCodeFunctions* skipped_code_functions)
|
| : ObjectPointerVisitor(isolate),
|
| thread_(Thread::Current()),
|
| heap_(heap),
|
| @@ -91,7 +155,7 @@ class MarkingVisitor : public ObjectPointerVisitor {
|
| work_list_(marking_stack),
|
| delay_set_(delay_set),
|
| visiting_old_object_(NULL),
|
| - visit_function_code_(visit_function_code),
|
| + skipped_code_functions_(skipped_code_functions),
|
| marked_bytes_(0) {
|
| ASSERT(heap_ != vm_heap_);
|
| ASSERT(thread_->isolate() == isolate);
|
| @@ -131,10 +195,13 @@ class MarkingVisitor : public ObjectPointerVisitor {
|
| }
|
| }
|
|
|
| - bool visit_function_code() const { return visit_function_code_; }
|
| + bool visit_function_code() const {
|
| + return skipped_code_functions_ == NULL;
|
| + }
|
|
|
| - virtual MallocGrowableArray<RawFunction*>* skipped_code_functions() {
|
| - return &skipped_code_functions_;
|
| + virtual void add_skipped_code_function(RawFunction* func) {
|
| + ASSERT(!visit_function_code());
|
| + skipped_code_functions_->Add(func);
|
| }
|
|
|
| // Returns the mark bit. Sets the watch bit if unmarked. (The prior value of
|
| @@ -171,10 +238,10 @@ class MarkingVisitor : public ObjectPointerVisitor {
|
|
|
| // Called when all marking is complete.
|
| void Finalize() {
|
| - if (!visit_function_code_) {
|
| - DetachCode();
|
| - }
|
| work_list_.Finalize();
|
| + if (skipped_code_functions_ != NULL) {
|
| + skipped_code_functions_->DetachCode();
|
| + }
|
| }
|
|
|
| void VisitingOldObject(RawObject* obj) {
|
| @@ -283,56 +350,6 @@ class MarkingVisitor : public ObjectPointerVisitor {
|
| MarkAndPush(raw_obj);
|
| }
|
|
|
| - void DetachCode() {
|
| - intptr_t unoptimized_code_count = 0;
|
| - intptr_t current_code_count = 0;
|
| - for (int i = 0; i < skipped_code_functions_.length(); i++) {
|
| - RawFunction* func = skipped_code_functions_[i];
|
| - RawCode* code = func->ptr()->instructions_->ptr()->code_;
|
| - if (!code->IsMarked()) {
|
| - // If the code wasn't strongly visited through other references
|
| - // after skipping the function's code pointer, then we disconnect the
|
| - // code from the function.
|
| - func->StorePointer(
|
| - &(func->ptr()->instructions_),
|
| - StubCode::LazyCompile_entry()->code()->ptr()->instructions_);
|
| - uword entry_point = StubCode::LazyCompile_entry()->EntryPoint();
|
| - func->ptr()->entry_point_ = entry_point;
|
| -
|
| - if (FLAG_log_code_drop) {
|
| - // NOTE: This code runs while GC is in progress and runs within
|
| - // a NoHandleScope block. Hence it is not okay to use a regular Zone
|
| - // or Scope handle. We use a direct stack handle so the raw pointer in
|
| - // this handle is not traversed. The use of a handle is mainly to
|
| - // be able to reuse the handle based code and avoid having to add
|
| - // helper functions to the raw object interface.
|
| - String name;
|
| - name = func->ptr()->name_;
|
| - ISL_Print("Detaching code: %s\n", name.ToCString());
|
| - current_code_count++;
|
| - }
|
| - }
|
| -
|
| - code = func->ptr()->unoptimized_code_;
|
| - if (!code->IsMarked()) {
|
| - // If the code wasn't strongly visited through other references
|
| - // after skipping the function's code pointer, then we disconnect the
|
| - // code from the function.
|
| - func->StorePointer(&(func->ptr()->unoptimized_code_), Code::null());
|
| - if (FLAG_log_code_drop) {
|
| - unoptimized_code_count++;
|
| - }
|
| - }
|
| - }
|
| - if (FLAG_log_code_drop) {
|
| - ISL_Print(" total detached current: %" Pd "\n", current_code_count);
|
| - ISL_Print(" total detached unoptimized: %" Pd "\n",
|
| - unoptimized_code_count);
|
| - }
|
| - // Clean up.
|
| - skipped_code_functions_.Clear();
|
| - }
|
| -
|
| Thread* thread_;
|
| Heap* heap_;
|
| Heap* vm_heap_;
|
| @@ -341,8 +358,7 @@ class MarkingVisitor : public ObjectPointerVisitor {
|
| WorkList work_list_;
|
| DelaySet* delay_set_;
|
| RawObject* visiting_old_object_;
|
| - const bool visit_function_code_;
|
| - MallocGrowableArray<RawFunction*> skipped_code_functions_;
|
| + SkippedCodeFunctions* skipped_code_functions_;
|
| uintptr_t marked_bytes_;
|
|
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor);
|
| @@ -529,22 +545,24 @@ void GCMarker::MarkObjects(Isolate* isolate,
|
| PageSpace* page_space,
|
| bool invoke_api_callbacks,
|
| bool collect_code) {
|
| - const bool visit_function_code = !collect_code;
|
| Prologue(isolate, invoke_api_callbacks);
|
| // The API prologue/epilogue may create/destroy zones, so we must not
|
| // depend on zone allocations surviving beyond the epilogue callback.
|
| {
|
| - StackZone zone(Thread::Current());
|
| + StackZone stack_zone(Thread::Current());
|
| + Zone* zone = stack_zone.GetZone();
|
| MarkingStack marking_stack;
|
| DelaySet delay_set;
|
| + SkippedCodeFunctions* skipped_code_functions =
|
| + collect_code ? new(zone) SkippedCodeFunctions() : NULL;
|
| MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
|
| - &delay_set, visit_function_code);
|
| + &delay_set, skipped_code_functions);
|
| IterateRoots(isolate, &mark, !invoke_api_callbacks);
|
| mark.DrainMarkingStack();
|
| IterateWeakReferences(isolate, &mark);
|
| MarkingWeakVisitor mark_weak;
|
| IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
|
| - // TODO(koda): Add hand-over callback and centralize skipped code functions.
|
| + // TODO(koda): Add hand-over callback.
|
| marked_bytes_ = mark.marked_bytes();
|
| mark.Finalize();
|
| delay_set.ClearReferences();
|
|
|