Reviewers: Toon Verwaest,

Description:
Preprocess structured stack trace on GC to get rid of code reference.

[email protected]
BUG=v8:2340
LOG=N

Please review this at https://codereview.chromium.org/1103843002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+75, -5 lines):
  M src/factory.h
  M src/heap/heap.h
  M src/heap/heap.cc
  M src/isolate.cc
  M src/messages.js
  M src/objects.h
  M src/objects.cc
  M src/objects-inl.h
  M test/cctest/test-heap.cc


Index: src/factory.h
diff --git a/src/factory.h b/src/factory.h
index 72991d9bf0ca7ef405c170a6f19029a5a2f3305f..0ab312b2b7e1b283a307a9070823725fcb888565 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -644,6 +644,10 @@ class Factory final {
     isolate()->heap()->set_string_table(*table);
   }

+  inline void set_weak_stack_trace_list(Handle<WeakFixedArray> list) {
+    isolate()->heap()->set_weak_stack_trace_list(*list);
+  }
+
   Handle<String> hidden_string() {
     return Handle<String>(&isolate()->heap()->hidden_string_);
   }
Index: src/heap/heap.cc
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 985d1f678862d87aa0c283aade75e79b3c8b0936..e276f570c36710470b577be1e65d02bcf64c3541 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -408,6 +408,8 @@ void Heap::GarbageCollectionPrologue() {
 #endif
   }

+  PreprocessStackTraces();
+
   // Reset GC statistics.
   promoted_objects_size_ = 0;
   previous_semi_space_copied_object_size_ = semi_space_copied_object_size_;
@@ -706,6 +708,26 @@ void Heap::GarbageCollectionEpilogue() {
 }


+void Heap::PreprocessStackTraces() {
+  if (!weak_stack_trace_list()->IsWeakFixedArray()) return;
+  WeakFixedArray* array = WeakFixedArray::cast(weak_stack_trace_list());
+  int length = array->Length();
+  for (int i = 0; i < length; i++) {
+    if (array->IsEmptySlot(i)) continue;
+    FixedArray* elements = FixedArray::cast(array->Get(i));
+    for (int i = 1; i < elements->length(); i += 4) {
+      Code* code = Code::cast(elements->get(i + 2));
+      int offset = Smi::cast(elements->get(i + 3))->value();
+      Address pc = code->address() + offset;
+      int pos = code->SourcePosition(pc);
+      elements->set(i + 2, Smi::FromInt(pos));
+    }
+    array->Clear(i);
+  }
+  array->Compact();
+}
+
+
 void Heap::HandleGCRequest() {
   if (incremental_marking()->request_type() ==
       IncrementalMarking::COMPLETE_MARKING) {
@@ -3082,6 +3104,8 @@ void Heap::CreateInitialObjects() {
   cell->set_value(Smi::FromInt(1));
   set_array_protector(*cell);

+  set_weak_stack_trace_list(Smi::FromInt(0));
+
   set_allocation_sites_scratchpad(
       *factory->NewFixedArray(kAllocationSiteScratchpadSize, TENURED));
   InitializeAllocationSitesScratchpad();
@@ -3118,6 +3142,7 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
     case kDetachedContextsRootIndex:
     case kWeakObjectToCodeTableRootIndex:
     case kRetainedMapsRootIndex:
+    case kWeakStackTraceListRootIndex:
 // Smi values
 #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
       SMI_ROOT_LIST(SMI_ENTRY)
Index: src/heap/heap.h
diff --git a/src/heap/heap.h b/src/heap/heap.h
index dcf7bdea0ac812972304bd382d52b0a1f4c5eff2..887d9c0cebdb8fdc120f2d6bf6b8aa6080576c5c 100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -186,7 +186,8 @@ namespace internal {
V(FixedArray, detached_contexts, DetachedContexts) \ V(ArrayList, retained_maps, RetainedMaps) \ V(WeakHashTable, weak_object_to_code_table, WeakObjectToCodeTable) \
-  V(PropertyCell, array_protector, ArrayProtector)
+ V(PropertyCell, array_protector, ArrayProtector) \
+  V(Object, weak_stack_trace_list, WeakStackTraceList)

 // Entries in this list are limited to Smis and are not visited during GC.
#define SMI_ROOT_LIST(V) \
@@ -1742,6 +1743,8 @@ class Heap {
   void GarbageCollectionPrologue();
   void GarbageCollectionEpilogue();

+  void PreprocessStackTraces();
+
   // Pretenuring decisions are made based on feedback collected during new
// space evacuation. Note that between feedback collection and calling this
   // method object in old space must not move.
Index: src/isolate.cc
diff --git a/src/isolate.cc b/src/isolate.cc
index 5427a8c319d59369dd8f6e5fbde3aea5789e1d43..90559b341bf8112b6500dbe4093e9225c5a57494 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -409,6 +409,10 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
   elements->set(0, Smi::FromInt(sloppy_frames));
   Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
   result->set_length(Smi::FromInt(cursor));
+  // Queue this structured stack trace for preprocessing on GC.
+  Handle<WeakFixedArray> new_weak_list =
+      WeakFixedArray::Add(factory()->weak_stack_trace_list(), elements);
+  factory()->set_weak_stack_trace_list(new_weak_list);
   return result;
 }

Index: src/messages.js
diff --git a/src/messages.js b/src/messages.js
index 0e48ae60bd1fa360278ea16fa78a142b37fb6309..c600eec4ae726b6cba7aba8a6f9b9b65b85bed23 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -1016,7 +1016,7 @@ function GetStackFrames(raw_stack) {
     var fun = raw_stack[i + 1];
     var code = raw_stack[i + 2];
     var pc = raw_stack[i + 3];
-    var pos = %FunctionGetPositionForOffset(code, pc);
+ var pos = %_IsSmi(code) ? code : %FunctionGetPositionForOffset(code, pc);
     sloppy_frames--;
     frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
   }
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 2e77f92927613732b2a1579824f27319330ee345..b1df7fc330523c788a437bcb5f794d5592e7dd13 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2356,7 +2356,7 @@ bool WeakFixedArray::IsEmptySlot(int index) const {
 }


-void WeakFixedArray::clear(int index) {
+void WeakFixedArray::Clear(int index) {
   FixedArray::cast(this)->set(index + kFirstIndex, Smi::FromInt(0));
 }

Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index f3733295c4dc1baf9d27330aa5a4200a3a3b999b..93dd606c10634879c78dc67f68fb9f92a7cbb281 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -8320,7 +8320,7 @@ void WeakFixedArray::Remove(Handle<HeapObject> value) {
   int first_index = last_used_index();
   for (int i = first_index;;) {
     if (Get(i) == *value) {
-      clear(i);
+      Clear(i);
// Users of WeakFixedArray should make sure that there are no duplicates,
       // they can use Add(..., kAddIfNotFound) if necessary.
       return;
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 68db075981513de26558e03cc12017748c9d32f4..459975b5c0614d485499291c3ac72f162f250a28 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2628,8 +2628,10 @@ class WeakFixedArray : public FixedArray {
   void Compact();

   inline Object* Get(int index) const;
+  inline void Clear(int index);
   inline int Length() const;

+  inline bool IsEmptySlot(int index) const;
   static Object* Empty() { return Smi::FromInt(0); }

   DECLARE_CAST(WeakFixedArray)
@@ -2644,7 +2646,6 @@ class WeakFixedArray : public FixedArray {
   static void Set(Handle<WeakFixedArray> array, int index,
                   Handle<HeapObject> value);
   inline void clear(int index);
-  inline bool IsEmptySlot(int index) const;

   inline int last_used_index() const;
   inline void set_last_used_index(int index);
Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 8858a82d9adf7f838a0add8538918278d1ba7748..a156e97410c44187abdf4328ba3f29575b9d4714 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -5369,3 +5369,36 @@ TEST(Regress472513) {
   TestRightTrimFixedTypedArray(i::kExternalUint16Array, 8 - 1, 3);
   TestRightTrimFixedTypedArray(i::kExternalUint32Array, 4, 3);
 }
+
+
+TEST(PreprocessStackTrace) {
+  // Do not automatically trigger early GC.
+  FLAG_gc_interval = -1;
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  v8::TryCatch try_catch;
+  CompileRun("throw new Error();");
+  CHECK(try_catch.HasCaught());
+  Isolate* isolate = CcTest::i_isolate();
+  Handle<Object> exception = v8::Utils::OpenHandle(*try_catch.Exception());
+  Handle<Name> key = isolate->factory()->stack_trace_symbol();
+  Handle<Object> stack_trace =
+      JSObject::GetProperty(exception, key).ToHandleChecked();
+  Handle<Object> code =
+      Object::GetElement(isolate, stack_trace, 3).ToHandleChecked();
+  CHECK(code->IsCode());
+
+  isolate->heap()->CollectAllAvailableGarbage("stack trace preprocessing");
+
+  Handle<Object> pos =
+      Object::GetElement(isolate, stack_trace, 3).ToHandleChecked();
+  CHECK(pos->IsSmi());
+
+  Handle<JSArray> stack_trace_array = Handle<JSArray>::cast(stack_trace);
+  int array_length = Smi::cast(stack_trace_array->length())->value();
+  for (int i = 0; i < array_length; i++) {
+    Handle<Object> element =
+        Object::GetElement(isolate, stack_trace, i).ToHandleChecked();
+    CHECK(!element->IsCode());
+  }
+}


--
--
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/d/optout.

Reply via email to