diff --git a/src/ic/ic.cc b/src/ic/ic.cc index 2ee76374c7..cd8b0835b1 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -832,7 +832,10 @@ bool IC::UpdatePolymorphicIC(Handle name, Handle code) { number_of_types - deprecated_types - (handler_to_overwrite != -1); if (number_of_valid_types >= 4) return false; - if (number_of_types == 0) return false; + if (number_of_types == 0 && state() != MONOMORPHIC && + state() != POLYMORPHIC) { + return false; + } if (UseVector()) { if (!nexus()->FindHandlers(&handlers, types.length())) return false; } else { diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index edb47d2559..bf580ee096 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -4639,6 +4639,94 @@ TEST(WeakMapInMonomorphicCompareNilIC) { } +Handle GetFunctionByName(Isolate* isolate, const char* name) { + Handle str = isolate->factory()->InternalizeUtf8String(name); + Handle obj = + Object::GetProperty(isolate->global_object(), str).ToHandleChecked(); + return Handle::cast(obj); +} + + +void CheckIC(Code* code, Code::Kind kind, InlineCacheState state) { + Code* ic = FindFirstIC(code, kind); + CHECK(ic->is_inline_cache_stub()); + CHECK(ic->ic_state() == state); +} + + +TEST(MonomorphicStaysMonomorphicAfterGC) { + if (FLAG_always_opt) return; + // TODO(mvstanton): vector ics need weak support! + if (FLAG_vector_ics) return; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + v8::HandleScope scope(CcTest::isolate()); + CompileRun( + "function loadIC(obj) {" + " return obj.name;" + "}" + "function testIC() {" + " var proto = {'name' : 'weak'};" + " var obj = Object.create(proto);" + " loadIC(obj);" + " loadIC(obj);" + " loadIC(obj);" + " return proto;" + "};"); + Handle loadIC = GetFunctionByName(isolate, "loadIC"); + { + v8::HandleScope scope(CcTest::isolate()); + CompileRun("(testIC())"); + } + heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + CheckIC(loadIC->code(), Code::LOAD_IC, MONOMORPHIC); + { + v8::HandleScope scope(CcTest::isolate()); + CompileRun("(testIC())"); + } + CheckIC(loadIC->code(), Code::LOAD_IC, MONOMORPHIC); +} + + +TEST(PolymorphicStaysPolymorphicAfterGC) { + if (FLAG_always_opt) return; + // TODO(mvstanton): vector ics need weak support! + if (FLAG_vector_ics) return; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + v8::HandleScope scope(CcTest::isolate()); + CompileRun( + "function loadIC(obj) {" + " return obj.name;" + "}" + "function testIC() {" + " var proto = {'name' : 'weak'};" + " var obj = Object.create(proto);" + " loadIC(obj);" + " loadIC(obj);" + " loadIC(obj);" + " var poly = Object.create(proto);" + " poly.x = true;" + " loadIC(poly);" + " return proto;" + "};"); + Handle loadIC = GetFunctionByName(isolate, "loadIC"); + { + v8::HandleScope scope(CcTest::isolate()); + CompileRun("(testIC())"); + } + heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + CheckIC(loadIC->code(), Code::LOAD_IC, POLYMORPHIC); + { + v8::HandleScope scope(CcTest::isolate()); + CompileRun("(testIC())"); + } + CheckIC(loadIC->code(), Code::LOAD_IC, POLYMORPHIC); +} + + TEST(WeakCell) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate();