Revision: 18616
Author:   [email protected]
Date:     Wed Jan 15 11:42:19 2014 UTC
Log:      Make cells pointing to JSObjects weak in optimized code.

This is done similar to weak embedded objects in optimized code (r17102). The reference from optimized code to a cell is treated weakly in marking visitors
if the cell points to a JSObject. After marking we iterate over all cells
embedded in optimized code. If a cell is not marked but its value is marked,
then we revive the cell by marking it. Otherwise, the cell value is dead, so
we mark the code for deoptimization.

BUG=v8:2073
TEST=cctest/test-heap/CellsInOptimizedCodeAreWeak
LOG=Y
[email protected], [email protected]

Review URL: https://codereview.chromium.org/117483002
http://code.google.com/p/v8/source/detail?r=18616

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/lithium-codegen.cc
 /branches/bleeding_edge/src/mark-compact.cc
 /branches/bleeding_edge/src/objects-visiting-inl.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/test/cctest/test-heap.cc
 /branches/bleeding_edge/tools/v8heapconst.py

=======================================
--- /branches/bleeding_edge/include/v8.h        Mon Jan 13 12:03:31 2014 UTC
+++ /branches/bleeding_edge/include/v8.h        Wed Jan 15 11:42:19 2014 UTC
@@ -5398,7 +5398,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 135;
+  static const int kEmptyStringRootIndex = 136;

   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
=======================================
--- /branches/bleeding_edge/src/heap.cc Mon Jan 13 10:57:49 2014 UTC
+++ /branches/bleeding_edge/src/heap.cc Wed Jan 15 11:42:19 2014 UTC
@@ -3399,6 +3399,11 @@
   }
   set_natives_source_cache(FixedArray::cast(obj));

+  { MaybeObject* maybe_obj = AllocateCell(undefined_value());
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_undefined_cell(Cell::cast(obj));
+
   // Allocate object to hold object observation state.
{ MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     if (!maybe_obj->ToObject(&obj)) return false;
=======================================
--- /branches/bleeding_edge/src/heap.h  Mon Jan 13 10:57:49 2014 UTC
+++ /branches/bleeding_edge/src/heap.h  Wed Jan 15 11:42:19 2014 UTC
@@ -185,6 +185,7 @@
V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset) \ V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset) \ V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset) \ + V(Cell, undefined_cell, UndefineCell) \ V(JSObject, observation_state, ObservationState) \ V(Map, external_map, ExternalMap) \ V(Symbol, frozen_symbol, FrozenSymbol) \
=======================================
--- /branches/bleeding_edge/src/lithium-codegen.cc Tue Dec 3 12:32:35 2013 UTC +++ /branches/bleeding_edge/src/lithium-codegen.cc Wed Jan 15 11:42:19 2014 UTC
@@ -150,15 +150,26 @@
void LCodeGenBase::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
   ZoneList<Handle<Map> > maps(1, zone());
   ZoneList<Handle<JSObject> > objects(1, zone());
-  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
+  ZoneList<Handle<Cell> > cells(1, zone());
+  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
+                  RelocInfo::ModeMask(RelocInfo::CELL);
   for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
- if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (mode == RelocInfo::CELL &&
+ Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_cell())) {
+      Handle<Cell> cell(it.rinfo()->target_cell());
+      cells.Add(cell, zone());
+    } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
+ Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) {
       if (it.rinfo()->target_object()->IsMap()) {
         Handle<Map> map(Map::cast(it.rinfo()->target_object()));
         maps.Add(map, zone());
       } else if (it.rinfo()->target_object()->IsJSObject()) {
Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object()));
         objects.Add(object, zone());
+      } else if (it.rinfo()->target_object()->IsCell()) {
+        Handle<Cell> cell(Cell::cast(it.rinfo()->target_object()));
+        cells.Add(cell, zone());
       }
     }
   }
@@ -174,6 +185,9 @@
   for (int i = 0; i < objects.length(); i++) {
     AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code);
   }
+  for (int i = 0; i < cells.length(); i++) {
+    AddWeakObjectToCodeDependency(isolate()->heap(), cells.at(i), code);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Tue Jan 14 09:57:05 2014 UTC
+++ /branches/bleeding_edge/src/mark-compact.cc Wed Jan 15 11:42:19 2014 UTC
@@ -97,6 +97,14 @@
       VisitPointer(&p);
     }
   }
+
+  void VisitCell(RelocInfo* rinfo) {
+    Code* code = rinfo->host();
+    ASSERT(rinfo->rmode() == RelocInfo::CELL);
+    if (!Code::IsWeakEmbeddedObject(code->kind(), rinfo->target_cell())) {
+      ObjectVisitor::VisitCell(rinfo);
+    }
+  }

  private:
   Heap* heap_;
@@ -2551,6 +2559,16 @@
       if (!table->IsKey(key)) continue;
       uint32_t value_index = table->EntryToValueIndex(i);
       Object* value = table->get(value_index);
