Index: src/mark-compact.cc |
diff --git a/src/mark-compact.cc b/src/mark-compact.cc |
index 9606092713a0e311ebe9e13b23eb04394d87c95a..8b0f7422ceb59ee0b50efdb7170119ef342b35b8 100644 |
--- a/src/mark-compact.cc |
+++ b/src/mark-compact.cc |
@@ -82,6 +82,15 @@ class VerifyMarkingVisitor: public ObjectVisitor { |
} |
} |
} |
+ |
+ void VisitEmbeddedPointer(RelocInfo* rinfo) { |
+ ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
+ if (rinfo->host()->kind() != Code::OPTIMIZED_FUNCTION || |
+ !rinfo->target_object()->IsMap() || |
+ !Map::cast(rinfo->target_object())->CanTransition()) { |
+ VisitPointer(rinfo->target_object_address()); |
+ } |
+ } |
}; |
@@ -382,7 +391,7 @@ void MarkCompactCollector::CollectGarbage() { |
MarkLiveObjects(); |
ASSERT(heap_->incremental_marking()->IsStopped()); |
- if (FLAG_collect_maps) ClearNonLiveTransitions(); |
+ if (FLAG_collect_maps) ClearNonLiveReferences(); |
ClearWeakMaps(); |
@@ -823,6 +832,13 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) { |
#endif |
} |
+class DeoptimizeMarkedCodeFilter : public OptimizedFunctionFilter { |
+ public: |
+ virtual bool TakeFunction(JSFunction* function) { |
+ return function->code()->marked_for_deoptimization(); |
+ } |
+}; |
+ |
void MarkCompactCollector::Finish() { |
#ifdef DEBUG |
@@ -834,6 +850,9 @@ void MarkCompactCollector::Finish() { |
// GC, because it relies on the new address of certain old space |
// objects (empty string, illegal builtin). |
heap()->isolate()->stub_cache()->Clear(); |
+ |
+ DeoptimizeMarkedCodeFilter filter; |
+ Deoptimizer::DeoptimizeAllFunctionsWith(&filter); |
} |
@@ -2166,7 +2185,7 @@ void MarkCompactCollector::ReattachInitialMaps() { |
} |
-void MarkCompactCollector::ClearNonLiveTransitions() { |
+void MarkCompactCollector::ClearNonLiveReferences() { |
HeapObjectIterator map_iterator(heap()->map_space()); |
// Iterate over the map space, setting map transitions that go from |
// a marked map to an unmarked map to null transitions. This action |
@@ -2178,9 +2197,7 @@ void MarkCompactCollector::ClearNonLiveTransitions() { |
if (map->IsFreeSpace()) continue; |
ASSERT(map->IsMap()); |
- // Only JSObject and subtypes have map transitions and back pointers. |
- STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE); |
- if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; |
+ if (!map->CanTransition()) continue; |
if (map_mark.Get() && |
map->attached_to_shared_function_info()) { |
@@ -2192,6 +2209,12 @@ void MarkCompactCollector::ClearNonLiveTransitions() { |
ClearNonLivePrototypeTransitions(map); |
ClearNonLiveMapTransitions(map, map_mark); |
+ |
+ if (map_mark.Get()) { |
+ ClearNonLiveDependentCodes(map); |
+ } else { |
+ ClearAndDeoptimizeDependentCodes(map); |
+ } |
} |
} |
@@ -2260,6 +2283,46 @@ void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, |
} |
+void MarkCompactCollector::ClearAndDeoptimizeDependentCodes(Map* map) { |
+ AssertNoAllocation no_allocation_scope; |
+ DependentCodes* codes = map->dependent_codes(); |
+ int number_of_codes = codes->number_of_codes(); |
+ if (number_of_codes == 0) return; |
+ for (int i = 0; i < number_of_codes; i++) { |
+ Code* code = codes->code_at(i); |
+ if (IsMarked(code) && !code->marked_for_deoptimization()) { |
+ code->set_marked_for_deoptimization(true); |
+ } |
+ codes->clear_code_at(i); |
+ } |
+ map->set_dependent_codes(DependentCodes::cast(heap()->empty_fixed_array())); |
+} |
+ |
+ |
+void MarkCompactCollector::ClearNonLiveDependentCodes(Map* map) { |
+ AssertNoAllocation no_allocation_scope; |
+ DependentCodes* codes = map->dependent_codes(); |
+ int number_of_codes = codes->number_of_codes(); |
+ if (number_of_codes == 0) return; |
+ int new_number_of_codes = 0; |
+ for (int i = 0; i < number_of_codes; i++) { |
+ Code* code = codes->code_at(i); |
+ if (IsMarked(code) && !code->marked_for_deoptimization()) { |
+ if (new_number_of_codes != i) { |
+ codes->set_code_at(new_number_of_codes, code); |
+ Object** slot = codes->code_slot_at(new_number_of_codes); |
+ RecordSlot(slot, slot, code); |
+ new_number_of_codes++; |
+ } |
+ } |
+ } |
+ for (int i = new_number_of_codes; i < number_of_codes; i++) { |
+ codes->clear_code_at(i); |
+ } |
+ codes->set_number_of_codes(new_number_of_codes); |
+} |
+ |
+ |
void MarkCompactCollector::ProcessWeakMaps() { |
Object* weak_map_obj = encountered_weak_maps(); |
while (weak_map_obj != Smi::FromInt(0)) { |