diff --git a/src/compiler.cc b/src/compiler.cc index 6e8ce12959..4e3ccad798 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -544,6 +544,61 @@ OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { } +namespace { + +void AddWeakObjectToCodeDependency(Isolate* isolate, Handle object, + Handle code) { + Handle cell = Code::WeakCellFor(code); + Heap* heap = isolate->heap(); + Handle dep(heap->LookupWeakObjectToCodeDependency(object)); + dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); + heap->AddWeakObjectToCodeDependency(object, dep); +} + + +void RegisterWeakObjectsInOptimizedCode(Handle code) { + // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. + Isolate* const isolate = code->GetIsolate(); + DCHECK(code->is_optimized_code()); + std::vector> maps; + std::vector> objects; + { + DisallowHeapAllocation no_gc; + int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | + RelocInfo::ModeMask(RelocInfo::CELL); + for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { + RelocInfo::Mode mode = it.rinfo()->rmode(); + if (mode == RelocInfo::CELL && + code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) { + objects.push_back(handle(it.rinfo()->target_cell(), isolate)); + } else if (mode == RelocInfo::EMBEDDED_OBJECT && + code->IsWeakObjectInOptimizedCode( + it.rinfo()->target_object())) { + Handle object(HeapObject::cast(it.rinfo()->target_object()), + isolate); + if (object->IsMap()) { + maps.push_back(Handle::cast(object)); + } else { + objects.push_back(object); + } + } + } + } + for (Handle map : maps) { + if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) { + isolate->heap()->AddRetainedMap(map); + } + Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); + } + for (Handle object : objects) { + AddWeakObjectToCodeDependency(isolate, object, code); + } + code->set_can_have_weak_objects(true); +} + +} // namespace + + OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { DCHECK(last_status() == SUCCEEDED); // TODO(turbofan): Currently everything is done in the first phase. @@ -552,6 +607,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { if (info()->is_deoptimization_enabled()) { info()->parse_info()->context()->native_context()->AddOptimizedCode( *info()->code()); + RegisterWeakObjectsInOptimizedCode(info()->code()); } RecordOptimizationStats(); return last_status(); @@ -576,6 +632,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { } return SetLastStatus(BAILED_OUT); } + RegisterWeakObjectsInOptimizedCode(optimized_code); info()->SetCode(optimized_code); } RecordOptimizationStats(); diff --git a/src/crankshaft/lithium.cc b/src/crankshaft/lithium.cc index 0a940d5b16..82ad6962be 100644 --- a/src/crankshaft/lithium.cc +++ b/src/crankshaft/lithium.cc @@ -406,53 +406,6 @@ Representation LChunk::LookupLiteralRepresentation( } -static void AddWeakObjectToCodeDependency(Isolate* isolate, - Handle object, - Handle code) { - Handle cell = Code::WeakCellFor(code); - Heap* heap = isolate->heap(); - Handle dep(heap->LookupWeakObjectToCodeDependency(object)); - dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); - heap->AddWeakObjectToCodeDependency(object, dep); -} - - -void LChunk::RegisterWeakObjectsInOptimizedCode(Handle code) const { - DCHECK(code->is_optimized_code()); - ZoneList > maps(1, zone()); - ZoneList > objects(1, zone()); - int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | - RelocInfo::ModeMask(RelocInfo::CELL); - for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { - RelocInfo::Mode mode = it.rinfo()->rmode(); - if (mode == RelocInfo::CELL && - code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) { - objects.Add(Handle(it.rinfo()->target_cell()), zone()); - } else if (mode == RelocInfo::EMBEDDED_OBJECT && - code->IsWeakObjectInOptimizedCode(it.rinfo()->target_object())) { - if (it.rinfo()->target_object()->IsMap()) { - Handle map(Map::cast(it.rinfo()->target_object())); - maps.Add(map, zone()); - } else { - Handle object( - HeapObject::cast(it.rinfo()->target_object())); - objects.Add(object, zone()); - } - } - } - for (int i = 0; i < maps.length(); i++) { - if (maps.at(i)->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) { - isolate()->heap()->AddRetainedMap(maps.at(i)); - } - Map::AddDependentCode(maps.at(i), DependentCode::kWeakCodeGroup, code); - } - for (int i = 0; i < objects.length(); i++) { - AddWeakObjectToCodeDependency(isolate(), objects.at(i), code); - } - code->set_can_have_weak_objects(true); -} - - void LChunk::CommitDependencies(Handle code) const { if (!code->is_optimized_code()) return; HandleScope scope(isolate()); @@ -470,7 +423,6 @@ void LChunk::CommitDependencies(Handle code) const { } info_->dependencies()->Commit(code); - RegisterWeakObjectsInOptimizedCode(code); } diff --git a/src/crankshaft/lithium.h b/src/crankshaft/lithium.h index 126517e2eb..10e980e983 100644 --- a/src/crankshaft/lithium.h +++ b/src/crankshaft/lithium.h @@ -690,7 +690,6 @@ class LChunk : public ZoneObject { int spill_slot_count_; private: - void RegisterWeakObjectsInOptimizedCode(Handle code) const; void CommitDependencies(Handle code) const; CompilationInfo* info_; diff --git a/src/objects-inl.h b/src/objects-inl.h index f853c3a437..4c98296d8a 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -5238,8 +5238,6 @@ Object* Code::GetObjectFromEntryAddress(Address location_of_address) { bool Code::CanContainWeakObjects() { - // is_turbofanned() implies !can_have_weak_objects(). - DCHECK(!is_optimized_code() || !is_turbofanned() || !can_have_weak_objects()); return is_optimized_code() && can_have_weak_objects(); } diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 7abc57b925..804d9fb748 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -121,10 +121,13 @@ # optimized and hence scripts don't "return" the correct value. Fix this. 'test-compiler/CompileFunctionInContext*': [PASS, NO_VARIANTS], - # TurboFan doesn't support allocation sites currently. - 'test-heap/CellsInOptimizedCodeAreWeak': [PASS, NO_VARIANTS], - 'test-heap/EnsureAllocationSiteDependentCodesProcessed': [PASS, NO_VARIANTS], + # TODO(bmeurer): TurboFan embeds strong references to all kinds of objects + # via deoptimization data (Crankshaft also does this, but lack proper test + # coverage). 'test-heap/ObjectsInOptimizedCodeAreWeak': [PASS, NO_VARIANTS], + + # TurboFan doesn't support allocation sites currently. + 'test-heap/EnsureAllocationSiteDependentCodesProcessed': [PASS, NO_VARIANTS], 'test-heap/OptimizedPretenuringAllocationFolding': [PASS, NO_VARIANTS], 'test-heap/OptimizedPretenuringdoubleArrayLiterals': [PASS, NO_VARIANTS], 'test-heap/OptimizedPretenuringDoubleArrayProperties': [PASS, NO_VARIANTS], diff --git a/test/cctest/heap/test-heap.cc b/test/cctest/heap/test-heap.cc index a4cbed3d95..94dd1bb774 100644 --- a/test/cctest/heap/test-heap.cc +++ b/test/cctest/heap/test-heap.cc @@ -4766,17 +4766,19 @@ TEST(CellsInOptimizedCodeAreWeak) { LocalContext context; HandleScope scope(heap->isolate()); - CompileRun("bar = (function() {" - " function bar() {" - " return foo(1);" - " };" - " var foo = function(x) { with (x) { return 1 + x; } };" - " bar(foo);" - " bar(foo);" - " bar(foo);" - " %OptimizeFunctionOnNextCall(bar);" - " bar(foo);" - " return bar;})();"); + CompileRun( + "bar = (function() {" + " function bar() {" + " return foo(1);" + " };" + " var foo = function(x) { with (x) { return 1 + x; } };" + " %NeverOptimizeFunction(foo);" + " bar(foo);" + " bar(foo);" + " bar(foo);" + " %OptimizeFunctionOnNextCall(bar);" + " bar(foo);" + " return bar;})();"); Handle bar = Handle::cast(v8::Utils::OpenHandle( *v8::Local::Cast(CcTest::global() @@ -4809,15 +4811,17 @@ TEST(ObjectsInOptimizedCodeAreWeak) { LocalContext context; HandleScope scope(heap->isolate()); - CompileRun("function bar() {" - " return foo(1);" - "};" - "function foo(x) { with (x) { return 1 + x; } };" - "bar();" - "bar();" - "bar();" - "%OptimizeFunctionOnNextCall(bar);" - "bar();"); + CompileRun( + "function bar() {" + " return foo(1);" + "};" + "function foo(x) { with (x) { return 1 + x; } };" + "%NeverOptimizeFunction(foo);" + "bar();" + "bar();" + "bar();" + "%OptimizeFunctionOnNextCall(bar);" + "bar();"); Handle bar = Handle::cast(v8::Utils::OpenHandle( *v8::Local::Cast(CcTest::global()