Make incremental marking clear type feedback cells.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 1 Aug 2012 11:24:14 +0000 (11:24 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 1 Aug 2012 11:24:14 +0000 (11:24 +0000)
This extends the existing clearing of type feedback cells during GC to
incremental marking in order to prevent cross-context retention that
would last until the next non-incremental GC.

R=erik.corry@gmail.com
TEST=cctest/test-heap/IncrementalMarkingClearsTypeFeedbackCells

Review URL: https://chromiumcodereview.appspot.com/10823082

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12245 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/incremental-marking.cc
src/mark-compact.cc
src/objects-visiting-inl.h
src/objects-visiting.h
test/cctest/test-heap.cc

index ebbee25..e3040ee 100644 (file)
@@ -196,12 +196,6 @@ class IncrementalMarkingMarkingVisitor
     MarkObject(heap, target);
   }
 
-  static void VisitCode(Map* map, HeapObject* object) {
-    Heap* heap = map->GetHeap();
-    Code* code = reinterpret_cast<Code*>(object);
-    code->CodeIterateBody<IncrementalMarkingMarkingVisitor>(heap);
-  }
-
   static void VisitJSWeakMap(Map* map, HeapObject* object) {
     Heap* heap = map->GetHeap();
     VisitPointers(heap,
index ccaaab8..0ba8a24 100644 (file)
@@ -1153,15 +1153,6 @@ class MarkCompactMarkingVisitor
     return true;
   }
 
-  static void VisitCode(Map* map, HeapObject* object) {
-    Heap* heap = map->GetHeap();
-    Code* code = reinterpret_cast<Code*>(object);
-    if (FLAG_cleanup_code_caches_at_gc) {
-      code->ClearTypeFeedbackCells(heap);
-    }
-    code->CodeIterateBody<MarkCompactMarkingVisitor>(heap);
-  }
-
   static void VisitJSWeakMap(Map* map, HeapObject* object) {
     MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector();
     JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(object);
index 30a7ad4..80662cc 100644 (file)
@@ -216,6 +216,18 @@ void StaticMarkingVisitor<StaticVisitor>::VisitGlobalContext(
 
 
 template<typename StaticVisitor>
+void StaticMarkingVisitor<StaticVisitor>::VisitCode(
+    Map* map, HeapObject* object) {
+  Heap* heap = map->GetHeap();
+  Code* code = Code::cast(object);
+  if (FLAG_cleanup_code_caches_at_gc) {
+    code->ClearTypeFeedbackCells(heap);
+  }
+  code->CodeIterateBody<StaticVisitor>(heap);
+}
+
+
+template<typename StaticVisitor>
 void StaticMarkingVisitor<StaticVisitor>::VisitJSRegExp(
     Map* map, HeapObject* object) {
   int last_property_offset =
index 7415101..fa81978 100644 (file)
@@ -396,6 +396,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
   static inline void VisitGlobalContext(Map* map, HeapObject* object);
 
  protected:
+  static inline void VisitCode(Map* map, HeapObject* object);
   static inline void VisitJSRegExp(Map* map, HeapObject* object);
 
   class DataObjectVisitor {
index ff7e2e7..94748cb 100644 (file)
@@ -2025,3 +2025,55 @@ TEST(Regress2211) {
     CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize);
   }
 }
+
+
+TEST(IncrementalMarkingClearsTypeFeedbackCells) {
+  if (i::FLAG_always_opt) return;
+  InitializeVM();
+  v8::HandleScope scope;
+  v8::Local<v8::Value> fun1, fun2;
+
+  {
+    LocalContext env;
+    CompileRun("function fun() {};");
+    fun1 = env->Global()->Get(v8_str("fun"));
+  }
+
+  {
+    LocalContext env;
+    CompileRun("function fun() {};");
+    fun2 = env->Global()->Get(v8_str("fun"));
+  }
+
+  // Prepare function f that contains type feedback for closures
+  // originating from two different global contexts.
+  v8::Context::GetCurrent()->Global()->Set(v8_str("fun1"), fun1);
+  v8::Context::GetCurrent()->Global()->Set(v8_str("fun2"), fun2);
+  CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);");
+  Handle<JSFunction> f =
+      v8::Utils::OpenHandle(
+          *v8::Handle<v8::Function>::Cast(
+              v8::Context::GetCurrent()->Global()->Get(v8_str("f"))));
+  Handle<TypeFeedbackCells> cells(TypeFeedbackInfo::cast(
+      f->shared()->code()->type_feedback_info())->type_feedback_cells());
+
+  CHECK_EQ(2, cells->CellCount());
+  CHECK(cells->Cell(0)->value()->IsJSFunction());
+  CHECK(cells->Cell(1)->value()->IsJSFunction());
+
+  // Go through all incremental marking steps in one swoop.
+  IncrementalMarking* marking = HEAP->incremental_marking();
+  CHECK(marking->IsStopped());
+  marking->Start();
+  CHECK(marking->IsMarking());
+  while (!marking->IsComplete()) {
+    marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
+  }
+  CHECK(marking->IsComplete());
+  HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+  CHECK(marking->IsStopped());
+
+  CHECK_EQ(2, cells->CellCount());
+  CHECK(cells->Cell(0)->value()->IsTheHole());
+  CHECK(cells->Cell(1)->value()->IsTheHole());
+}