+      if (key->IsCell() && !IsMarked(key)) {
+        Cell* cell = Cell::cast(key);
+        Object* object = cell->value();
+        if (IsMarked(object)) {
+          MarkBit mark = Marking::MarkBitFrom(cell);
+          SetMark(cell, mark);
+ Object** value_slot = HeapObject::RawField(cell, Cell::kValueOffset);
+          RecordSlot(value_slot, value_slot, *value_slot);
+        }
+      }
       if (IsMarked(key)) {
         if (!IsMarked(value)) {
           HeapObject* obj = HeapObject::cast(value);
=======================================
--- /branches/bleeding_edge/src/objects-visiting-inl.h Tue Jan 7 15:53:54 2014 UTC +++ /branches/bleeding_edge/src/objects-visiting-inl.h Wed Jan 15 11:42:19 2014 UTC
@@ -261,6 +261,9 @@
   ASSERT(!rinfo->target_object()->IsConsString());
   HeapObject* object = HeapObject::cast(rinfo->target_object());
   heap->mark_compact_collector()->RecordRelocSlot(rinfo, object);
+ // TODO(ulan): It could be better to record slots only for strongly embedded + // objects here and record slots for weakly embedded object during clearing
+  // of non-live references in mark-compact.
   if (!Code::IsWeakEmbeddedObject(rinfo->host()->kind(), object)) {
     StaticVisitor::MarkObject(heap, object);
   }
@@ -272,7 +275,10 @@
     Heap* heap, RelocInfo* rinfo) {
   ASSERT(rinfo->rmode() == RelocInfo::CELL);
   Cell* cell = rinfo->target_cell();
-  StaticVisitor::MarkObject(heap, cell);
+ // No need to record slots because the cell space is not compacted during GC.
+  if (!Code::IsWeakEmbeddedObject(rinfo->host()->kind(), cell)) {
+    StaticVisitor::MarkObject(heap, cell);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/objects.cc      Mon Jan 13 17:11:36 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc      Wed Jan 15 11:42:19 2014 UTC
@@ -10311,11 +10311,15 @@

 void Code::InvalidateEmbeddedObjects() {
   Object* undefined = GetHeap()->undefined_value();
-  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
+  Cell* undefined_cell = GetHeap()->undefined_cell();
+  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
+                  RelocInfo::ModeMask(RelocInfo::CELL);
   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
     RelocInfo::Mode mode = it.rinfo()->rmode();
     if (mode == RelocInfo::EMBEDDED_OBJECT) {
       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
+    } else if (mode == RelocInfo::CELL) {
+      it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
     }
   }
 }
@@ -11277,7 +11281,8 @@
            FLAG_weak_embedded_maps_in_optimized_code;
   }

-  if (object->IsJSObject()) {
+  if (object->IsJSObject() ||
+      (object->IsCell() && Cell::cast(object)->value()->IsJSObject())) {
     return FLAG_weak_embedded_objects_in_optimized_code;
   }

=======================================
--- /branches/bleeding_edge/test/cctest/test-heap.cc Tue Jan 14 16:15:05 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-heap.cc Wed Jan 15 11:42:19 2014 UTC
@@ -3664,3 +3664,87 @@
int index = starts.at(DependentCode::kAllocationSiteTransitionChangedGroup);
   CHECK(!(site->dependent_code()->is_code_at(index)));
 }
+
+
+TEST(CellsInOptimizedCodeAreWeak) {
+  if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
+  i::FLAG_weak_embedded_objects_in_optimized_code = true;
+  i::FLAG_allow_natives_syntax = true;
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  v8::internal::Heap* heap = CcTest::heap();
+
+  if (!isolate->use_crankshaft()) return;
+  HandleScope outer_scope(heap->isolate());
+  Handle<Code> code;
+  {
+    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;})();");
+
+    Handle<JSFunction> bar =
+        v8::Utils::OpenHandle(
+            *v8::Handle<v8::Function>::Cast(
+                CcTest::global()->Get(v8_str("bar"))));
+    code = scope.CloseAndEscape(Handle<Code>(bar->code()));
+  }
+
+  // Now make sure that a gc should get rid of the function
+  for (int i = 0; i < 4; i++) {
+    heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
+  }
+
+  ASSERT(code->marked_for_deoptimization());
+}
+
+
+TEST(ObjectsInOptimizedCodeAreWeak) {
+  if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
+  i::FLAG_weak_embedded_objects_in_optimized_code = true;
+  i::FLAG_allow_natives_syntax = true;
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  v8::internal::Heap* heap = CcTest::heap();
+
+  if (!isolate->use_crankshaft()) return;
+  HandleScope outer_scope(heap->isolate());
+  Handle<Code> code;
+  {
+    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();");
+
+    Handle<JSFunction> bar =
+        v8::Utils::OpenHandle(
+            *v8::Handle<v8::Function>::Cast(
+                CcTest::global()->Get(v8_str("bar"))));
+    code = scope.CloseAndEscape(Handle<Code>(bar->code()));
+  }
+
+  // Now make sure that a gc should get rid of the function
+  for (int i = 0; i < 4; i++) {
+    heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
+  }
+
+  ASSERT(code->marked_for_deoptimization());
+}
=======================================
--- /branches/bleeding_edge/tools/v8heapconst.py Mon Oct 14 13:35:06 2013 UTC +++ /branches/bleeding_edge/tools/v8heapconst.py Wed Jan 15 11:42:19 2014 UTC
@@ -226,32 +226,32 @@
   ("OLD_POINTER_SPACE", 0x09521): "TerminationException",
   ("OLD_POINTER_SPACE", 0x09531): "MessageListeners",
   ("OLD_POINTER_SPACE", 0x0954d): "CodeStubs",
