Vector-based ICs also need to hold maps weakly.
authormvstanton <mvstanton@chromium.org>
Fri, 19 Dec 2014 16:53:41 +0000 (08:53 -0800)
committerCommit bot <commit-bot@chromium.org>
Fri, 19 Dec 2014 16:53:49 +0000 (16:53 +0000)
Regular ICs in MONOMORPHIC and POLYMORPHIC state now hold onto maps with
WeakCells. Vector-based ICs should do the same.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/815953002

Cr-Commit-Position: refs/heads/master@{#25907}

src/code-stubs-hydrogen.cc
src/type-feedback-vector.cc
test/cctest/test-heap.cc

index 3b5002b..800a09d 100644 (file)
@@ -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<HLoadKeyed>(array, start, nullptr, FAST_ELEMENTS,
+    HValue* weak_cell = Add<HLoadKeyed>(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<HLoadNamedField>(weak_cell, nullptr,
+                                             HObjectAccess::ForWeakCellValue());
+
     IfBuilder if_correct_map(this);
     if_correct_map.If<HCompareObjectEqAndBranch>(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<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS,
+        HValue* weak_cell = Add<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS,
                                             ALLOW_RETURN_HOLE);
+        HValue* array_map = Add<HLoadNamedField>(
+            weak_cell, nullptr, HObjectAccess::ForWeakCellValue());
         IfBuilder if_correct_poly_map(this);
         if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map,
                                                           array_map);
index 45028b8..c51d987 100644 (file)
@@ -223,12 +223,13 @@ Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
 void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types,
                                     CodeHandleList* handlers) {
   Isolate* isolate = GetIsolate();
-  FixedArray* array = FixedArray::cast(GetFeedback());
+  Handle<FixedArray> array = handle(FixedArray::cast(GetFeedback()), isolate);
   int receiver_count = types->length();
   for (int current = 0; current < receiver_count; ++current) {
     Handle<HeapType> type = types->at(current);
     Handle<Map> map = IC::TypeToMap(*type, isolate);
-    array->set(start_index + (current * 2), *map);
+    Handle<WeakCell> 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<HeapType> type,
                                        Handle<Code> handler) {
   Handle<FixedArray> array = EnsureArrayOfSize(2);
   Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
-  array->set(0, *receiver_map);
+  Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+  array->set(0, *cell);
   array->set(1, *handler);
 }
 
@@ -359,7 +365,8 @@ void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
   } else {
     array->set(0, *name);
   }
-  array->set(1, *receiver_map);
+  Handle<WeakCell> 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 [<optional name>], 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<Code> 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 [<optional name>], 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;
index 52d1dba..f1ada2b 100644 (file)
@@ -3407,8 +3407,6 @@ static void CheckVectorICCleared(Handle<JSFunction> 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];"
                 "}"