| Index: src/mark-compact.cc
|
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc
|
| index adbc5e7e549997172f467458d6f1623a2b23f070..522eaff738595540e2ae8c889b1589f846b78f4e 100644
|
| --- a/src/mark-compact.cc
|
| +++ b/src/mark-compact.cc
|
| @@ -83,6 +83,16 @@ 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());
|
| + }
|
| + }
|
| };
|
|
|
|
|
| @@ -824,6 +834,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
|
| @@ -835,6 +852,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);
|
| }
|
|
|
|
|
| @@ -2140,9 +2160,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()) {
|
| @@ -2154,6 +2172,12 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
|
|
|
| ClearNonLivePrototypeTransitions(map);
|
| ClearNonLiveMapTransitions(map, map_mark);
|
| +
|
| + if (map_mark.Get()) {
|
| + ClearNonLiveDependentCodes(map);
|
| + } else {
|
| + DeoptimizeLiveDependentCodes(map);
|
| + }
|
| }
|
| }
|
|
|
| @@ -2222,6 +2246,46 @@ void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map,
|
| }
|
|
|
|
|
| +void MarkCompactCollector::DeoptimizeLiveDependentCodes(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)) {
|
|
|