-  ("OLD_POINTER_SPACE", 0x0a9d9): "NonMonomorphicCache",
-  ("OLD_POINTER_SPACE", 0x0afed): "PolymorphicCodeCache",
-  ("OLD_POINTER_SPACE", 0x0aff5): "NativesSourceCache",
-  ("OLD_POINTER_SPACE", 0x0b03d): "EmptyScript",
-  ("OLD_POINTER_SPACE", 0x0b075): "IntrinsicFunctionNames",
-  ("OLD_POINTER_SPACE", 0x0e091): "ObservationState",
-  ("OLD_POINTER_SPACE", 0x0e09d): "FrozenSymbol",
-  ("OLD_POINTER_SPACE", 0x0e0a9): "ElementsTransitionSymbol",
-  ("OLD_POINTER_SPACE", 0x0e0b5): "EmptySlowElementDictionary",
-  ("OLD_POINTER_SPACE", 0x0e251): "ObservedSymbol",
-  ("OLD_POINTER_SPACE", 0x29861): "StringTable",
+  ("OLD_POINTER_SPACE", 0x10485): "NonMonomorphicCache",
+  ("OLD_POINTER_SPACE", 0x10a99): "PolymorphicCodeCache",
+  ("OLD_POINTER_SPACE", 0x10aa1): "NativesSourceCache",
+  ("OLD_POINTER_SPACE", 0x10aed): "EmptyScript",
+  ("OLD_POINTER_SPACE", 0x10b25): "IntrinsicFunctionNames",
+  ("OLD_POINTER_SPACE", 0x13b41): "ObservationState",
+  ("OLD_POINTER_SPACE", 0x13b4d): "FrozenSymbol",
+  ("OLD_POINTER_SPACE", 0x13b5d): "ElementsTransitionSymbol",
+  ("OLD_POINTER_SPACE", 0x13b6d): "EmptySlowElementDictionary",
+  ("OLD_POINTER_SPACE", 0x13d09): "ObservedSymbol",
+  ("OLD_POINTER_SPACE", 0x32325): "StringTable",
   ("OLD_DATA_SPACE", 0x08099): "EmptyDescriptorArray",
   ("OLD_DATA_SPACE", 0x080a1): "EmptyFixedArray",
   ("OLD_DATA_SPACE", 0x080a9): "NanValue",
   ("OLD_DATA_SPACE", 0x08141): "EmptyByteArray",
-  ("OLD_DATA_SPACE", 0x08269): "EmptyExternalByteArray",
-  ("OLD_DATA_SPACE", 0x08275): "EmptyExternalUnsignedByteArray",
-  ("OLD_DATA_SPACE", 0x08281): "EmptyExternalShortArray",
-  ("OLD_DATA_SPACE", 0x0828d): "EmptyExternalUnsignedShortArray",
-  ("OLD_DATA_SPACE", 0x08299): "EmptyExternalIntArray",
-  ("OLD_DATA_SPACE", 0x082a5): "EmptyExternalUnsignedIntArray",
-  ("OLD_DATA_SPACE", 0x082b1): "EmptyExternalFloatArray",
-  ("OLD_DATA_SPACE", 0x082bd): "EmptyExternalDoubleArray",
-  ("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
-  ("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
-  ("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
-  ("CODE_SPACE", 0x111a1): "JsConstructEntryCode",
-  ("CODE_SPACE", 0x18bc1): "JsEntryCode",
+  ("OLD_DATA_SPACE", 0x08279): "EmptyExternalByteArray",
+  ("OLD_DATA_SPACE", 0x08285): "EmptyExternalUnsignedByteArray",
+  ("OLD_DATA_SPACE", 0x08291): "EmptyExternalShortArray",
+  ("OLD_DATA_SPACE", 0x0829d): "EmptyExternalUnsignedShortArray",
+  ("OLD_DATA_SPACE", 0x082a9): "EmptyExternalIntArray",
+  ("OLD_DATA_SPACE", 0x082b5): "EmptyExternalUnsignedIntArray",
+  ("OLD_DATA_SPACE", 0x082c1): "EmptyExternalFloatArray",
+  ("OLD_DATA_SPACE", 0x082cd): "EmptyExternalDoubleArray",
+  ("OLD_DATA_SPACE", 0x082d9): "EmptyExternalPixelArray",
+  ("OLD_DATA_SPACE", 0x082e5): "InfinityValue",
+  ("OLD_DATA_SPACE", 0x082f1): "MinusZeroValue",
+  ("CODE_SPACE", 0x14181): "JsConstructEntryCode",
+  ("CODE_SPACE", 0x15c61): "JsEntryCode",
 }

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to