diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 3b5002b7ff..800a09dd22 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -2043,8 +2043,13 @@ void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver, HValue* receiver_map = AddLoadMap(receiver, nullptr); HValue* start = keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); - HValue* array_map = Add(array, start, nullptr, FAST_ELEMENTS, + HValue* weak_cell = Add(array, start, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); + // Load the weak cell value. It may be Smi(0), or a map. Compare nonetheless + // against the receiver_map. + HValue* array_map = Add(weak_cell, nullptr, + HObjectAccess::ForWeakCellValue()); + IfBuilder if_correct_map(this); if_correct_map.If(receiver_map, array_map); if_correct_map.Then(); @@ -2059,8 +2064,10 @@ void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver, start = keyed_load ? constant_three : constant_two; HValue* key = builder.BeginBody(start, length, Token::LT); { - HValue* array_map = Add(array, key, nullptr, FAST_ELEMENTS, + HValue* weak_cell = Add(array, key, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); + HValue* array_map = Add( + weak_cell, nullptr, HObjectAccess::ForWeakCellValue()); IfBuilder if_correct_poly_map(this); if_correct_poly_map.If(receiver_map, array_map); diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc index 45028b8787..c51d9877f1 100644 --- a/src/type-feedback-vector.cc +++ b/src/type-feedback-vector.cc @@ -223,12 +223,13 @@ Handle FeedbackNexus::EnsureArrayOfSize(int length) { void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types, CodeHandleList* handlers) { Isolate* isolate = GetIsolate(); - FixedArray* array = FixedArray::cast(GetFeedback()); + Handle array = handle(FixedArray::cast(GetFeedback()), isolate); int receiver_count = types->length(); for (int current = 0; current < receiver_count; ++current) { Handle type = types->at(current); Handle map = IC::TypeToMap(*type, isolate); - array->set(start_index + (current * 2), *map); + Handle cell = Map::WeakCellForMap(map); + array->set(start_index + (current * 2), *cell); array->set(start_index + (current * 2 + 1), *handlers->at(current)); } } @@ -244,6 +245,8 @@ InlineCacheState LoadICNexus::StateFromFeedback() const { } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) { return PREMONOMORPHIC; } else if (feedback->IsFixedArray()) { + // Determine state purely by our structure, don't check if the maps are + // cleared. FixedArray* array = FixedArray::cast(feedback); int length = array->length(); DCHECK(length >= 2); @@ -264,6 +267,8 @@ InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { } else if (feedback == *vector()->GenericSentinel(isolate)) { return GENERIC; } else if (feedback->IsFixedArray()) { + // Determine state purely by our structure, don't check if the maps are + // cleared. FixedArray* array = FixedArray::cast(feedback); int length = array->length(); DCHECK(length >= 3); @@ -344,7 +349,8 @@ void LoadICNexus::ConfigureMonomorphic(Handle type, Handle handler) { Handle array = EnsureArrayOfSize(2); Handle receiver_map = IC::TypeToMap(*type, GetIsolate()); - array->set(0, *receiver_map); + Handle cell = Map::WeakCellForMap(receiver_map); + array->set(0, *cell); array->set(1, *handler); } @@ -359,7 +365,8 @@ void KeyedLoadICNexus::ConfigureMonomorphic(Handle name, } else { array->set(0, *name); } - array->set(1, *receiver_map); + Handle cell = Map::WeakCellForMap(receiver_map); + array->set(1, *cell); array->set(2, *handler); } @@ -390,15 +397,20 @@ int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { Isolate* isolate = GetIsolate(); Object* feedback = GetFeedback(); if (feedback->IsFixedArray()) { + int found = 0; FixedArray* array = FixedArray::cast(feedback); // The array should be of the form [], then // [map, handler, map, handler, ... ] DCHECK(array->length() >= (2 + start_index)); for (int i = start_index; i < array->length(); i += 2) { - Map* map = Map::cast(array->get(i)); - maps->Add(handle(map, isolate)); + WeakCell* cell = WeakCell::cast(array->get(i)); + if (!cell->cleared()) { + Map* map = Map::cast(cell->value()); + maps->Add(handle(map, isolate)); + found++; + } } - return (array->length() - start_index) / 2; + return found; } return 0; @@ -411,11 +423,14 @@ MaybeHandle FeedbackNexus::FindHandlerForMap(int start_index, if (feedback->IsFixedArray()) { FixedArray* array = FixedArray::cast(feedback); for (int i = start_index; i < array->length(); i += 2) { - Map* array_map = Map::cast(array->get(i)); - if (array_map == *map) { - Code* code = Code::cast(array->get(i + 1)); - DCHECK(code->kind() == Code::HANDLER); - return handle(code); + WeakCell* cell = WeakCell::cast(array->get(i)); + if (!cell->cleared()) { + Map* array_map = Map::cast(cell->value()); + if (array_map == *map) { + Code* code = Code::cast(array->get(i + 1)); + DCHECK(code->kind() == Code::HANDLER); + return handle(code); + } } } } @@ -431,13 +446,17 @@ bool FeedbackNexus::FindHandlers(int start_index, CodeHandleList* code_list, if (feedback->IsFixedArray()) { FixedArray* array = FixedArray::cast(feedback); // The array should be of the form [], then - // [map, handler, map, handler, ... ] + // [map, handler, map, handler, ... ]. Be sure to skip handlers whose maps + // have been cleared. DCHECK(array->length() >= (2 + start_index)); for (int i = start_index; i < array->length(); i += 2) { - Code* code = Code::cast(array->get(i + 1)); - DCHECK(code->kind() == Code::HANDLER); - code_list->Add(handle(code)); - count++; + WeakCell* cell = WeakCell::cast(array->get(i)); + if (!cell->cleared()) { + Code* code = Code::cast(array->get(i + 1)); + DCHECK(code->kind() == Code::HANDLER); + code_list->Add(handle(code)); + count++; + } } } return count == length; diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 52d1dbaf5c..f1ada2b3ca 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -3407,8 +3407,6 @@ static void CheckVectorICCleared(Handle f, int ic_slot_index) { TEST(IncrementalMarkingPreservesMonomorphicIC) { if (i::FLAG_always_opt) return; - // TODO(mvstanton): vector-ics need to treat maps weakly. - if (i::FLAG_vector_ics) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3806,8 +3804,6 @@ TEST(Regress169209) { i::FLAG_stress_compaction = false; i::FLAG_allow_natives_syntax = true; i::FLAG_flush_code_incrementally = true; - // TODO(mvstanton): vector ics need weak support. - if (i::FLAG_vector_ics) return; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -4161,8 +4157,6 @@ static int AllocationSitesCount(Heap* heap) { TEST(EnsureAllocationSiteDependentCodesProcessed) { - // TODO(mvstanton): vector ics need weak support! - if (FLAG_vector_ics) return; if (i::FLAG_always_opt || !i::FLAG_crankshaft) return; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); @@ -4211,10 +4205,6 @@ TEST(EnsureAllocationSiteDependentCodesProcessed) { heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); } - // TODO(mvstanton): this test fails when FLAG_vector_ics is true because - // monomorphic load ics are preserved, but also strongly walked. They - // end up keeping function bar alive. - // The site still exists because of our global handle, but the code is no // longer referred to by dependent_code(). DependentCode::GroupStartIndexes starts(site->dependent_code()); @@ -4225,8 +4215,6 @@ TEST(EnsureAllocationSiteDependentCodesProcessed) { TEST(CellsInOptimizedCodeAreWeak) { if (i::FLAG_always_opt || !i::FLAG_crankshaft) return; - // TODO(mvstanton): vector-ics need to treat maps weakly. - if (i::FLAG_vector_ics) return; i::FLAG_weak_embedded_objects_in_optimized_code = true; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); @@ -4269,8 +4257,6 @@ TEST(CellsInOptimizedCodeAreWeak) { TEST(ObjectsInOptimizedCodeAreWeak) { - // TODO(mvstanton): vector ics need weak support! - if (FLAG_vector_ics) return; if (i::FLAG_always_opt || !i::FLAG_crankshaft) return; i::FLAG_weak_embedded_objects_in_optimized_code = true; i::FLAG_allow_natives_syntax = true; @@ -4314,8 +4300,6 @@ TEST(ObjectsInOptimizedCodeAreWeak) { TEST(NoWeakHashTableLeakWithIncrementalMarking) { if (i::FLAG_always_opt || !i::FLAG_crankshaft) return; if (!i::FLAG_incremental_marking) return; - // TODO(mvstanton): vector ics need weak support. - if (FLAG_vector_ics) return; i::FLAG_weak_embedded_objects_in_optimized_code = true; i::FLAG_allow_natives_syntax = true; i::FLAG_compilation_cache = false; @@ -4487,8 +4471,6 @@ void CheckWeakness(const char* source) { // Each of the following "weak IC" tests creates an IC that embeds a map with // the prototype pointing to _proto_ and checks that the _proto_ dies on GC. TEST(WeakMapInMonomorphicLoadIC) { - // TODO(mvstanton): vector ics need weak support! - if (FLAG_vector_ics) return; CheckWeakness("function loadIC(obj) {" " return obj.name;" "}" @@ -4504,8 +4486,6 @@ TEST(WeakMapInMonomorphicLoadIC) { TEST(WeakMapInPolymorphicLoadIC) { - // TODO(mvstanton): vector-ics need to treat maps weakly. - if (i::FLAG_vector_ics) return; CheckWeakness( "function loadIC(obj) {" " return obj.name;" @@ -4525,8 +4505,6 @@ TEST(WeakMapInPolymorphicLoadIC) { TEST(WeakMapInMonomorphicKeyedLoadIC) { - // TODO(mvstanton): vector ics need weak support! - if (FLAG_vector_ics) return; CheckWeakness("function keyedLoadIC(obj, field) {" " return obj[field];" "}"